android自定义ViewGroup之瀑布流FlowLayout 简洁明了 支持padding和margin 100行代码搞定
2016-10-18 13:21
555 查看
FlowLayout完美解决购物类app参差不齐的标签、热门搜索等:
支持padding和margin
支持xml和java代码动态添加childView
简洁明了100行代码
2、重写onLayout:
3、由于ViewGroup支持margin属性,必须重写generateLayoutParams和generateDefaultLayoutParams,否则会出现classcastexception错误
好了,就这么简单,代码仔细看应该都能看懂,主要是一些计算。
支持padding和margin
支持xml和java代码动态添加childView
简洁明了100行代码
效果图
核心代码
1、重写onMeasure:@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //获取测量模式和测量父容器推荐宽高 int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); MarginLayoutParams cParams; int width = 0;//用于保存最大宽度 int height = 0;//用于保存最大高度,累加 int lineWidth = 0;//当前行最大宽度,累加行宽度 int lineHeight = 0;//当前行最大高度 int cCount = getChildCount(); for (int i = 0; i < cCount; i++) { View childView = getChildAt(i); measureChild(childView, widthMeasureSpec, heightMeasureSpec);//测量childView cParams = (MarginLayoutParams) childView.getLayoutParams(); int leftMargin = cParams.leftMargin; int rightMargin = cParams.rightMargin; int topMargin = cParams.topMargin; int bottomMargin = cParams.bottomMargin; int cWidth = childView.getMeasuredWidth() + leftMargin + rightMargin; int cHeight = childView.getMeasuredHeight() + topMargin + bottomMargin; if (lineWidth + cWidth > widthSize - getPaddingLeft() - getPaddingRight()) {//如果达到换行条件 height += lineHeight;//累加高度 lineHeight = cHeight;//开启新行 width = Math.max(cWidth, lineWidth);//获取较大宽度 lineWidth = cWidth;//初始化行宽 } else { lineHeight = Math.max(lineHeight, cHeight);//获取当前行最大高度 lineWidth += cWidth;//累加当前行宽度 } if (i == cCount - 1) {//如果是最后一个clildView,比较width确保为最大值,累加最后一行高度 width = Math.max(width, lineWidth); height += lineHeight; } } //最后加上父容器padding width += getPaddingLeft() + getPaddingRight(); height += getPaddingTop() + getPaddingBottom(); setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : width, heightMode == MeasureSpec.EXACTLY ? heightSize : height); }
2、重写onLayout:
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { MarginLayoutParams cParams; int cCount = getChildCount(); int selfWidth = getWidth(); int height = 0;//最大高累加 int lineWidth = 0;//每行最大宽累加 int lineHeight = 0;//每行最大高 for (int i = 0; i < cCount; i++) { View childView = getChildAt(i); if (childView.getVisibility() == View.GONE) { continue; } cParams = (MarginLayoutParams) childView.getLayoutParams(); int leftMargin = cParams.leftMargin; int rightMargin = cParams.rightMargin; int topMargin = cParams.topMargin; int bottomMargin = cParams.bottomMargin; int cWidth = childView.getMeasuredWidth() + leftMargin + rightMargin; int cHeight = childView.getMeasuredHeight() + topMargin + bottomMargin; int cl = 0, ct = 0, cr = 0, cb = 0;//childView上左、下右2个点 if (lineWidth + cWidth > selfWidth - getPaddingLeft() - getPaddingRight()) {//如果换行 height += lineHeight;//累加高度 lineHeight = cHeight;//开启新行 lineWidth = cWidth;//重置行宽 cl = getPaddingLeft() + leftMargin; ct = getPaddingTop() + height + topMargin; cr = getPaddingLeft() + cWidth - rightMargin; cb = getPaddingTop() + height + cHeight - bottomMargin; } else { lineHeight = Math.max(cHeight, lineHeight);//获取较大的行高 lineWidth += cWidth;//累加行宽 cl = getPaddingLeft() + lineWidth - cWidth + leftMargin; ct = getPaddingTop() + height + topMargin; cr = getPaddingLeft() + lineWidth - rightMargin; cb = getPaddingTop() + height + cHeight - bottomMargin; } childView.layout(cl, ct, cr, cb); } }
3、由于ViewGroup支持margin属性,必须重写generateLayoutParams和generateDefaultLayoutParams,否则会出现classcastexception错误
@Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } @Override protected LayoutParams generateDefaultLayoutParams() { return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); } @Override protected LayoutParams generateLayoutParams(LayoutParams p) { return new MarginLayoutParams(p); }
好了,就这么简单,代码仔细看应该都能看懂,主要是一些计算。
相关文章推荐
- 【Android】快速开发偷懒必备,一句话搞定所有ViewGroup的Adapter . 支持自定义ViewGroup
- android之自定义View和ViewGroup(二)(此篇不讲述代码,只讲述原理和结构,带你走进自定义的世界)
- android之自定义View和ViewGroup(五)(代码篇,实现类似竖着的ViewPager引导页,竖向引导页)
- android之自定义ViewGroup和自动换行的布局的实现(支持按钮间隔)
- android之自定义view和ViewGroup(三)(代码篇,实现条形进度条)
- Android自定义View、ViewGroup的OnMeasure的原理和模板代码
- android之自定义View和ViewGroup(六)(代码篇,实现简单的走势图,柱状图同理)
- <Android 进阶(三)> 自定义View之支持Gravity的ViewGroup
- 自定义ViewGroup支持margin,gravity以及水平,垂直排列
- android自定义viewgroup之我也玩瀑布流
- Android 自定义圆形头像CircleImageView支持加载网络图片的实现代码
- 在自定义ViewGroup应该怎样去考虑padding和margin
- 教你搞定Android自定义ViewGroup
- 教你搞定Android自定义ViewGroup
- android自定义View之margin和padding的处理
- 自定义ViewGroup考虑padding,margin
- 两行代码搞定iOS自定义HUD风格动画弹窗(支持选择记录) - SKChoosePopView的使用和实现思路
- android之自定义View和ViewGroup(四)(代码篇,实现圆形进度条)
- 自定义ViewGroup 支持Margin
- 教你搞定Android自定义ViewGroup