onLayout方法
- 该方法必须重写, 否则包含的控件不会显示
- 包含的子View调用layout方法控制View显示的位置和大小,可以直接通过layout方法控制子view大小位置,不使用onMeasure方法
- layout(int left,int top,int right,int bottom)通过四个参数将子View放到指定的位置, 四个参数分别表示左、上、右和下距离上左的距离,该距离是视图坐标。
onDraw方法
在ViewGroup中重写onDraw方法,需要在构造方法中调用this.setWillNoDraw(flase); 系统才会调用重写过的onDraw(Canvas cancas)方法,否则系统不会调用onDraw(Canvas canvas)方法.
onMeasure方法
- 测量View的大小
- 子view在测量之后可以调用getMeasuredWidth()方法获取测量的宽,可以使用测量的结果影响layout方法的参数
- 子view在layout方法设置过大小之后,可以使用getWidth()方法获取控件实际的宽.
- 三种测量模式
- EXACTLY:表示设置了精确的值,一般当childView设置其宽、高为精确值、match_parent时,ViewGroup会将其设置为EXACTLY;
- AT_MOST:表示子布局被限制在一个最大值内,一般当childView设置其宽、高为wrap_content时,ViewGroup会将其设置为AT_MOST;
- UNSPECIFIED:表示子布局想要多大就多大,一般出现在AadapterView的item的heightMode中、ScrollView的childView的heightMode中;此种模式比较少见。
View的measure(int, int)方法
- 该函数会回调该子View的onMeasure方法
- 测量模式为MeasureSpec.AT_MOST或MeasureSpec.EXACTLY时, 才有效
- 调用该方法不会实际改变View大小, 需要View再调用layout方法
自定义的ViewGroup子类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
public class MyViewGroup extends ViewGroup { public MyViewGroup(Context context) { super(context); } public MyViewGroup(Context context, AttributeSet attrs) { super(context, attrs); } public MyViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount();//子view的数目 int top = 20; for (int i = 0; i < childCount; i++) { View child = this.getChildAt(i); // 设置子view在父容器里的相对位置 // child.measure(MeasureSpec.AT_MOST+241, MeasureSpec.AT_MOST+131); child.layout(50, top, 50 + child.getMeasuredWidth(), top + child.getMeasuredHeight()); top = top + child.getMeasuredHeight() + 20; } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 获得组件的宽高的像素表示 int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); // 设置控件的宽高 setMeasuredDimension(width, height); // 自动测量该组件的子View的大小(与下面的循环2选1) // measureChildren(widthMeasureSpec,heightMeasureSpec); // 循环设置子view的宽高 int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = this.getChildAt(i); // measure方法调用后子view被按照wrap测量 child.measure(MeasureSpec.AT_MOST + 441, MeasureSpec.AT_MOST + 131); } } } |
布局中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<comb.example.MyViewGroup android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New Text" /> </comb.example.MyViewGroup> |
0 Comments