Android ListView的header footer設定visibility gone不起作用

來源:互聯網
上載者:User

標籤:

  常用的ViewGroup,例如LinearLayout,在onMeasure方法內對每個child view執行measure前,會判斷child view的visibility是否為gone。如果是gone,則不對這個child view執行measure操作,即這個child view的高度不被計算在linearLayout的高度裡面。LinearLayout的measureVertical程式碼片段:

if (child.getVisibility() == View.GONE) {    i += getChildrenSkipCount(child, i);    continue;}

  

  view在measure自己時,並不會去判斷自己的Visibility是GONE。這個邏輯操作如上述代碼所示,是在parent view裡面做的。所以當對LinearLayout裡面的一個childView設定Visiblility為gone時,這個view不會被measure,最終也不會被顯示出來。

 

  在使用ListView時,經常會添加一些headerView、footerView。但是當設定headerView、footerView的visibility為gone時,卻發現headerView、footerView雖然沒有顯示出來,但垂直方向其所佔的位置還是被顯示出來了,從而出現了空白地區。網上查到的解決辦法是:不能直接設定headerView、footerView的Visibility為gone。而是要在HeaderView、FooterView外麵包一層parent view(FrameLayout RelativeLayout 都可以),並設定layout_height=“wrap_content”。然後對裡面的childView設定visibility為GONE、VISIBLE都會生效。查看源碼,情況確實如此。

 

  ListView的onMeasure裡面,如果ListView的widthMode、heightMode有一個是unspecified時(應該對應於在XML中沒有對listView設定layout_width、layout_height),會調用方法measureScrapChild。如果沒有unspecified的情況,則會調用measureHeightOfChildren方法,而此方法內部也會調用measureScrapChild方法。查看measureScrapChild方法:

private void measureScrapChild(View child, int position, int widthMeasureSpec) {    LayoutParams p = (LayoutParams) child.getLayoutParams();    if (p == null) {        p = (AbsListView.LayoutParams) generateDefaultLayoutParams();        child.setLayoutParams(p);    }    p.viewType = mAdapter.getItemViewType(position);    p.forceAdd = true;    int childWidthSpec = ViewGroup.getChildMeasureSpec(widthMeasureSpec,            mListPadding.left + mListPadding.right, p.width);    int lpHeight = p.height;    int childHeightSpec;    if (lpHeight > 0) {        childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);    } else {        childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);    }    child.measure(childWidthSpec, childHeightSpec);}

  可以看出,listview在對child view執行measure前,沒有判斷visibility為gone的情況

  再看看裡面的詳細邏輯:

  • lpHeight>0時,說明在xml或者程式裡面設定了一個確定的尺寸,這裡沒有問題;
  • else裡面,設定mode為UNSPECIFIED,就是讓child view自己去決定大小,child view在measure自己時,不會考慮VISIBILITY屬性。

  else包含的邏輯:

  • lpHeight == 0:對應於在xml或者代碼中設定尺寸為0,說明也是不起作用的,最終還是會顯示出空白
  • lpHeight == -1:MATCH_PARENT
  • lpHeight == -2:WRAP_CONTENT

  三種情況,都會根據view實際的內容返回一個wrap_content的尺寸。這裡就解釋了為何設定headerView、footerView的visibility為gone時,會出現空白地區。

 

  如果外麵包一層parent view(例如LinearLayout),並設定layout_height為wrap_content(按上面的分析,設定match_parent也是可以的),listView會調用調用額外的這個parent view的measure方法。而LinearLayout在measure時,會判斷child view的visibility,如果為gone,則會返回0.最終這個額外的parent view返回給list view的尺寸就是0,從而解決了空白地區的問題。

 

  這個問題算是listview的一個feature吧!

Android ListView的header footer設定visibility gone不起作用

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.