MainActivity如下:
ViewGroupSubClass如下:
main.xml如下:
PS:
main.mxl没有任何用处
package cc.testviewstudy5; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 自定义ViewGroup及其onMeasure()的理解 * * 参考资料: * 1 http://blog.csdn.net/guolin_blog/article/details/16330267 * 2 http://blog.csdn.net/dawanganban/article/details/23953827 * Thank you very much */ public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new ViewGroupSubClass(this)); } }
ViewGroupSubClass如下:
package cc.testviewstudy5; import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.Button; /** * 当继承自ViewGroup时,如果在onMeasure()对于子View不调用 * 1 measureChild(child, parentWidthMeasureSpec, parentHeightMeasureSpec) * 2 childView.measure(childWidthMeasureSpec, childHeightMeasureSpec) * 这两个方法的任何其中一个,那么: * childView.getMeasuredWidth()和childView.getMeasuredHeight()得到的值均为0 * * 这是为什么呢? * 因为ViewGroup继承自View,View就根本没有子View.所以: * 在ViewGroup的onMeasure()中的super.onMeasure(widthMeasureSpec,heightMeasureSpec) * 只是测量该ViewGroup本身的宽和高.而没有去测量其每个子View的宽和高. * 于是需要我们自己写代码去测量该ViewGroup的每个子View,或者让子View自己调用measure().这么操作以后,再用 * childView.getMeasuredWidth()和childView.getMeasuredHeight() * 得到的值就不再是0了. * * 假若不继承自ViewGroup而继承自XXXLayout,那么就不是必须要自己去测量每个子View的大小了. * 查看XXXLayout的源代码,可以看到在其onMeasure()中已经测量了子View的大小. * */ public class ViewGroupSubClass extends ViewGroup { public ViewGroupSubClass(Context context) { super(context); Button button1 = new Button(context); button1.setText("button1"); this.addView(button1); Button button2 = new Button(context); button2.setText("button2"); this.addView(button2); Button button3 = new Button(context); button3.setText("button3"); this.addView(button3); } public ViewGroupSubClass(Context context, AttributeSet attrs) { super(context, attrs); } public ViewGroupSubClass(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 获取系统自动测量的该ViewGroup的大小 int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); System.out.println("获取系统自动测量的该ViewGroup的大小: widthSize="+widthSize+",heightSize="+heightSize); // 我们也可调用setMeasuredDimension()重新设置测量结果 // 修改了系统自动测量的子View的大小 int childCount = this.getChildCount(); int childMeasuredWidth = 0; int childMeasuredHeight = 0; int childWidthMeasureSpec = 0; int childHeightMeasureSpec = 0; for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); // 系统自动测量子View: measureChild(childView, widthMeasureSpec, heightMeasureSpec); // 如果不希望系统自动测量子View,我们用以下的方式: // childWidthMeasureSpec = // MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXACTLY); // childHeightMeasureSpec = // MeasureSpec.makeMeasureSpec(100,MeasureSpec.EXACTLY); // childView.measure(childWidthMeasureSpec, childHeightMeasureSpec); } // 获取每个子View测量所得的宽和高 for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); childMeasuredWidth = childView.getMeasuredWidth(); childMeasuredHeight = childView.getMeasuredHeight(); System.out.println("i=" + i+ ",获取系统自动测量的该子View的大小:" + "childMeasuredWidth="+ childMeasuredWidth + "," + "childMeasuredHeight="+ childMeasuredHeight); } } @Override protected void onLayout(boolean arg0, int l, int t, int r, int b) { System.out.println("该ViewGroup的布局:"+"l="+l+",t="+t+",r="+r+",b="+b); int childCount = getChildCount(); int left = 0; int top = 10; int right = 0; int bottom = 0; for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); right = left + childView.getMeasuredWidth(); // 也可不用测量所得的宽而指定一个值 // right=left+180; bottom = top + childView.getMeasuredHeight(); // 也可不用测量所得的高而指定一个值 // bottom=top+180; childView.layout(left, top, right, bottom); System.out.println("i=" + i + ",该子View的布局:" + "" + "left="+left+",top="+top+",right="+right+",bottom="+bottom); top += 190; } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } }
main.xml如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" > <cc.testviewstudy5.ButtonSubClass android:id="@+id/button" android:layout_width="100dip" android:layout_height="200dip" android:text="Button"/> </RelativeLayout>
PS:
main.mxl没有任何用处