2011-10-24 26 views
19

我已經在ListView中啓用了快速滾動功能,它有一個不可選擇的headerview。如果向下滾動列表並將快速滾動指點拖到頂部,列表僅滾動回第一個元素,但不滾動到標題視圖。拖動列表,按預期工作。FastScroller只滾動回第一個元素,而不滾動到標題視圖

截圖1:截圖中的紅色區域是標題視圖。
屏幕截圖2:如果您將拇指拖到頂部,則只能看到第一個元素,並且標題視圖仍位於上方。

ListView lv = (ListView) findViewById(R.id.listView); 
lv.addHeaderView(getLayoutInflater().inflate(R.layout.view,null), null, false); 

 

<ListView 
    android:layout_height="fill_parent" 
    android:id="@+id/listView" 
    android:layout_width="fill_parent" 
    android:fastScrollEnabled="true" 
></ListView> 

我創建了一個演示項目: https://github.com/mikegr/fastscroll-bug

爲什麼拖動滑塊不回頂部滾動?

Red area is a header view dragging thumb does not go back to top

+0

你有沒有發現如何解決這個問題? – clauziere

回答

12

這是FastScroller的故意行爲。當您在ListView上撥打setAdapter時,如果設置了任何標頭,適配器將被包裝在HeaderViewListAdapter中;這就是爲什麼你必須在setAdapter之前致電addHeaderView。然後,在FastScroller代碼,我們可以看到:

if (adapter instanceof HeaderViewListAdapter) { 
     mListOffset = ((HeaderViewListAdapter)adapter).getHeadersCount(); 
     adapter = ((HeaderViewListAdapter)adapter).getWrappedAdapter(); 
    } 

也就是說,得到一個偏移量和使用底層適配器。 mListOffset然後用於設置頂部位置以滾動到快速滾動。那麼這個包裹究竟在哪裏發生?最多,符合市場預期,ListView.addHeaderView,在這裏我們可以看到:

if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) { 
     mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter); 
    } else { 
     mAdapter = adapter; 
    } 

所以我們肯定圍繞着正確的地方尋找。現在,這聽起來像你的目標是沒有你的快速拇指列表標題的偏移行爲,但否則有一個正常的標題列表。要做到這一點,就足夠了(根據我們所看到的代碼)要有FastScroller.mListOffset = 0。這僅在getSectionsFromIndexer中設置,在init中被無條件地調用,並且僅在mListAdapter == null時有條件地在其他幾個函數中有效。如果onSectionsChanged被調用,則mListAdapter僅爲空,因此我們暫時忽略該路徑。

經過大量的挖掘,並與各種反射掛鉤玩,我可以說,沒有辦法做到這一點,即使稍有未來兼容。您可以使用反射來替換HeaderViewListAdapter,以使其位於其標題計數等位置;但這是相當脆弱的。同樣的,你可以將(包可見的)FastScroller與你自己的行爲進行子類化;但mListOffset被廣泛引用,而不是通過getter,所以這比平常更醜。基本上,你遇到了一個事實,即系統不能按照你想要的方式工作。

我毫不猶豫地稱這是一個錯誤,因爲它從代碼中清楚地知道它是故意的行爲。你是否考慮過讓列表的第一個元素只是一個特殊的第一個元素(可能使用自定義WrapperListAdapter,如果需要用於簿記),而不是使用標題機制?

+0

較新的「mListOffset」現在稱爲「mHeaderCount」。我將這兩個設置爲0,一切似乎都很好。毫無疑問,未來的每一次發佈都可能打破這件事 –