Android中获取控件宽和高的方法

第一种:直接获取getWidth()和getHeight()

我们都知道这两个方法在onCreate()方法中得到的数据都是0;

代码:

mTextView = (TextView) findViewById(R.id.textview);
    mWidth = mTextView.getWidth();
    mHeight = mTextView.getHeight();
    Log.d(TAG, "onCreate: width = " + mWidth + "   height = " + mHeight);

布局:

<TextView
    android:id="@+id/textview"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:background="#33ff00ff"
    android:text="Hello World!"/>

log打印:

D/MainActivity: onCreate: width = 0 height = 0

在onResume()方法中得到的数据也是0;

代码:

@Override
    protected void onResume() {
        super.onResume();
        mWidth = mTextView.getWidth();
        mHeight = mTextView.getHeight();
        Log.d(TAG, "onResume: width = " + mWidth + "   height = " + mHeight);
    }

log打印:

D/MainActivity: onResume: width = 0 height = 0

onStart()就不用多说了;我们都知道getWidth()和getHeight(),只有在View布局完成之后才会有值,那么在Activity的生命周期中的哪个方法

中会有值呢? 

答案是:onWindowFocusChanged(boolean hasFocus){}:当Activity的焦点发生改变时调用,他会在onResume()方法执行之后调用。

oncreate()→onResume()→onMeasure()→onLayout()→onWidnowFocusChanged()→.....→onDraw()...

可以看到onWindowFocusChanged()方法是在onLayout()之后执行的,所以getWidth()与getHeight()会得到具体的数值:

代码:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    mWidth = mTextView.getWidth();
    mHeight = mTextView.getHeight();
    Log.d(TAG, "onWindowFocusChanged: width = " + mWidth + "   height = " + mHeight);
}

log打印:

D/MainActivity: onWindowFocusChanged: width = 600 height = 600

控件的实际宽高就是600,记住这个答案!!!(为什么不是200!不明白的可以看一下屏幕密度,dp与px相关的知识)

第二种:手动测量(自己调用measure()方法)

代码:

mTextView = (TextView) findViewById(R.id.textview);
    mTextView.measure( 0,  0);
    int measuredWidth = mTextView.getMeasuredWidth();
    int measuredHeight = mTextView.getMeasuredHeight();
    Log.d(TAG, "onCreate: measuredWidth =" + measuredWidth + "    measuredHeight = " + measuredHeight);

log打印:

D/MainActivity: onCreate: measuredWidth =225 measuredHeight = 57

什么鬼? 看到这个结果我又返回去看了一眼布局 
->android:layout_width=”200dp” 
->android:layout_height=”200dp” 
没毛病啊,这个225和57哪来的? 

接下来,将布局中的HelloWorld *2,改成

android:text="Hello World!Hello World!"

log打印:

onCreate: measuredWidth =450    measuredHeight = 57

对的,你猜的没错,他得到的是内容的大小!!跟你给控件设置的宽高没一毛钱关系(感兴趣的可以自己测一下,我把TextView改成ImageView,宽和高都给的很小或者很大,设置个大的图片,getMeasuredWidth()方法得到的结果都是图片的大小) 

所以,此方法慎用!!!
第三种:观察者模式

观察View的绘制流程,设置OnGlobalLayoutListener监听,布局完成时会调用onGlobalLayout(),在onGlobalLayout()方法里面获取

控件的宽和高 

代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mTextView = (TextView) findViewById(R.id.textview);
    mTextView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mWidth = mTextView.getWidth();
            int measuredHeight = mTextView.getMeasuredHeight();
            mHeight = mTextView.getHeight();
            Log.d(TAG, "onGlobalLayout: width = " + mWidth + "   height = " + mHeight);
        }
    });
 }

log打印:

onGlobalLayout: width = 600 height = 600

第四种:View.post(Runnable action)
代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mTextView = (TextView) findViewById(R.id.textview);

    mTextView.post(new Runnable() {
        @Override
        public void run() {
            mWidth = mTextView.getWidth();
            mHeight = mTextView.getHeight();
            Log.d(TAG, "run: width = " + mWidth + "   height = " + mHeight);
        }
    });

log打印:

run: width = 600   height = 600

解释一下为什么View.post(Runnable action)可以获取到正确的宽高 
先看一下方法执行的时间 
这里用自定义控件,重写onMeasure(),onLayout(),onDraw().方法 
在这些方法中分别测量宽高,并打印时间

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    mWidth = getWidth();
    mHeight = getHeight();
    Log.d(TAG, "onMeasure: width = " + mWidth + "   height = " + mHeight + "时间 : " + System.currentTimeMillis());
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    mWidth = getWidth();
    mHeight = getHeight();
    Log.d(TAG, "onLayout: width = " + mWidth + "   height = " + mHeight + "时间 : " + System.currentTimeMillis());
    super.onLayout(changed, left, top, right, bottom);
}

@Override
protected void onDraw(Canvas canvas) {
    mWidth = getWidth();
    mHeight = getHeight();
    Log.d(TAG, "onDraw: width = " + mWidth + "   height = " + mHeight + "时间 : " + System.currentTimeMillis() );
    super.onDraw(canvas);
}

log打印:

   onResume: width = 0   height = 0时间 : 1484040644793
   onMeasure: width = 0   height = 0时间 : 1484040644819
   onLayout: width = 600   height = 600时间 : 1484040644904
   run: width = 600   height = 600时间 : 1484040644930
   onWindowFocusChanged: width = 600   height = 600时间 : 1484040644930
   onDraw: width = 600   height = 600时间 : 1484040644971

从上面日志的时间可以看出,View.post()中的run方法和onWindowFocusChanged方法几乎是同时执行,都是在onLayout之后,所以都是可以得到控件的宽高的!!! 
还有,getMeasuredHeight()和getMeasuredWidth(),在Layout执行完成后得到的也是控件的宽高了!!!



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值