Android 实现自定义FlowLayout
来源:互联网 发布:恩尼格玛密码机 知乎 编辑:程序博客网 时间:2024/06/06 13:24
参考自 http://blog.csdn.net/lmj623565791/article/details/38352503/
自定义ViewGroup实现流式布局的效果,支持Margin
代码
public class FlowViewGroup extends ViewGroup { private static final String TAG = "FlowViewGroup"; /*所有子View,按照行进行存储*/ private List<List<View>> mEachLineViews = new ArrayList<>(); /*每行的高度*/ private List<Integer> mLineHeight = new ArrayList<>(); public FlowViewGroup(Context context) { this(context, null); } public FlowViewGroup(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FlowViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } /*针对wrap_content的情况进行处理*/ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // mode and size int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); // wrap_content时记录宽和高 int width = 0; int height = 0; int lineWidth = 0; // 最长的width int lineHeight = 0; // 累加的Height int childCount = getChildCount(); // 测量所有子View for (int i = 0; i < childCount; i++) { View child = getChildAt(i); measureChild(child, widthMeasureSpec, heightMeasureSpec); MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams(); int childWidth = params.leftMargin + params.rightMargin + child.getMeasuredWidth(); int childHeight = params.topMargin + params.bottomMargin + child.getMeasuredHeight(); // 加入当前View时,宽度超过ViewGroup的宽度时,进行换行 if (lineWidth + childWidth > widthSize) { width = Math.max(lineWidth, childWidth); lineHeight += childHeight; lineWidth = 0; } else { // 没有换行时,lineWidth继续累加 lineWidth += childWidth; lineHeight = Math.max(lineHeight, childHeight); // 最大高度 } if (i == childCount - 1) { // 处理最后一个子View的情况 width = Math.max(width, lineWidth); height += lineHeight; } } setMeasuredDimension(widthMode == MeasureSpec.AT_MOST ? width : widthSize , heightMode == MeasureSpec.AT_MOST ? height : heightSize); } /*对子View位置的摆放*/ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { /*计算每个ChildView的位置*/ mEachLineViews.clear(); mLineHeight.clear(); int width = getWidth(); int childCount = getChildCount(); int lineHeight = 0; int lineWidth = 0; List<View> lineViews = new ArrayList<>(); for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); MarginLayoutParams params = (MarginLayoutParams) childView.getLayoutParams(); int childWidth = childView.getMeasuredWidth() + params.leftMargin + params.rightMargin; int childHeight = childView.getMeasuredHeight() + params.topMargin + params.bottomMargin; // 需要换行的情况 if (lineWidth + childWidth > width) { mLineHeight.add(lineHeight); mEachLineViews.add(lineViews); lineWidth = 0; lineHeight = 0; lineViews = new ArrayList<>(); } // 没有换行,进行累加 lineWidth += childWidth; lineHeight = Math.max(lineHeight, childHeight); lineViews.add(childView); } // 记录最后一行 mLineHeight.add(lineHeight); mEachLineViews.add(lineViews); /*对每个ChildView进行显示*/ int left = 0; int top = 0; int lineNums = mEachLineViews.size(); for (int i = 0; i < lineNums; i++) { // 获取每一行所有的View lineViews = mEachLineViews.get(i); lineHeight = mLineHeight.get(i); // 对当前行的所有View排列位置 for (View childView : lineViews) { if (childView.getVisibility() == View.GONE) { continue; } MarginLayoutParams params = (MarginLayoutParams) childView.getLayoutParams(); // 确定位置 int lc = left + params.leftMargin; // left int tc = top + params.topMargin; // top int rc = lc + childView.getMeasuredWidth(); // right int bc = tc + childView.getMeasuredHeight(); // bottom childView.layout(lc, tc, rc, bc); left += childView.getMeasuredWidth() + params.leftMargin + params.rightMargin; } left = 0; top += lineHeight; } } /* 生成默认的LayoutParams */ @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } @Override protected LayoutParams generateLayoutParams(LayoutParams p) { return new MarginLayoutParams(p); } @Override protected LayoutParams generateDefaultLayoutParams() { return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); }}
测试的布局代码
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="cn.edu.hebust.customviewgroup.MainActivity"> <cn.edu.hebust.customviewgroup.FlowViewGroup android:layout_width="match_parent" android:background="#dddddd" android:layout_height="match_parent"> <TextView android:layout_width="50dp" android:layout_height="wrap_content" android:layout_margin="10dp" android:text="Hello World" /> <View android:layout_width="120dp" android:layout_height="30dp" android:layout_margin="10dp" android:background="#dd4564" /> <View android:layout_width="40dp" android:layout_height="10dp" android:layout_margin="10dp" android:background="#d652" /> <View android:layout_width="220dp" android:layout_height="20dp" android:layout_margin="10dp" android:background="#dd641d" /> <View android:layout_width="20dp" android:layout_height="50dp" android:layout_margin="10dp" android:background="#dd23ee" /> <View android:layout_width="220dp" android:layout_height="70dp" android:layout_margin="10dp" android:background="#d4d564" /> </cn.edu.hebust.customviewgroup.FlowViewGroup></RelativeLayout>
1 0
- 自定义FlowLayout,android flowLayout实现
- Android自定义实现FlowLayout
- Android 实现自定义FlowLayout
- Android 自定义ViewGroup 实现FlowLayout
- Android 自定义ViewGroup 实现FlowLayout
- Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
- Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
- Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
- 【Android】 自定义ViewGroup 实战篇 -> 实现FlowLayout
- Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
- Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
- Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
- Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
- Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
- Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
- Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
- Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
- Android 自定义ViewGroup 实战篇 -> 实现FlowLayout
- hihocoder1065 点分治 【 全图传送 】
- 如何打印Spark RDD中的内容
- 一个关于先验概率、似然函数与后验概率计算的小例子
- python爬虫文章
- 腾讯云分布式高可靠消息队列CMQ架构
- Android 实现自定义FlowLayout
- 布局文件不常用属性
- Spring MVC + Mybatis搭建过程
- Detour开发包介绍(2):使用
- 数据结构-Hash总结(三):实践基础篇
- 欢迎使用CSDN-markdown编辑器
- 初窥Linux 之 我最常用的20条命令
- Cocoa Core - App ID
- jvm 垃圾收集器参数