转载+验证:本人已经验证过,请放心复制粘贴,嘿嘿~~~~~~省了你的时间了
我们都知道在onCreate()里面获取控件的高度是0,这是为什么呢?我们来看一下示例:
首先我们自己写一个控件,这个控件非常简单:
- public class MyImageView extends ImageView {
- public MyImageView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- public MyImageView(Context context) {
- super(context);
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- System.out.println("onMeasure 我被调用了"+System.currentTimeMillis());
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- System.out.println("onDraw 我被调用了"+System.currentTimeMillis());
- }
- }
- 布局文件:
- [java]
- <com.test.MyImageView
- android:id="@+id/p_w_picpathview"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/test" />
- 测试的Activity的onCreate():
- [java]
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- System.out.println("执行完毕.."+System.currentTimeMillis());
- }
说明等onCreate方法执行完了,我们定义的控件才会被度量(measure),所以我们在onCreate方法里面通过view.getHeight()获取控件的高度或者宽度肯定是0,因为它自己还没有被度量,也就是说他自己都不知道自己有多高,而你这时候去获取它的尺寸,肯定是不行的.
在Android中,有时需要对控件进行测量,得到的控件宽度和高度可以用来做一些计算。在需要自适应屏幕的情况下,这种计算就显得特别重要。另一方便,由于需求的原因,希望一进入界面后,就能得到控件的宽度和高度。
可惜的是,根据我的验证,利用网上转载的那些方法在OnCreate函数中获取到的仍然是0(希望搞技术的能自己验证过再转载),例如Measure方法之后调用getMeasuredWidth的值还是0。
原因是因为当OnCreate函数发生时,只是提供了数据初始化的机会,此时还没有正式绘制图形。而绘制图形在OnDraw中进行,此时计算又显得太晚。容易想到的办法是:希望能在程序刚刚测量好某个指定控件后,拿到它的宽度和高度立刻进行计算或数据初始化。这就需要有一个方法来监听到这个事件的发生,幸好Android提供了这样的机制,利用View类中的getViewTreeObserver方法,可以获取到指定View的观察者,在绘制控件前的一刹那进行回调,这样速度上又不耽误,得到的数据由是准确的,但此方法在之后可能会被反复调用,因此需要加入限制,普通需求下,只计算一次就够了,代码如下(此代码在OnCreate回调函数中验证通过,实时上,因为它是监听器,所以发生事件时已经和OnCreate无关了):
方法一:(它的回调方法会调用很多次,并且滑动TextView的时候任然会调用,所以不建议使用)2.3.x和4.0.4验证通过
- ViewTreeObserver vto=p_w_picpathView222.getViewTreeObserver();
- vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- int height = p_w_picpathView222.getHeight();
- int width = p_w_picpathView222.getWidth();
- int meansureH=p_w_picpathView222.getMeasuredHeight();
- int meansureW=p_w_picpathView222.getMeasuredWidth();
- testView.append("\npre"+" height"+height+",width"+width);
- testView.append("\npre"+"\n measureH"+meansureH+",measureW"+meansureW);
- return true; //这里返还为falsejian
- }
- }); //虽然是转载,但已验证,可行,此处得到的measureHeight和height值相同
方法二:
仅触发一次,建议使用,个人认为是最好的方式,是否有其他弊端不明显,2.3.x和4.0.4验证通过
- ViewTreeObserver vto2 = p_w_picpathView222.getViewTreeObserver();
- vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- p_w_picpathView222.getViewTreeObserver()
- .removeGlobalOnLayoutListener(this);
- testView.append("\n global" + " height"
- + p_w_picpathView222.getHeight() + ",width"
- + p_w_picpathView222.getWidth());
- testView.append("\n global" + "measureH"
- + p_w_picpathView222.getMeasuredHeight() + ",measureW"
- + p_w_picpathView222.getMeasuredWidth());
- }
- });
方法三:不建议使用,使用getHeight和getWidth得到的值仍然是0;getMeasuredHeight得到的值与最终在其他方法中得到的height和width值不同,个人验证认为是无效的
- int w = View.MeasureSpec.makeMeasureSpec(0,
- View.MeasureSpec.UNSPECIFIED);
- int h = View.MeasureSpec.makeMeasureSpec(0,
- View.MeasureSpec.UNSPECIFIED);
- p_w_picpathView222.measure(w, h);
- int mHeight = p_w_picpathView222.getMeasuredHeight();
- int height = p_w_picpathView222.getHeight();
- int mWidth = p_w_picpathView222.getMeasuredWidth();
- int width = p_w_picpathView222.getWidth();
- testView.append("\n measere Height" + height + ",width" + width);
- testView.append("\n measere MeasuredHeight" + mHeight
- + ",MeasuredHeight" + mWidth);
以下是验证截图: