Activity获取控件宽高的最佳时机和方法

Activity获取控件宽高的最佳时机和方法

我们在做android UI方面开发的时候,获取某一个控件宽高是不可避免的事情,获取view的宽高android提供有现成的方法View.getWidth()和View.getHeight(),但是如果获取时机不对,我们获取到的宽高值会为0.那么什么时候调用才能获取到正确的值呢?

我们都知道只有在View的onlayout方法执行完之后,其宽高值才能确定,而在Activity中,有很多生命周期相关的方法onCreate、onStart、onResume,哪个方法是在onLayout之后执行的呢?我们首先会想到onResume方法里面是不是能获取到,我们来测试一下。界面布局如下

<LinearLayout
   
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
   
android:layout_height="match_parent">

   <com.example.localuser.retrofittest.Drawable.MyDrawableView
       
android:layout_width="400dp"
       
android:layout_height="400dp"
       
android:id="@+id/drawable_view"
       
android:background="@android:color/darker_gray"/>
</LinearLayout>

Acitivity的代码如下:

public class DrawableActivity extends AppCompatActivity {
    public static String TAG_PREX = "DrawableActivity--";
    private String TAG = TAG_PREX+getClass().getSimpleName();
    private MyDrawableView myDrawableView;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        Log.d(TAG,"onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drawable_main);
        myDrawableView = findViewById(R.id.drawable_view);
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG,"onResume()");
        Log.d(TAG,"myDrawableView.getWidth() = "+myDrawableView.getWidth()+",myDrawableView.getHeight() = "+myDrawableView.getHeight());
    }
}

为了结合View的绘制流程,我自定义一个ImageView:

public class MyDrawableView extends android.support.v7.widget.AppCompatImageView {
    private String TAG = DrawableActivity.TAG_PREX+getClass().getSimpleName();
    public MyDrawableView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.d(TAG,"onMeasure()");
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        Log.d(TAG,"onLayout()");
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d(TAG,"onDraw()");
    }
}

运行日志如下:


从日志可以看出,Activity的resume方法执行完的时候,View的onLayout方法还未执行,在onResume方法是获取不到View的宽高的。那么在onResume之前的生命周期方法更不用提了。那么我们应该怎么获取呢,其实Activity有一个生命周期方法onWindowFocusChanged(),这个方法会在View.onLayout()方法之后执行,我们修改修改一下Activity,运行日志如下:


从日志可以看出,在onWindowFocusChanged()的确可以正确获取到view的宽和高。

另外还有一种方法,就是利用View.post(Runable)方法,用法如下:

myDrawableView.post(new Runnable() {
    @Override
    public void run() {
        Log.d(TAG,"view.post.run");
        Log.d(TAG,"myDrawableView.getWidth() = "+myDrawableView.getWidth()+",myDrawableView.getHeight() = "+myDrawableView.getHeight());
    }
});

post方法可以用在Activity的任何生命周期中,甚至在onCreate中用都可以,运行日志如下:


猜你喜欢

转载自blog.csdn.net/baidu_27196493/article/details/80596244