开发的时候总会遇到一些分割线,可以用一个View或者一个ImageView来绘制一条比较细的分割线,但布局写多了,感觉很麻烦,而且显得代码不优雅,所以一个带有边框的ViewGroup对开发会方便很多。
1、自定义属性,在 attr.xml 文件中写入
2、自定义控件,定义一个 BorderRelativeLayout 继承自 RelativeLayout
package com.tcmain.djim.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.widget.RelativeLayout;
import com.risen.tclibrary.R;
/**
* Created by sgll on 2018/7/17.
* 带边框的RelativeLayout 或 LinearLayout
*/
public class BorderRelativeLayout extends RelativeLayout {
// 默认边框宽度, 1dp
public static final float DEFAULT_STROKE_WIDTH = 1.0f;
//画笔
private Paint mPain;
//边框颜色
private int mPaintColor;
//边框粗细
private float mBorderStrokeWidth;
//底边边线左边断开距离
private int mBorderBottomLeftBreakSize;
//底边边线右边断开距离
private int mBorderBottomRightBreakSize;
//是否需要上边框
private boolean isNeedTopBorder;
//是否需要左右边框
private boolean isNeedLeftAndRightBorder;
//是否需要下边框
private boolean isNeedBottomBorder;
private DisplayMetrics displayMetrics;
public BorderRelativeLayout(Context context) {
this(context, null);
}
public BorderRelativeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BorderRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 将DIP单位默认值转为PX
displayMetrics = context.getResources().getDisplayMetrics();
// 获取自定义属性
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.BorderViewLayout);
mPaintColor = ta.getColor(R.styleable.BorderViewLayout_borderColor, Color.GRAY);
mBorderStrokeWidth = ta.getFloat(R.styleable.BorderViewLayout_borderStrokeWidth, DEFAULT_STROKE_WIDTH);
// mBorderStrokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mBorderStrokeWidth, displayMetrics);
mBorderBottomLeftBreakSize = ta.getDimensionPixelSize(R.styleable.BorderViewLayout_borderBottomLeftBreakSize, 0);
mBorderBottomLeftBreakSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mBorderBottomLeftBreakSize, displayMetrics);
mBorderBottomRightBreakSize = ta.getDimensionPixelSize(R.styleable.BorderViewLayout_borderBottomRightBreakSize, 0);
mBorderBottomRightBreakSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mBorderBottomRightBreakSize, displayMetrics);
isNeedTopBorder = ta.getBoolean(R.styleable.BorderViewLayout_needTopBorder, true);
isNeedLeftAndRightBorder = ta.getBoolean(R.styleable.BorderViewLayout_needLeftAndRigtBorder, false);
isNeedBottomBorder = ta.getBoolean(R.styleable.BorderViewLayout_needBottomBorder, true);
ta.recycle();
init();
}
private void init(){
mPain = new Paint();
mPain.setColor(mPaintColor);
//设置画笔为无锯齿
mPain.setAntiAlias(true);
//线宽
mPain.setStrokeWidth(mBorderStrokeWidth);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
//画4个边
if(isNeedTopBorder){
canvas.drawLine(0, 0, this.getWidth(), 0, mPain);
}
if(isNeedBottomBorder){
canvas.drawLine(mBorderBottomLeftBreakSize, this.getHeight(), this.getWidth() - mBorderBottomRightBreakSize, this.getHeight(), mPain);
}
if(isNeedLeftAndRightBorder){
canvas.drawLine(0, 0, 0, this.getHeight(), mPain);
canvas.drawLine(this.getWidth(), 0, this.getWidth(), this.getHeight(), mPain);
}
}
/**
* 设置边框颜色
* @param color 颜色
*/
public void setBorderColor(int color){
mPain.setColor(color);
invalidate();
}
/**
* 设置边框宽度
* @param size 宽度
*/
public void setBorderStrokeWidth(float size){
mPain.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, displayMetrics));
invalidate();
}
/**
* 设置是否需要顶部边框
* @param needtopborder boolean类型
*/
public void setNeedTopBorder(boolean needtopborder){
isNeedTopBorder = needtopborder;
invalidate();
}
/**
* 设置是否需要底部边框
* @param needbottomborder boolean类型
*/
public void setNeedBottomBorder(boolean needbottomborder){
isNeedBottomBorder = needbottomborder;
invalidate();
}
}
3、在布局中使用
1、带边框的 BorderRelativeLayout 也可使用 ListView 中,如头部带分割线
只需要在适配器中进行判断,就能够添加头部分割线了。在适配器getView部分添加:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
...
// 如果是第一个位置显示顶部边框
BorderRelativeLayout br = (BorderRelativeLayout) convertView.findViewById(R.id.br_ia_detail);
if (0 == position) {
br.setNeedTopBorder(true);
} else {
br.setNeedTopBorder(false);
}
return convertView;
}
2、ListView 中的分割线,也可使用这个代替,只需在 item 布局里使用即可。
使用比较简单,用法也比较多变,如果需要 LinearLayout,只需改变一下继承关系就可以了。
相关文章
Android自定义控件 – 带边框的TextView