Android流式布局
来源:互联网 发布:怎么安装photoshop软件 编辑:程序博客网 时间:2024/06/05 06:21
看了慕课网上hyman老师的讲解,现在将自己写的代码记录一下
hyman老师的视频地址http://www.imooc.com/learn/237
解释全部在代码里面啦
package com.example.flowlayout;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;import java.util.ArrayList;import java.util.List;/** * Created by libingyuan on 2016/12/9. * <p> * 模式: * AT_MOST==wrap_content * EXACTILY=match_parent,100dp * ... */public class FlowLayout extends ViewGroup { //存储行的View的位置 private List<List<View>> mAllView = new ArrayList<>(); //每一行的高度 private List<Integer> mLineHeight = new ArrayList<>(); /* 使用new关键字创建的时候调用 */ public FlowLayout(Context context) { this(context, null); } /* 在xml中调用的时候会调用这个方法 */ public FlowLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } /* 在xml中有自定义属性的时候会调用 */ public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //测量父布局的大小和模式 int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); int modeWidth = MeasureSpec.getMode(widthMeasureSpec); int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); int modeHeight = MeasureSpec.getMode(heightMeasureSpec); /** * 当父控件为match_parent或精确值的时候sizeWidth等是固定的, * 但是是wrap_content的时候就需要重新动态测量宽高 */ //父控件的宽高(wrap_content的时候) int width = 0; int height = 0; //每一行的宽高(wrap_content的时候) int lineWidth = 0; int lineHeight = 0; //所有子View的个数 int childCount = getChildCount(); //循环这些子View for (int i = 0; i < childCount; i++) { //得到其中的一个子View View child = getChildAt(i); //测量子View的宽和高 measureChild(child, widthMeasureSpec, heightMeasureSpec); //得到子View的layoutParams MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); //子View所占的宽度 int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; //子View所占的高度 int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; //换行 if (lineWidth + childWidth > sizeWidth) { //对比得到最大的宽度 width = Math.max(width, lineWidth); //重置行宽 lineWidth = childWidth; //高度累加 height += lineHeight; //重置行高 lineHeight = childHeight; } else {//未换行 //叠加行宽 lineWidth += childWidth; //得到这一行的最大高度 lineHeight = Math.max(lineHeight, childHeight); } //最后一个控件 if (i == childCount - 1) { width = Math.max(width, lineWidth); height += lineHeight; } } //设置父控件的宽高 setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width, modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { mAllView.clear(); mLineHeight.clear(); //每一行的宽高 int lineWidth = 0; int lineHeight = 0; //存储这行所有的子view List<View> lineView = new ArrayList<>(); //得到viewgroup的宽度 int width = getWidth(); //得到子View的个数 int cCount = getChildCount(); //循环子View for (int i = 0; i < cCount; i++) { //得到每一个字View View child = getChildAt(i); //得到子View的margin MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); //子View 的宽度 int childWidth = child.getMeasuredWidth(); //子View 的高度 int childHeight = child.getMeasuredHeight(); //如果需要换行(这是个for循环的出口, // 只有符合if条件,也就是换行的时候才会添加总的list以及重置) if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width) { //记录当前行的高度 mLineHeight.add(lineHeight); //添加当前行所有的View mAllView.add(lineView); //重置行宽和行高 lineWidth = 0; lineHeight = childHeight + lp.topMargin + lp.bottomMargin; //重置这一行的list lineView = new ArrayList<>(); } //计算行宽(累加) lineWidth += childWidth + lp.leftMargin + lp.rightMargin; //得到行高(最大) lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin); //添加进list lineView.add(child); } //处理最后一行(for循环的if里面没办法加载最后一行,这里特殊处理) mLineHeight.add(lineHeight); mAllView.add(lineView); /** * 下面开始为每个子View设置位置,主要是想办法计算子View的left top rigth bottom, * 然后调用子View 的layout方法即可 */ //行的高度(换成lineheight应该更容易理解,不过已经存在啦,所以用了left) int top = 0; //行的宽度(同上) int left = 0; //有多少行 int lineNum = mAllView.size(); //循环设置每一行 for (int i = 0; i < lineNum; i++) { //得到这一行所有的子view集合 lineView = mAllView.get(i); //得到这一行所有子View的高度集合 lineHeight = mLineHeight.get(i); //循环子View集合得到每一个子View for (int j = 0; j < lineView.size(); j++) { //得到每一个子View View child = lineView.get(j); //判断子View 是否隐藏,是,则不处理(注意:gone不占空间,所以不处理,INVISIBLE不可见但是占空间,不能跳过) if (child.getVisibility() == View.GONE) { continue; } //得到子View 的margin MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); //分别计算子View 的四个值 int cleft = left + lp.leftMargin; int ctop = top + lp.topMargin; int cright = cleft + child.getMeasuredWidth(); int cbottom = ctop + child.getMeasuredHeight(); // 为子View布局 child.layout(cleft, ctop, cright, cbottom); //行的宽度累加 left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; } //下一行清空行宽(left) left = 0; //行高(top)叠加 top += lineHeight; } } //设置子View的Layoutparams是什么类型 @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); }}
用法直接把它当作一个LinearLayout或其他的布局用就行啦
0 0
- Android流式布局
- Android 流式布局
- Android流式布局
- Android流式布局
- Android流式布局
- Android流式布局
- android流式布局
- Android 流式布局FlowLayout
- Android流式布局实现
- Android流式布局-FlowLayout
- Android流式布局实现
- Android 自定义流式布局
- Android流式布局实现
- Android流式布局实现
- android流式布局控件
- Android流式布局FlowLayout
- Android:FlowLayout流式布局
- Android 流式布局LinearLayout
- 查找问题的最好终极方案
- Vue.js:轻量高效的前端组件化方案
- CodeForces 741C Arpa’s overnight party and Mehrdad’s silent entering
- iOS 动画 - 从不会到熟练应用
- jQuery修改操作css属性实现方法
- Android流式布局
- GO中的sync.waitgroup的用法
- java设计模式之代理模式,java动态代理
- Drawable资源
- docker .net core
- 相似性度量
- 新手学web
- 进程编程中的system函数
- mysql数据库的备份策略