android流式布局控件
Posted zero-27
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android流式布局控件相关的知识,希望对你有一定的参考价值。
另外再说一个控件,先看效果图:
使用代码如下:
private void init()
FlowLayout flow = (FlowLayout) findViewById(R.id.flow);
for(String s : data)
TextView tv = new TextView(this);
tv.setText(s);
int padding = dip2Px(5);
tv.setPadding(padding, padding, padding, padding);
tv.setGravity(Gravity.CENTER);
tv.setTextColor(Color.WHITE);
GradientDrawable bg = new GradientDrawable();
bg.setCornerRadius(dip2Px(6));
Random random = new Random();
int alpha = 255;
int red = random.nextInt(190)+30;
int green = random.nextInt(190)+30;
int blue = random.nextInt(190)+30;
int argb = Color.argb(alpha, red, green, blue);
bg.setColor(argb);
tv.setClickable(true);
tv.setBackgroundDrawable(bg);
int dip = dip2Px(5);
flow.setSpace(dip, dip);
flow.addView(tv);
很简单,FlowLayout继承ViewGroup,用addView将View添加进去就行,有兴趣的童鞋可以写一个Adapter方便使用,老规矩,本人一向喜欢直入主题,看源码实现:
public FlowLayout(Context context, AttributeSet attrs)
super(context, attrs);
public FlowLayout(Context context)
super(context);
可见构造方法没有改变。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
// 清空记录
mLines.clear();
mCurrentLine = null;
// 获得layout的宽度
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int childMaxWidth = widthSize - getPaddingLeft() - getPaddingRight();
// 子控件个数
int count = getChildCount();
// 测量孩子
for (int i = 0; i < count; i++)
// 具体孩子
View child = getChildAt(i);
// 判断是否显示
if (child.getVisibility() == View.GONE)
continue;
// 测量每一个孩子
measureChild(child, widthMeasureSpec, heightMeasureSpec);
// 记录孩子到行中
if (mCurrentLine == null)
// 新建一行
mCurrentLine = new Line(childMaxWidth, mHorizontalSpace);
// 将这一行记录到list
mLines.add(mCurrentLine);
if (mCurrentLine.canAdd(child))
// 可以添加
mCurrentLine.addView(child);
else
// 不可以添加
// 新建一行
mCurrentLine = new Line(childMaxWidth, mHorizontalSpace);
// 将这一行记录到list
mLines.add(mCurrentLine);
// 将child加到line
mCurrentLine.addView(child);
// 行的高度的累加
int heightSize = getPaddingTop() + getPaddingBottom();
for (int i = 0; i < mLines.size(); i++)
Line line = mLines.get(i);
heightSize += line.mHeight;
if (i != 0)
// 垂直的间隙
heightSize += mVerticalSpace;
// setMeasuredDimension:设置自己宽度和高度
setMeasuredDimension(widthSize, heightSize);
自定义View中的三方法之一,onMeasure中先是计算出了自身的宽度,再通知子View测量,这是为了得到子View的具体大小,在通过行容器判断能否添加,如果不能新建一行,最后计算出自身的宽高设定。
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
// 获取上边距
int top = getPaddingTop();
// 遍历行
for (int i = 0; i < mLines.size(); i++)
Line line = mLines.get(i);
// 让行布局
line.layout(getPaddingLeft(), top);
// 高度计算
top += line.mHeight;
// 加上间隙
if (i != mLines.size() - 1)
top += mVerticalSpace;
自定义View中的三方法之一,onLayout用于计算View放置的位置,left值交由Line内部计算,这里主要计算每个Line的Top。
Line是FlowLayout内部的封装类,用来记录描述 layout中的行的信息,它只有一个构造方法。
// 构造
public Line(int maxWidth, int space)
this.mMaxWidth = maxWidth;
this.mSpace = space;
mMaxWidth代表最大宽度,mSpace代表间隙。
/** 布局 */
public void layout(int pLeft, int pTop)
// 多余的宽度
int extraWidth = mMaxWidth - mCurrentWidth;
// 获得平均值
int avgWidth = (int) (extraWidth * 1f / mViews.size() + .5f);
// 给View布局
for (int i = 0; i < mViews.size(); i++)
View view = mViews.get(i);
// 测量宽
int width = view.getMeasuredWidth();
// 测量高
int height = view.getMeasuredHeight();
// 平均值大于0
if (avgWidth > 0)
// 指定孩子具体的大小
view.measure(MeasureSpec.makeMeasureSpec(width + avgWidth,
MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
height, MeasureSpec.EXACTLY));
// 重新获取宽高
width = view.getMeasuredWidth();
height = view.getMeasuredHeight();
// 多余的高度
int extraHeight = mHeight - height;
// 指定左边距
int l = pLeft;
// 指定上边距
int t = (int) (pTop + extraHeight / 2f + .5f);
// 右边据
int r = l + width;
// 下边据
int b = t + height;
// 设置控件大小
view.layout(l, t, r, b);
// 左值计算
pLeft += width + mSpace;
这里的主要方法就是这个onLayout,计算行内View所要安置的位置,具体的都写了注释,不多讲。
最后同样附上Demo以供参考。
以上是关于android流式布局控件的主要内容,如果未能解决你的问题,请参考以下文章