展示多个标签,一行满后自动换行,可以设置行间距和标签的左右间距
效果图
布局文件
<com.rsd.library.widget.RFlowLayout
android:layout_width="wrap_content"
app:fTextBg="@drawable/border"
app:fLineSpace="10dp"
app:fTagSpace="10dp"
app:fTextSize="23sp"
android:layout_height="wrap_content"/>
继承viewgroup,重写起onmeasure计算wrap宽高,重写onlayout计算每个子view的位置
首先onMeasure
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width = 0, height = getPaddingTop() + getPaddingBottom();
int lineWidth = getPaddingLeft() + getPaddingRight(), lineHeight = 0;
View child;
int space = 0;
for (int i = 0; i < getChildCount(); i++) {
child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
int cWidth = child.getMeasuredWidth();
int cHeight = child.getMeasuredHeight();
if (lineWidth + cWidth + space > widthSize) {
space = 0;
//如果再加一个标签宽度不够就换行
width = Math.max(lineWidth, cWidth); //总行宽改变
lineWidth = cWidth + getPaddingLeft() + getPaddingRight();//新行宽
height += lineHeight;//总行高增加
if (i != 0) {
cHeight += lineSpace;
}
lineHeight = cHeight; //新行高
} else {
space = tagSpace;
if (i != 0) {
cWidth += tagSpace;
}
lineWidth += cWidth; //行宽增加
lineHeight = Math.max(lineHeight, cHeight); //改变该行高度
}
if (i == getChildCount() - 1) {
width = Math.max(width, lineWidth);
height += lineHeight;
}
}
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
}
setMeasuredDimension(width, height);
}
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left = getPaddingLeft(), top = getPaddingTop();//每个view的左上开始位置
int ml = 0, mt = 0;//每个子view的左上边距,正常是两个space,但第一行和每行第一个为0
int width = getWidth();
int lineHeight = 0;
View child;
for (int i = 0; i < getChildCount(); i++) {
child = getChildAt(i);
if (left + child.getMeasuredWidth() + tagSpace + getPaddingRight() > width) {//换行
left = getPaddingLeft();
ml = 0;//每行第一个没有左边距
top += lineHeight;
lineHeight = child.getMeasuredHeight();
if (i == 0) {
mt = 0;//第一行没有上边据,其余的加上行间距
} else {
mt = lineSpace;
}
lineHeight += mt;
} else {
if (i == 0) {//如果第一个没有左边距
ml = 0;
} else {
ml = tagSpace;
}
lineHeight = Math.max(lineHeight, child.getMeasuredHeight() + mt);
}
child.layout(left + ml, top + mt,
left + ml + child.getMeasuredWidth(),
top + mt + child.getMeasuredHeight());
left += child.getMeasuredWidth() + ml;
}
}
然后就是设置标签内容,点击事件,标签我就是添加了一个个textview
public void setTags(String[] tags) {
removeAllViews();
for (int i = 0; i < tags.length; i++) {
TextView textView = new TextView(getContext());
textView.setTextSize(textSize);
textView.setTextColor(textColor);
textView.setGravity(Gravity.CENTER);
if (textBg != -1) {
textView.setBackgroundResource(textBg);
}
textView.setText(tags[i]);
textView.setTag(i);
textView.setOnClickListener(this);
addView(textView);
}
setSelectIndex(0);
}
//设置选中某个tag
public void setSelectIndex(int index) {
if (index == oldIndex) {
return;
}
//改变上次选中的状态,默认选中是0
TextView view = (TextView) getChildAt(oldIndex);
view.setTextColor(textColor);
if (textBg != -1) {
view.setBackgroundResource(textBg);
}
//当前选中的
view = (TextView) getChildAt(index);
view.setTextColor(selectTextColor);
if (selectTextBg != -1) {
view.setBackgroundResource(selectTextBg);
}
oldIndex = index;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
@Override
public void onClick(View v) {
int position = (int) v.getTag();
if (onItemClickListener != null) {
setSelectIndex(position);
onItemClickListener.onTagClick(position);
}
}
public interface OnItemClickListener {
void onTagClick(int position);
}