android View 绘制完成监听

//view重绘时回调
view.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {		
	@Override
	public void onDraw() {
	// TODO Auto-generated method stub
		
	}
});
//布局的状态发生变化或者可见性发生变化才会调用
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
	@Override
	public void onGlobalLayout() {
	    //处理完后remove掉,至于为什么,后面有解释
		view.getViewTreeObserver().removeOnGlobalLayoutListener(this);	
	}
});

通过源码追溯进去,找到ViewTreeObserver这个类,里面有很多interface,都是用来追踪View的各种状态变化的。 
找到OnGlobalLayoutListener

/**
     * Interface definition for a callback to be invoked when the global layout state
     * or the visibility of views within the view tree changes.
     */
    public interface OnGlobalLayoutListener {
        /**
         * Callback method to be invoked when the global layout state or the visibility of views
         * within the view tree changes
         */
        public void onGlobalLayout();
    }

注释的大概意思就是这个回调在布局状态和可见状态发生变化时回调,所以准确的说,这个不是监听View的加载完成,而是监听布局变化的。 

我们来测试一下。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.myapplication.MainActivity">

    <Button
        android:onClick="test"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="test"/>

    <TextView
        android:id="@+id/tv_test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="测试"/>
</LinearLayout>
public class MainActivity extends AppCompatActivity {

    TextView tv_test;
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        tv_test = (TextView)findViewById(R.id.tv_test);
        //app切换到后台,再点开会调用一次,屏幕关闭运行程序会调用两次
        tv_test.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Log.e(TAG, "onGlobalLayout: ");
            }
        });
    }



    public void test(View v){
        //改变可见性,调用一次
//        tv_test.setVisibility(View.GONE);
        //改变文字布局,没有效果
//        tv_test.setGravity(Gravity.CENTER);

        //修改控件大小,调用一次
//        LinearLayout.LayoutParams para = (LinearLayout.LayoutParams) tv_test.getLayoutParams();
//        para.height = 200;
//        para.weight = 100;
//        tv_test.setLayoutParams(para);

        //修改layoutgravity,这个是在LayoutParams中,调用一次
        LinearLayout.LayoutParams para = (LinearLayout.LayoutParams) tv_test.getLayoutParams();
        para.gravity = Gravity.CENTER_HORIZONTAL;
        tv_test.setLayoutParams(para);
    }
}

运行程序,得到从android monitor中可以看到,启动后调用了三次onGlobalLayout,很奇怪,为什么是三次?后来有一次屏幕锁了,发现调用了两次。经过测试,app退到后台后重新进入会调用一次,屏幕锁屏后重新打开会调用两次(小米两次,努比亚1次),其中一次猜测是控件的可见性改变了。 

通过按键的测试,分别修改控件的可见性和布局,都会调用一次,修改控件内部布局,不会调用,同时修改布局和可见性,只调用一次。

到此三次之谜依旧没有解决,不过,可以肯定的是,这个会重复 
调用多次,使用的时候需要注意。解决的办法就是第一次回调后,就把回调remove掉,如:gv_test.getViewTreeObserver() 
.removeOnGlobalLayoutListener(this);
 

发布了513 篇原创文章 · 获赞 2668 · 访问量 1311万+

猜你喜欢

转载自blog.csdn.net/jdsjlzx/article/details/100042988
今日推荐