Android控件绘制完成原来是这样的

实际开发中经常会碰到需要获取某个控件的宽度和高度的情况,但是在实际测试中我们在Activity的启动中期函数中废了老大劲了,我们发现是这样的

OnCreate=>>>>>>>>>width==0,height==0 onStart=>>>>>>>>>width==0,height==0
onResume=>>>>>>>>>width==0,height==0

这可不就傻眼了,裤子都脱了,你就给我看这个。好吧我们再尝试一下,试一试Activity的那些Hook方法内在什么时候width与height在那个方法内不为0,我们终于有发现了:

OnCreate=>>>>>>>>>width==0,height==0
onStart=>>>>>>>>>width==0,height==0
onPostCreate=>>>>>>>>>width==0,height==0
onResume=>>>>>>>>>width==0,height==0
onPostResume=>>>>>>>>>width==0,height==0
onAttachedToWindow=>>>>>>>>>width==0,height==0
onWindowFocusChanged=>>>>>>>>>width==222,height==58

是不是感觉有种千呼万唤始出来的感觉,原来在onWindowFocusChange()`方法调用的时候完成了控件的绘制。有的哥们肯定要开心了,这问题就解决了,我复写onWindowFocusChanged()方法,在这个方法内是获取控件的宽度和高度就可以了。当然这个方案在解决Activity内的控件获取高度的时候不失为一个不错的方案,代码量少,逻辑清晰。但是,问题又来了,虽然在 onWinodwsFocusChanged() 函数中,可以得到正确的控件尺寸。但这只在 Activity 中奏效,而在 Fragment 中,该方法并不能生效。那我们又该怎么在适当的时候获取控件的宽度和高度呢?
下面给大家提供两种可行的解决方案:

  • 使用 ViewTreeObserver 提供的 Hook 方法。
@Override
protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        hello_world_tv = (TextView)       this.findViewById(R.id.hello_world_tv);
        // 获取View的观察者
        final ViewTreeObserver observer = hello_world_tv.getViewTreeObserver();
        // 给观察者添加布局监听器
        observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

            @SuppressWarnings("deprecation")
            @SuppressLint("NewApi")
            @Override
            public void onGlobalLayout() {
                getWidthAndHeight("onGlobalLayout");
                final int version = VERSION.SDK_INT;
                /* * 移除监听器,避免重复调用 */
                // 判断sdk版本,removeGlobalOnLayoutListener在API 16以后不再使用
                if (version >= 16) {
                    observer.removeOnGlobalLayoutListener(this);
                } else {
                    observer.removeGlobalOnLayoutListener(this);
                }

            }
        });
    }

该方法在 onGlobalLayout() 方法将在控件完成绘制后调用,因而可以得到正确地结果。该方法在 Fragment 中,也可以使用。
- 使用 View 的 post() 方法

    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        hello_world_tv = (TextView) this.findViewById(R.id.hello_world_tv);
        hello_world_tv.post(new Runnable() {

            @Override
            public void run() {
                getWidthAndHeight("post");
            }
        });
    }

这种方法是比较简单并可靠的做法
经过这么一番折腾,我们可以得出android中控件的高度和宽度需要绘制完成后才能获取到。那么获取的方法有:
1.Acyivity内通过复写onWinodwsFocusChanged()方法,在这个方法内去获取控件的相关属性(Fragment内不适用)
2.最优雅的做法是调用View的post()方法
3.使用 ViewTreeObserver 注册 OnGlobalLayoutListener

你可能感兴趣的:(android)