您的位置:首页 > 移动开发 > Android开发

Android学习自定义View(五)——自定义ViewGroup及其onMeasure()的理解

2014-02-03 20:43 459 查看
MainActivity如下:

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没有任何用处
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: