2017-04-19 36 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無需佈局()當滾動將提高其效率