引言:问题是这样的,项目里有个功能需要在代码里面获取、计算控件宽度,因此项目里面引入了监听View绘制完成的方法。但是由于该方法的引入,导致页面滑动过程中,绑定了addOnGlobalLayoutListener()监听的控件存在滑动抖动现象。
Android中Activity的生命周期方法与 View的绘制流程方法的执行顺序为oncreate()→onResume()→onMeasure()→onLayout()→onWidnowFocusChanged()→.....→onDraw()...
View.getWidth()/View.getWidth()都需要在onLayout()执行完后才有效,这就是为什么我们在onCreate(onLayout()方法前获取)View.getWidth()/View.getWidth()则为0的原因;OnGlobalLayoutListener 是ViewTreeObserver的内部类,当一个视图树的布局发生改变时,可以被ViewTreeObserver监听到,这是一个注册监听视图树的观察者(observer),在视图树的全局事件改变时得到通知。ViewTreeObserver不能直接实例化,而是通过getViewTreeObserver()获得。
而我遇到的问题正好是在滑动屏幕的时,textview控件就上下抖动。问题其实很简单,滑动页面,textview可见到不可见,不可见到可见,View会被重绘,视图树的布局发生改变,此时OnGlobalLayoutListener会被一直监听,然后不断设置宽高,导致textview抖动现象。解决的办法就是计算出textview宽高后,应及时调用removeOnGlobalLayoutListener()方法清除OnGlobalLayoutListener。
//监听title 的view绘制完成后,获取宽度title.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
LinearLayout.LayoutParams layoutParams = (LayoutParams)viewFlipper.getLayoutParams();
layoutParams.width = AppUtils.getScreenWidth(getContext()) - (title.getWidth() + AppUtils.dip2px(getContext(), 100));
viewFlipper.setLayoutParams(layoutParams);
getViewTreeObserver().removeOnGlobalLayoutListener(this);
}});