流布局Flowlayoiut
直接上代码:
1 ViewGroup 的使用
/** * 个人理解,容器的布局执行过程 1 父容器调用measureChildren 2 子容器调用measure 计算当前容器的宽高和其子容器的宽高 3 * 当前执行的这个子容器触发onMeasure ,设置当前子容器的宽高 4 当前容器调用onLayout , 来展示当前容器的显示 */ public class CustomFlowlayoutContainer extends ViewGroup { public CustomFlowlayoutContainer(Context context) { super(context); } // attrs 是xml中配置的参数会传到这里 public CustomFlowlayoutContainer(Context context, AttributeSet attrs) { super(context, attrs); } @Override public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } /** * * 根据父类传入的 widthMeasureSpec和heightMeasureSpec计算本类和其子类的宽高 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 获得它的父容器为它设置的测量模式和大小 int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);//容器的模式为fill_parent或者固定大小,所以这个值为容器宽度 int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); int modeWidth = MeasureSpec.getMode(widthMeasureSpec); int modeHeight = MeasureSpec.getMode(heightMeasureSpec); // 如果是warp_content情况下,记录宽和高 int width = 0; int height = 0; /** * 记录每一行的宽度,width不断取最大宽度 */ int lineWidth = 0; /** * 每一行的高度,累加至height */ int lineHeight = 0; int cCount = getChildCount(); // 遍历每个子元素 for (int i = 0; i < cCount; i++) { View child = getChildAt(i); // 测量每一个child的宽和高 measureChild(child, widthMeasureSpec, heightMeasureSpec); // 得到child的lp MarginLayoutParams lp = (MarginLayoutParams) child .getLayoutParams(); // 当前子控件实际占据的宽度 int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; // 当前子控件实际占据的高度 int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; /** * 如果加入当前child,则超出最大宽度,则的到目前最大宽度给width,类加height 然后开启新行 */ if (lineWidth + childWidth > sizeWidth) { width = Math.max(lineWidth, childWidth);// 取最大的 lineWidth = childWidth; // 重新开启新行,开始记录 // 叠加当前高度, height += lineHeight; // 开启记录下一行的高度 lineHeight = childHeight; } else // 否则累加值lineWidth,lineHeight取最大高度 { lineWidth += childWidth; lineHeight = Math.max(lineHeight, childHeight); } // 如果是最后一个,则将当前记录的最大宽度和当前lineWidth做比较 if (i == cCount - 1) { width = Math.max(width, lineWidth); height += lineHeight; } } //一般流式布局宽为EXACTLY所以数值为sizeWidth,高为wrap_content 为计算的height setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY) ? sizeWidth : width, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight : height); } /** * 存储所有的View,按行记录 */ private List<List<View>> mAllViews = new ArrayList<List<View>>(); /** * 记录每一行的最大高度 */ private List<Integer> mLineHeight = new ArrayList<Integer>(); /** * 对其所有childView进行定位 */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { //每次布局前要清零 mAllViews.clear(); mLineHeight.clear(); int width = getWidth(); int lineWidth = 0; int lineHeight = 0; // 存储每一行所有的childView List<View> lineViews = new ArrayList<View>(); int cCount = getChildCount(); // 遍历所有的孩子 for (int i = 0; i < cCount; i++) { View child = getChildAt(i); MarginLayoutParams lp = (MarginLayoutParams) child .getLayoutParams(); int childWidth = child.getMeasuredWidth(); int childHeight = child.getMeasuredHeight(); // 如果已经需要换行 if (childWidth + lp.leftMargin + lp.rightMargin + lineWidth > width) { // 记录这一行所有的View以及最大高度 mLineHeight.add(lineHeight); // 将当前行的childView保存,然后开启新的ArrayList保存下一行的childView mAllViews.add(lineViews); lineWidth = 0;// 重置行宽 lineViews = new ArrayList<View>(); } /** * 如果不需要换行,则累加 */ lineWidth += childWidth + lp.leftMargin + lp.rightMargin; lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin); lineViews.add(child); } // 记录最后一行 mLineHeight.add(lineHeight); mAllViews.add(lineViews); int left = 0; int top = 0; // 得到总行数 int lineNums = mAllViews.size(); for (int i = 0; i < lineNums; i++) { // 每一行的所有的views lineViews = mAllViews.get(i); // 当前行的最大高度 lineHeight = mLineHeight.get(i); Log.e("位置", "第" + i + "行 :" + lineViews.size() + " , " + lineViews); Log.e("位置", "第" + i + "行, :" + lineHeight); // 遍历当前行所有的View for (int j = 0; j < lineViews.size(); j++) { View child = lineViews.get(j); if (child.getVisibility() == View.GONE) { continue; } MarginLayoutParams lp = (MarginLayoutParams) child .getLayoutParams(); //计算childView的left,top,right,bottom int lc = left + lp.leftMargin; int tc = top + lp.topMargin; int rc =lc + child.getMeasuredWidth(); int bc = tc + child.getMeasuredHeight(); Log.e("位置", child + " , l = " + lc + " , t = " + t + " , r =" + rc + " , b = " + bc); child.layout(lc, tc, rc, bc); left += child.getMeasuredWidth() + lp.rightMargin + lp.leftMargin; } left = 0; top += lineHeight; } } }
2 Activity代码
public class TestFlowlayoutActivity extends Activity implements OnClickListener { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_flowlayout ); //DisplayUtil displayUtil = new DisplayUtil(getWindowManager()); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.start: break; default: break; } } }
3 xml 代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#E1E6F6" android:orientation="vertical" > <com.example.fragmentdemo1.widget.CustomFlowlayoutContainer android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:background="@drawable/button_bg" android:text="Welcome" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:background="@drawable/button_bg" android:text="IT工程师" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:background="@drawable/button_bg" android:text="努力啊" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:background="@drawable/button_bg" android:text="学习挣钱" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:background="@drawable/button_bg" android:text="攒钱娶媳妇了" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:background="@drawable/button_bg" android:text="攒钱买房子了" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:background="@drawable/button_bg" android:text="攒钱买车子了,什么时候出去玩玩" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" android:background="@drawable/button_bg" android:text="一辈子就这样没了,该出去休息一下了" /> </com.example.fragmentdemo1.widget.CustomFlowlayoutContainer> </LinearLayout>
4 背景代码button_bg.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <!-- 填充色 --> <solid android:color="#FFFFFF" > </solid> <!-- 圆角 --> <corners android:radius="20dp"/> <!-- 描边 --> <stroke android:color="#C9C9C9" android:width="2dp"/> <padding android:bottom="2dp" android:left="10dp" android:right="10dp" android:top="2dp" /> </shape>
相关推荐
yangkang 2020-11-09
alien 2020-11-15
ChlatZed 2020-11-11
远远的山 2020-11-09
xysoul 2020-11-03
onepiecedn 2020-10-29
lnkToKing 2020-10-29
ChlatZed 2020-10-27
谢恩铭 2020-10-23
yuanye0 2020-10-15
liverlife 2020-10-10
somyjun 2020-09-29
xiaoying 2020-09-28
kunyus 2020-09-25
dusuanyun 2020-09-21
newisI 2020-09-01
afanti 2020-09-14