Android 正确获取View的宽和高

Android 在实际开发过程中,我们可能经常要获取View的宽和高,那么如何来正确获取一个View的宽和高呢。

View提供了getWidth(),getHeight(),getMeasureWidth(),getMeasureHeight()
方法来获取View的宽和高,getWidth(),getHeight()获取的是View最终显示的宽和高
也即实际宽和高,而getMeasureWidth(),getMeasureHeight()获取的是View测量后的宽和高,一般情况下getMeasureWidth(),getMeasureHeight()和getWidth(),getHeight()的值是一样的,但不是一定一样。
那么在Activity中是不是只要调用view的上面方法就能正确的获取到View的宽和高,你会发现,在Activity的onCreate(),onStart(),onResume()生命周期中调用上述方法获取到
View的宽和高都是0。这是因为在Activity上面的生命周期函数中,View还没有测量,和布局好,任何一个View的绘制都要经过onMeasure()测量,onLayout()布局,onDraw()绘制 这三个过程,而getWidth(),getHeight()获取的是View的实际宽和高,必须要在onLayout之后才能获取到View的宽和高,getMeasureWidth()和getMeasureHeight()必须要在onMeasure()之后才能获取到View的测量的宽和高。

下面来看看到底如何正确的获取到View的宽和高

(1)在Activity的onWindowFocusChanged(boolean hasFocus)方法中通过 getWidth(),getHeight();getMeasureWidth(),getMeasureHeight()可以获取到View的宽和高。

onWindowFocusChanged(boolean hasFocus)是在Activity当前Window获取焦点,失去焦点时,会回调这个方法,当Activity的获取到焦点时,其中的View是已经完成了onMeasure()测量和onLayout()布局,所以可以正确获取到View的宽和高。
但是要注意的是,只要Activity的当前Window获取焦点或者失去焦点都会回调该方法,
所以要注意的是判断一下只在第一次获取到焦点时获取View的宽和高

  @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if(mFirstFocus){
            mFirstFocsu=false;
            Log.e(TAG, "onWindowFocusChanged: " + view.getWidth() + "," + view.getHeight());
            Log.e(TAG, "onWindowFocusChanged: " + view.getMeasuredWidth() + "," + view.getMeasuredHeight());
        }
    
    }

(2)View 的 post(Runnable action) 方法里可以通过上述方法获取到View的宽和高。
View的post(Runnable action) 方法是添加一个操作到队列末尾,当等到View attachToWindow时调用。,当View attachToWindow,已经进行了onMeasure()和onLayout()所以可以获取到宽高。

view.post(new Runnable(){
         //获取View的宽和高操作
          Log.e(TAG, "onCreate: "+view.getWidth()+","+view.getHeight());
          Log.e(TAG, "onCreate: "+view.getMeasuredWidth()+","+view.getMeasuredHeight());
    });

(3)使用 View的 measure(int widthMeasureSpec, int heightMeasureSpec) 测量 View
的宽高后,获取View测量的宽高。

测量后就可以调用getMeasureWidth()和getMeasureHeight()来获取ViewC测量的宽和高。

view.measure(View.MeasureSpec.UNSPECIFIED,View.MeasureSpec.UNSPECIFIED);
Log.e(TAG, "onCreate: "+view.getMeasuredWidth()+","+view.getMeasuredHeight());

(4)ViewTreeObserver. OnPreDrawListener
给View添加onPreDrawListener监听,在View将要绘制时,通过上述方法获取View的宽和高,因为View将要绘制时,已经经过了onMeasure(),onLayout(),所以可以获取到
View的宽和高。但是onPreDrawListener可能会被回调多次,所以注意移除。

view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                Log.e(TAG, "onCreate: "+view.getWidth()+","+view.getHeight());
                Log.e(TAG, "onCreate: "+view.getMeasuredWidth()+","+view.getMeasuredHeight());
                //移除监听
                view.getViewTreeObserver().removeOnPreDrawListener(this);
                return false;
            }
        });  

(5)ViewTreeObserver. OnDrawListener
给View添加OnDrawListener监听,在View绘制时,通过上述方法获取View的宽和高,
OnPreDrawListener 和 OnPreDrawListener使用一样,注意移除
(6)ViewTreeObserver. OnGlobalLyoutListener 在View的布局和可见性发生改变时
会回调。 使用和OnPreDrawListener,OnDrawListener一样,也会回调多次,注意移除。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值