自定义ViewGroup,流式布局FlowLayout
来源:互联网 发布:怎么加入农村淘宝网 编辑:程序博客网 时间:2024/04/29 08:19
本文参考了【张鸿洋的博客】: Android 手把手教您自定义ViewGroup(一)和Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
在很多应用里面,我们能看到类似于这样的流式
用现有的控件我们实现这种动态适应的布局很麻烦,对于如何比较简单的去实现这种布局,就需要我们去自定义ViewGroup了
实现步骤
一、新建一个FlowLayout类,继承ViewGroup,并重写generateLayoutParams方法
重写generateLayoutParams是为了设置布局的LayoutParams,在这里,我们用系统的MarginLayoutParams就可以了
//设置布局的LayoutParams,用系统的MarginLayoutParams就行 @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); }
二、重写onMeasure方法
重写onMeasure方法是为了根据子控件去计算布局的宽高,并进行设置
//根据childView的高宽,计算布局的宽高,并进行设置 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //获取布局的父容器为它设置的测量模式和大小 int widthSize = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); //最后计算的布局宽高 int width = 0, height = 0; //每一行的宽高 int lineWidth = 0, lineHeight = 0; //循环childView for (int i = 0, count = getChildCount(); i < count; i++) { View view = getChildAt(i); //计算当前childView的高和宽 measureChild(view, widthMeasureSpec, heightMeasureSpec); //得到childView的LayoutParams MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams(); //得到childView所占的宽度和高度 int childWidth = view.getMeasuredWidth() + params.leftMargin + params.rightMargin; if (childWidth > widthSize) { params.width = widthSize - params.leftMargin - params.rightMargin; view.setLayoutParams(params); measureChild(view, widthMeasureSpec, heightMeasureSpec); } params = (MarginLayoutParams) view.getLayoutParams(); childWidth = view.getMeasuredWidth() + params.leftMargin + params.rightMargin; int childHeight = view.getMeasuredHeight() + params.topMargin + params.bottomMargin; //如果加入当前childView的宽度会超出父容器计算的宽度话,则需要开启新的一行,累加height //否则累加当前行的宽高 if (lineWidth + childWidth > widthSize) { //取宽度最大值 width = Math.max(lineWidth, childWidth); //累加height height += lineHeight; //记录下一行的宽高 lineWidth = childWidth; lineHeight = childHeight; } else { lineWidth += childWidth; lineHeight = Math.max(lineHeight, childHeight); } //如果是最后一个,则将当前行的宽度与width做比较,累加height if (i == count - 1) { width = Math.max(lineWidth, width); height += lineHeight; } } //设置布局的宽高 setMeasuredDimension((widthMode == MeasureSpec.EXACTLY ? widthSize : width), (heightMode == MeasureSpec.EXACTLY ? heightSize : height)); }
三、重写onLayout方法
重写onLayout方法是为了对布局所有的子控件进行重新排版,对他们的位置进行设置
//对所有的childView位置和大小进行设置 @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int widht = getWidth(); int height = getHeight(); //记录的高度 int recordHeight = 0; //每行的宽高 int lineWidth = 0, lineHeight = 0; //每个childView的坐标 int left = 0, top = 0, right = 0, bottom = 0; //循环childView for (int i = 0, count = getChildCount(); i < count; i++) { View view = getChildAt(i); //得到childView的LayoutParams MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams(); //得到childView宽高 int childWidth = view.getMeasuredWidth(); int childHeight = view.getMeasuredHeight(); if (childWidth + params.leftMargin + params.rightMargin + lineWidth > widht) { recordHeight = recordHeight + lineHeight; left = params.leftMargin; right = left + childWidth; top = recordHeight + params.topMargin; bottom = top + childHeight; lineWidth = childWidth + params.leftMargin + params.rightMargin; lineHeight = childHeight + params.topMargin + params.bottomMargin; } else { left = lineWidth + params.leftMargin; right = left + childWidth; top = recordHeight + params.topMargin; bottom = top + childHeight; lineWidth = lineWidth + childWidth + params.leftMargin + params.rightMargin; lineHeight = Math.max(lineHeight, childHeight + params.topMargin + params.bottomMargin); } view.layout(left, top, right, bottom); } }
四、代码中使用
至此,我们的流式布局已经写完,现在去用他进行布局
布局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.krubo.flowlayout.MainActivity"> <com.krubo.flowlayout.FlowLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="遍历所有的childView"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="用于设置allViews的值"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="根据"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="childView"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="所有的"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="遍历"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="到此完成了所有的childView的绘制区域的确定,到此,我们的FlowLayout的代码也结束了~~静下心来看一看是不是也不难"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="静下心"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="用于设置allViews的值"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="根据"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="childView"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="所有的"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#dddddd" android:text="遍历"/> </com.krubo.flowlayout.FlowLayout></LinearLayout>
运行后的效果图如下
0 0
- 自定义ViewGroup实现流式布局FlowLayout
- 自定义ViewGroup,流式布局FlowLayout
- 自定义流式布局FlowLayout
- 自定义流式布局FlowLayout
- Android自定义流式布局-FlowLayout
- 自定义流式布局控件FlowLayout
- Android自定义流式布局-FlowLayout
- 自定义控件之-流式布局FlowLayout
- Android自定义控件--流式布局(FlowLayout)
- android_studio自定义FlowLayout流式布局
- FlowLayout实现自定义的流式布局
- 自定义viewgroup流式布局
- 自定义ViewGroup——FlowLayout(标签式布局)的实现
- Android 自定义ViewGroup 实现FlowLayout,动态添加布局
- android 实现FlowLayout 流线布局(自定义ViewGroup)
- FlowLayout流式布局
- FlowLayout流式布局
- 流式布局FlowLayout
- eclipse设置jvm
- hive json数据生成和处理
- mipi 调试经验
- 管理对象图以避免内存泄露
- 队列之顺序队列与循环队列
- 自定义ViewGroup,流式布局FlowLayout
- 用FileSystem API来操作HDFS
- 指定存储位置/Bitmap内存溢出解决/解决Bitmap无法序列化问题/输入流转Bitmap
- 一步一步实现iOS微信自动抢红包(非越狱)
- GC日志分析、年轻代、老年代
- CListCtrl控件使用方法总结
- 链栈
- 并发编程(4)线程的生命周期及基本状态
- 动态判断UIScrollview滑动方向