android 标签 瀑布流,Android 瀑布流标签选择FlowLayout

1、说明

一个瀑布流标签的选择,支持单选与多选,其实就是一个自定义的ViewGroup。

2、演示

b8394668d7a644308d427ec0da4fdafb.gif

3、代码

有人说,Android的自定义,玩的就是算法,其实真没错。自定义ViewGroup最重要就两个东西:onMeasure()方法和onLayout()方法;

思路大概就是:

在onMeasure()对子view宽高进行计算:

a:循环遍历所有的二级子view,计算子view的宽和高。当然宽和高要包括Margin值。

b:一行中的子view宽度之和比父view能给的最大宽度要大的话。就换到下一行。

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int widthMax = MeasureSpec.getSize(widthMeasureSpec);

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int heightMax = MeasureSpec.getSize(heightMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

int widthNeed = 0;//需要的宽度

int heightNeed = 0;//需要的高度

int x_axle = 0;//位置坐标

int y_axle = 0;

int lineHeight = 0;//一行的高度

View child;

for (int i = 0; i < getChildCount(); i++) {

child = getChildAt(i);

if (child.getVisibility() == View.GONE) {

continue;

}

child.measure(widthMeasureSpec, heightMeasureSpec);//通知child计算自己的宽高度

MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();//获取child的margin值

int childHeight = child.getMeasuredHeight() + lp.topMargin+ lp.bottomMargin;

//measure 时考虑把 margin 及 padding 也作为子视图大小的一部分

measureChildWithMargins(child, widthMeasureSpec, 0,heightMeasureSpec, 0);

int childWidth = child.getMeasuredWidth() + lp.leftMargin+ lp.rightMargin;

if (x_axle + childWidth > widthMax) {//当一行的宽度不够时,本行高度和x轴都清零,y轴下移本行的高度

y_axle += lineHeight;

lineHeight = 0;

x_axle = 0;

}

x_axle += childWidth;

lineHeight = Math.max(lineHeight, childHeight);

widthNeed = Math.max(widthNeed, x_axle);

heightNeed = Math.max(heightNeed, y_axle + lineHeight);

}

setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthMax

: widthNeed, heightMode == MeasureSpec.EXACTLY ? heightMax

: heightNeed);

}

在onLayout()中根据计算的结果,来摆放子view。

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

int widthMax = getWidth();

int x_axle, y_axle;

x_axle = 0;//位置坐标

y_axle = 0;

View child;

int left = 0;//child左上角坐标点

int top = 0;

int lineHeight = 0;

for (int i = 0; i < getChildCount(); i++) {

child = getChildAt(i);

if (child.getVisibility() == View.GONE) {

continue;

}

MarginLayoutParams lp = (MarginLayoutParams) child

.getLayoutParams();

int childWidth = child.getMeasuredWidth() + lp.leftMargin

+ lp.rightMargin;

int childHeight = child.getMeasuredHeight() + lp.topMargin

+ lp.bottomMargin;

if (x_axle + childWidth > widthMax) {// 换行处理

y_axle += lineHeight;

x_axle = 0;

lineHeight = 0;

}

left = x_axle + lp.leftMargin;

top = y_axle + lp.topMargin;

//在合适的位置摆放child

child.layout(left, top, left + child.getMeasuredWidth(), top

+ child.getMeasuredHeight());

x_axle += childWidth;

lineHeight = Math.max(lineHeight, childHeight);

}

}

代码不是多,也不难,无非就是计算,很容易看懂。后面的单选和多选就只是逻辑处理了。代码中是用的TextView作为的子view。当然这里可以是任何的view。

demo下载地址:http://download.csdn.net/detail/u010886975/9693799

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值