Android自定义控件:绘制ViewGroup控件
程序员文章站
2022-06-08 17:07:56
...
自定义布局ViewGroup:基本操作由四个函数完成:onMeasure()、onSizeChanged()、onLayout()、dispatchDraw()。
onMeasure
测量所有子控件的尺寸(触发所有子View的onMeasure方法测量自己并把测量结果回传给ViewGroup)和设置自己的尺寸。(所有子View测量完毕后,再调用setMeasuredDimension将ViewGroup自身的宽和高传给它的父View)getChildCount()方法,返回子View的数量,measureChild()方法,调用子View的测量方法。
onSizeChanged
在onMeasure()后执行,只有大小发生了变化才会执行onSizeChange
onLayout
排列所有子View的位置,通过getChildCount()获取所有子view,getChildAt获取childView调用各自的layout(int, int, int, int)方法来排列自己。
简单实现自动换行
public class CustomViewGroup extends ViewGroup {
private final int PADDING_HOR = 10;
private final int PADDING_VERTICAL = 20;
//父控件的宽度
private int parentWidth;
private int coordinateX;
private int coordinateY;
//总行数
private int number;
public CustomViewGroup(Context context) {
this(context, null);
}
public CustomViewGroup(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
coordinateX = 0;
coordinateY = 0;
number = 1;
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
child.setBackgroundColor(Color.RED);
int width = child.getMeasuredWidth();
int height = child.getMeasuredHeight();
coordinateX += width;
if (coordinateX > parentWidth) {
coordinateX = width;
number++;
}
coordinateY = number * height;
child.layout(coordinateX - width, coordinateY - height, coordinateX, coordinateY);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
coordinateX = 0;
coordinateY = 0;
number = 1;
parentWidth = measureSize(widthMeasureSpec, 240);
int count = getChildCount();//子View数量
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
child.setPadding(PADDING_HOR, PADDING_VERTICAL, PADDING_HOR, PADDING_VERTICAL);
child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
int width = child.getMeasuredWidth();
int height = child.getMeasuredHeight();
coordinateX += width;
if (coordinateX > parentWidth) {//换行
coordinateX = width;
number++;
}
coordinateY = number * (height);
}
}
setMeasuredDimension(parentWidth, coordinateY);
}
/**
* 计算父控件宽度
*
* @param measureSpec
* @param defaultSize
* @return
*/
private int measureSize(int measureSpec, int defaultSize) {
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
int result = defaultSize;
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else if (mode == MeasureSpec.AT_MOST) {
result = Math.max(size, result);
}
return result;
}
}
arrayList.add("张三");
arrayList.add("测试测试测试测试测试测试");
arrayList.add("李四");
arrayList.add("测试测试测试测试测试测试测试测试测试测试测试测试");
arrayList.add("王五");
arrayList.add("测试测试测试测");
arrayList.add("赵六");
for (int i = 0; i < arrayList.size(); i++) {
textView = new TextView(this);
textView.setId(i);
textView.setText(arrayList.get(i));
customViewGroup.addView(textView);
}
推荐阅读