private FlowLayout mFL_FlowLayout;
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(10, 5, 10, 5); if (mFL_FlowLayout != null) { mFL_FlowLayout.removeAllViews(); } for (int i = 0; i < mLocationList.size(); i++) { final String tag = mLocationList.get(i); mTV_viewText = new TextView(this); mTV_viewText.setPadding(28, 10, 28, 10); mTV_viewText.setText(mLocationList.get(i)); mTV_viewText.setMaxEms(10); mTV_viewText.setSingleLine(); mTV_viewText.setBackgroundResource(R.drawable.flowlayout_bg); mTV_viewText.setLayoutParams(layoutParams); mFL_FlowLayout.addView(mTV_viewText, layoutParams); mTV_viewText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); }
<com.haribit.media.utils.FlowLayout
android:id="@+id/flayout_interface"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/tv_hintawake"/>
public class FlowLayout extends ViewGroup { public FlowLayout(Context context) { super(context); } public FlowLayout(Context context, AttributeSet attrs) { super(context, attrs); } public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // super.onMeasure(widthMeasureSpec, heightMeasureSpec); //遍历去调用所有子元素的measure方法(child.getMeasuredHeight()才能获取到值,否则为0) measureChildren(widthMeasureSpec, heightMeasureSpec); int measuredWidth = 0, measuredHeight = 0; int widthSize = MeasureSpec.getSize(widthMeasureSpec); int widtMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); //由于计算子view所占宽度,这里传值需要自身减去PaddingRight宽度,PaddingLeft会在接下来计算子元素位置时加上 Map<String, Integer> compute = compute(widthSize - getPaddingRight()); //EXACTLY模式:对应于给定大小或者match_parent情况 if (widtMode == MeasureSpec.EXACTLY) { measuredWidth = widthSize; //AT_MOS模式:对应wrap-content(需要手动计算大小,否则相当于match_parent) } else if (widtMode == MeasureSpec.AT_MOST) { measuredWidth = compute.get("allChildWidth"); } if (heightMode == MeasureSpec.EXACTLY) { measuredHeight = heightSize; } else if (heightMode == MeasureSpec.AT_MOST) { measuredHeight = compute.get("allChildHeight"); } //设置flow的宽高 setMeasuredDimension(measuredWidth, measuredHeight); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); Rect rect = (Rect) getChildAt(i).getTag(); child.layout(rect.left, rect.top, rect.right, rect.bottom); } } /** * 测量过程 * * @param flowWidth 该view的宽度 * @return 返回子元素总所占宽度和高度(用于计算Flowlayout的AT_MOST模式设置宽高) */ private Map<String, Integer> compute(int flowWidth) { //是否是单行 boolean aRow = true; MarginLayoutParams marginParams;//子元素margin int rowsWidth = getPaddingLeft();//当前行已占宽度(注意需要加上paddingLeft) int columnHeight = getPaddingTop();//当前行顶部已占高度(注意需要加上paddingTop) int rowsMaxHeight = 0;//当前行所有子元素的最大高度(用于换行累加高度) for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); //获取元素测量宽度和高度 int measuredWidth = child.getMeasuredWidth(); int measuredHeight = child.getMeasuredHeight(); //获取元素的margin marginParams = (MarginLayoutParams) child.getLayoutParams(); //子元素所占宽度 = MarginLeft+ child.getMeasuredWidth+MarginRight 注意此时不能child.getWidth,因为界面没有绘制完成,此时wdith为0 int childWidth = marginParams.leftMargin + marginParams.rightMargin + measuredWidth; int childHeight = marginParams.topMargin + marginParams.bottomMargin + measuredHeight; //判断是否换行: 该行已占大小+该元素大小>父容器宽度 则换行 rowsMaxHeight = Math.max(rowsMaxHeight, childHeight); //换行 if (rowsWidth + childWidth > flowWidth) { //重置行宽度 rowsWidth = getPaddingLeft() + getPaddingRight(); //累加上该行子元素最大高度 columnHeight += rowsMaxHeight; //重置该行最大高度 rowsMaxHeight = childHeight; aRow = false; } //累加上该行子元素宽度 rowsWidth += childWidth; //判断时占的宽段时加上margin计算,设置顶点位置时不包括margin位置,不然margin会不起作用,这是给View设置tag,在onlayout给子元素设置位置再遍历取出 child.setTag(new Rect(rowsWidth - childWidth + marginParams.leftMargin, columnHeight + marginParams.topMargin, rowsWidth - marginParams.rightMargin, columnHeight + childHeight - marginParams.bottomMargin)); } //返回子元素总所占宽度和高度(用于计算Flowlayout的AT_MOST模式设置宽高) Map<String, Integer> flowMap = new HashMap<>(); //单行 if (aRow) { flowMap.put("allChildWidth", rowsWidth); } else { //多行 flowMap.put("allChildWidth", flowWidth); } //FlowLayout测量高度 = 当前行顶部已占高度 +当前行内子元素最大高度+FlowLayout的PaddingBottom flowMap.put("allChildHeight", columnHeight + rowsMaxHeight + getPaddingBottom()); return flowMap; }
}
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF" />
<corners android:radius="3dp" />
<stroke android:width="1dp"
android:color="#BBBBBB"/>
</shape>