自定义View-自动换行的标签控件

时间:2022-02-04 18:35:47

android自定义换行标签:最近项目中需要实现一个功能:

自定义View-自动换行的标签控件

网上有很多可以用的开源控件,我自己也学习写了一个自定义换行标签,让一个View继承ViewGroup,重写onmeasure()和onlayout()方法,核心代码如下自定义View-自动换行的标签控件



    @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//最后测量宽度和高度
int resultWidth = 0;
int resultHeigh = 0;
//临时测量宽度和高度
int linewidth = 0;
int lineHeight = 0;
int childCount = getChildCount();
//测量控件的宽高模式 在之前文章中有讲过这个用法,不懂的可以看下
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);

for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
//测量每一个子view的宽和高
measureChild(childView, widthMeasureSpec, heightMeasureSpec);
//获取测量的高度
int childWidth = childView.getMeasuredWidth();
int childHeight = childView.getMeasuredHeight();
//因为子View可能设置margin,这里要加上margin的距离
MarginLayoutParams mlp = (MarginLayoutParams) childView.getLayoutParams();
//子控件真实宽度和高度
int realwidth = mlp.leftMargin + childWidth + mlp.rightMargin;
int realHight = mlp.topMargin + childHeight + mlp.bottomMargin;

//计算宽度
if (linewidth + realwidth > widthSize) {
//换行
resultWidth = Math.max(linewidth, realwidth);
resultHeigh = resultHeigh + realHight;
//换行后高度和宽度重新计算
linewidth = realwidth;
lineHeight = realHight;
} else {
linewidth = linewidth + realwidth;
lineHeight = Math.max(lineHeight, realHight);
}
}
//保存测量完成后的宽度和高度
setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : resultWidth,
heightMode == MeasureSpec.EXACTLY ? heightSize : resultHeigh);
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//子控件左边距离和上边距离
int childleft = 0;
int childtop = 0;
//为每个孩子布局
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);

int measuredHeight = childView.getMeasuredHeight();
int measuredWidth = childView.getMeasuredWidth();

//因为子View可能设置margin,这里要加上margin的距离
MarginLayoutParams mlp = (MarginLayoutParams) childView.getLayoutParams();
if (childleft + mlp.leftMargin + mlp.rightMargin + measuredWidth > getWidth()) {
//换行上边距离增加,左边距离为0
childtop = childtop + mlp.topMargin + mlp.bottomMargin + measuredHeight;
childleft = 0;
}
    //计算子控件            int left = childleft + mlp.leftMargin;            int top = childtop + mlp.topMargin;            int right = childleft + mlp.leftMargin + mlp.rightMargin + measuredWidth;            int bottom = childtop + mlp.topMargin + mlp.bottomMargin + measuredHeight;
    //布局子控件            childView.layout(left, top, right, bottom);            //不换行左边距离是前面子控件宽度之和 childleft = childleft + mlp.leftMargin + mlp.rightMargin + measuredWidth;        }    }
这样我们基本完成了该控件的绘制,我们通过addview加入子控件,例如:
public void setTextviewRes(List<TextView> textviews) {    //添加文字  //先移除所有的子view  removeAllViews();    for (int i = 0; i < textviews.size(); i++) {        TextView textView = textviews.get(i);        addView(textView);    }    //重新布局  requestLayout();}
我们使用控件,调用控件的settextviewres()方法,以textview为例子,
传入添加好的textview的集合(这里可以任意设置,功能需求是什么就可以按照自己的需求去更改)。
这样就完成自定义换行标签自定义View-自动换行的标签控件