1107-如何在Activity启动时,获取到布局中的View正确的宽高?



先来考虑一个简单的功能需求:Activity启动时,获取一个文本框的长宽值

你第一反应可能会这样获取:




    

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    TextView tvTest = (TextView) findViewById(R.id.tv_test);
    int height = tvTest.getHeight();
    int width = tvTest.getWidth();
    Log.e("log", "height=" + height + "; width=" + width);
}

但没有获取到

11-07 19:55:22.377 17988-17988/com.example.david.viewdraw E/log: height=0; width=0

原因是什么呢?

View的初始化分为测量、布局、绘制三个步骤。当View的测量步骤完成后,才能获取到其真实的长宽值。而view的初始化和Activity的启动不是同步执行的,因此无法确保在onCreate、onStart或onResume时,view的测量步骤已经完成。如果没有完成,则只能获取到默认值0。

好在还可以用其他方式获取。

Activity/View#onWindowFocusChanged.

Activity启动后,当执行到onWindowFocusChanged方法时,view的初始化已经完成,因此可以获取到其正确的长宽值。

需要注意的是,onWindowFocusChanged方法在Activity的窗口得到焦点和失去焦点时都会被调用,因此当Activity多次的进行onResume和onPause时,onWindowFocusChanged也会多次调用。

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        int height = mTvTest.getHeight();
        int width = mTvTest.getWidth();
        Log.e("log", "height=" + height + "; width=" + width);
    }
}

11-08 08:27:55.927 25368-25368/com.example.david.viewdraw E/log: height=65; width=258 .

view.post(runnable)

view的post方法可以将Runnable投递到消息队列的末尾,而当Looper来调用时,view的初始化已经完成了。

@Override
protected void onStart() {
    super.onStart();
    mTvTest.post(new Runnable() {
        @Override
        public void run() {
            int height = mTvTest.getHeight();
            int width = mTvTest.getWidth();
            Log.e("log", "height=" + height + "; width=" + width);
        }
    });
}

你可能感兴趣的:(1107-如何在Activity启动时,获取到布局中的View正确的宽高?)