简介
组件的布局就是实现onlayout方法,把子视图绘制在界面上。比如LinearLayout可以水平的布局,也可以垂直布局,GridView可以实现宫格方式的布局。下面就通过一个实例来说明是如何布局的。
一个宫格布局实例
想实现一个类似GridView的宫格布局,可以设置要展示的列数、横竖间距。
定义了这些属性
//列间距
private int columnSpsace = 16;
//行间距private int rowSpace = 16;
//列数private int column = 3;
也可以通过自定义属性的方式从布局中获取。
1、实现onMeasure方法测量子视图的宽高、确定自定义组件的宽高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//定义GridView的宽高为填充父视图
setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec));
//计算子视图的宽高
int parentWidth = getMeasuredWidth();
int childSize = (parentWidth - (columnSpsace * 2)) / 3;
int count = getChildCount(); int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childSize, MeasureSpec.EXACTLY);
int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childSize, MeasureSpec.EXACTLY);
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
}
这里要注意的是测量子视图的宽高时要扣除间距,因为是有具体的宽高,子视图的测量模式定义为MeasureSpec.EXACTLY精确模式。
2、实现onlayout方法进行布局
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//布局为9宫格
int childCount = getChildCount();
int childL = l;
int childT = t;
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
child.layout(childL, childT, childL + child.getMeasuredWidth(), childT + child.getMeasuredHeight());
if (i % 3 == 2) {
childL = l;
childT = childT + rowSpace + child.getMeasuredHeight();
} else {
childL = childL + columnSpsace + child.getMeasuredWidth();
}
}
}
计算出每个子视图的位置,调用他们的layout方法进行布局。
组件的布局并没有涉及到太多的概念,关键是要结合测量,根据定义好的规则计算他们的位置。