2017-04-19 106 views
0

编写自定义的ListView,如:滚动ListView时,为什么在ListView中不调用onLayout方法?

public class MyListView extends ListView { 
    public MyListView(Context context) { 
     super(context); 
    } 

    public MyListView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public MyListView(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) { 
     super.onLayout(changed, l, t, r, b); 
     Log.d("onLayout","onLayout====="); 
    } 
} 

据我所知,当观看布局属性发生变化,以应用更改(invalide()或requestLayout()),其母公司的onLayout方法应该是呼吁并布置其子女。

所以,当我滚动ListView时,其子视图的布局属性已更改,但onLayout根本不会调用。为什么?

+0

检查此解决方案http://stackoverflow.com/questions/23471906/android-when-onlayout-calls –

+0

大概是因为滚动不会改变_layout_,只有ListView的部分是可见的,所以你不(不应该)需要重新布局孩子。更改列表视图占用的_size_将调用onLayout,因为此_would_通常需要重新计算孩子的布局。 – TripeHound

+0

请注意滚动列表视图不会改变它的绑定。尝试在视图下添加视图并切换该视图的可见性以查看“onLayout”获取调用。 –

回答

0

最后我意识到重新布局一个ViewGroup不需要总是调用onLayout()/ layout()方法。ViewGroup中有多种方式来改变视图的位置,但是每个方法都必须调用onDraw()来将改变的位置写入。帧缓冲,以显示它的屏幕(请告诉我是否错了这一点) ListView中,我已经调试源代码,并在滚动的ListView,堆栈跟踪是: `

trackMotionScroll:5023, AbsListView (android.widget) 
scrollIfNeeded:3424, AbsListView (android.widget) 
startScrollIfNeeded:3352, AbsListView (android.widget) 
onTouchMove:3793, AbsListView (android.widget) 
onTouchEvent:3651, AbsListView (android.widget) 
dispatchTouchEvent:9294, View (android.view) 

在trackMotionScroll中,它将调用ViewGroup#offsetChildrenTopAndBottom(incrementalDeltaY)

public void offsetChildrenTopAndBottom(int offset) { 
    final int count = mChildrenCount; 
    final View[] children = mChildren; 
    boolean invalidate = false; 

    for (int i = 0; i < count; i++) { 
     final View v = children[i]; 
     v.mTop += offset; 
     v.mBottom += offset; 
     if (v.mRenderNode != null) { 
      invalidate = true; 
      v.mRenderNode.offsetTopAndBottom(offset); 
     } 
    } 

    if (invalidate) { 
     invalidateViewProperty(false, false); 
    } 
    notifySubtreeAccessibilityStateChangedIfNeeded(); 
} 

这将导致ListView的reLayout。所以我得到了一个结论,你不需要服从框架的measure() - layout() - draw()过程,但只能改变视图的布局属性并使其无效,它也会改变视图的布局。 我猜ListView无需布局()当滚动将提高其效率