android自定义流式布局思路,Android 自定义控件基础-流式布局

本文详细介绍了如何在Android中自定义ViewGroup实现流式布局。通过重写onMeasure()和onLayout()方法,测量并放置子View,以适应不同屏幕尺寸。同时,文章强调了在自定义ViewGroup时需要定义LayoutParams,并提供了相关代码示例。
摘要由CSDN通过智能技术生成

什么是流式布局?其实我们在平时遇到过,只是有可能叫不出它的名字。

如图:

cfc2d8d263c4

如上图,就是一个流式布局的样式。

&esmp;这里,将记录一下怎么实现这个功能。其实实现这个功能的方法,就是自定义ViewGroup。

自定义ViewGroup的时候,要注意两点:

1.子View和父View大小的测量。

2.子View的在父View里面怎么摆放。

想要解决上面的两个问题,就得重写两个方法,分别是:onMeasure方法,在这个方法我们通常来测量子View和父View的大小;onLayout方法,在这个方法里面,我们通常来决定子View在父View的摆放。

1.重写onMeasure方法

//测量父控件和子控件的大小

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int widthSize = MeasureSpec.getSize(widthMeasureSpec);

int widthMode = MeasureSpec.getMode(widthMeasureSpec);

int heightSize = MeasureSpec.getSize(heightMeasureSpec);

int heightMode = MeasureSpec.getMode(heightMeasureSpec);

int width = getMeasuredWidth();

int height = 0;

int lineWidth = 0;

int lineHeight = 0;

int childWidth = 0;

int childHeight = 0;

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

View child = getChildAt(i);

measureChild(child, widthMeasureSpec, heightMeasureSpec);

MarginLayoutParams marginLayoutParams = (MarginLayoutParams) child.getLayoutParams();

Log.i("main", "width = " + child.getMeasuredWidth() + " height = " + child.getMeasuredHeight() + " leftMargin = " + marginLayoutParams.leftMargin + " rightMargin = " + marginLayoutParams.rightMargin);

childWidth = child.getMeasuredWidth() + marginLayoutParams.leftMargin + marginLayoutParams.rightMargin;

childHeight = child.getMeasuredHeight() + marginLayoutParams.topMargin + marginLayoutParams.bottomMargin;

//换行

if (lineWidth + childWidth > width) {

lineWidth = childWidth;

height += lineHeight;

} else {

lineWidth += childWidth;

lineHeight = Math.max(childHeight, lineHeight);

}

if (i == n - 1) {

height += lineHeight;

}

}

setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : width, heightMode == MeasureSpec.EXACTLY ? heightSize : height);

}

2.重写onLayou方法

private List> mAllViews = new ArrayList>();

private List mLineHeights = new ArrayList();

@Override

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

mAllViews.clear();

mLineHeights.clear();

int width = getWidth(); // 父布局的宽度

List lineViews = new ArrayList();

int childWidth = 0;

int childHeight = 0;

int lineWidth = 0;

int lineHeight = 0;

Log.i("main", "childCount = " + getChildCount() + " width = " + width);

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

View child = getChildAt(i);

MarginLayoutParams marginLayoutParams = (MarginLayoutParams) child.getLayoutParams();

childWidth = child.getMeasuredWidth() + marginLayoutParams.leftMargin + marginLayoutParams.rightMargin;

childHeight = child.getMeasuredHeight() + marginLayoutParams.topMargin + marginLayoutParams.bottomMargin;

if (childWidth + lineWidth > width) {

mAllViews.add(lineViews);

mLineHeights.add(lineHeight);

lineViews = new ArrayList();

lineWidth = 0;

lineHeight = childHeight;

}

lineWidth += childWidth;

lineHeight = Math.max(lineHeight, childHeight);

lineViews.add(child);

}

mAllViews.add(lineViews);

mLineHeights.add(lineHeight);

int top = 0;

int left = 0;

Log.i("main", "n = " + mAllViews.size() + " m = " + lineViews.size());

for(int i = 0, n = mAllViews.size(); i < n; i++)

{

lineViews = mAllViews.get(i);

for(int j = 0, m = lineViews.size(); j < m; j++)

{

View child = lineViews.get(j);

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

{

continue;

}

MarginLayoutParams marginLayoutParams = (MarginLayoutParams) child.getLayoutParams();

int lc = left + marginLayoutParams.leftMargin;

int tc = top + marginLayoutParams.topMargin;

int rc = lc + child.getMeasuredWidth();

int bc = tc + child.getMeasuredHeight();

Log.i("main", "lc = " + lc + " tc = " + tc + " rc = " + rc + " bc = " + bc);

child.layout(lc, tc, rc, bc);

left += child.getMeasuredWidth() + marginLayoutParams.leftMargin + marginLayoutParams.rightMargin;

}

left = 0;

top += mLineHeights.get(i);

}

}

在自定义ViewGroup的时候,一定要定义ViewGroup的LayoutParams。所以还要重写generateLayoutParams方法。

@Override

public LayoutParams generateLayoutParams(AttributeSet attrs) {

return new MarginLayoutParams(getContext(), attrs);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值