列表頂部的標籤懸浮大家應該都知道,但「頂上去」是個啥玩意?
看一下效果圖就知道了,注意看頂部的懸浮標籤切換時的效果:
這是我在之前一個自定義側邊索引欄的專案上修改的,對側邊索引欄的實現有興趣的可以看一下之前的文章:自定義側邊快速索引欄
思路是這樣子的:
- 佈局裡面增加一個和索引 item 長的一樣的 view,預設顯示列表第一項的索引字母。
- 監聽列表的滑動,當列表可見的第二項是索引 item 時,計算並更新懸浮 view 的 y 座標,讓它處於索引 item 的上方。
- 監聽列表的滑動,當列表可見第一項發生變化時,更新懸浮 view 顯示的字母為當前可見第一項的索引字母。
感覺比想象中簡單啊。可以看出邏輯都是在滑動事件裡,我們用 RecyclerView 的 addOnScrollListener 方法監聽列表的滑動事件,在監聽器裡面實現上面的邏輯。說的可能不是很好,看程式碼就知道多簡單了。
監聽器的程式碼如下:
class mScrollListener extends RecyclerView.OnScrollListener {
private int mFlowHeight;
private int mCurrentPosition = -1;
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
mFlowHeight = vFlow.getMeasuredHeight();
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
View view = layoutManager.findViewByPosition(firstVisibleItemPosition + 1);
if (view != null) {
if (view.getTop() <= mFlowHeight && isItem(firstVisibleItemPosition + 1)) {
vFlow.setY(view.getTop() - mFlowHeight);
} else {
vFlow.setY(0);
}
}
if (mCurrentPosition != firstVisibleItemPosition) {
mCurrentPosition = firstVisibleItemPosition;
tvFlowIndex.setText(mList.get(mCurrentPosition).getFirstWord());
}
}
/**
* @param position 對應項的下標
* @return 是否為標籤項
*/
private boolean isItem(int position) {
return mAdapter.getItemViewType(position) == MainAdapter.VIEW_INDEX;
}
}
複製程式碼
這樣就已經實現「頂上去」的效果了,妥妥的。
最後說明一下,這個程式碼是使用 RecyclerView 實現的,要是用 ListView 的話是有問題的。ListView 的 item 使用 getTop() 方法,剛開始拿到的應該是 item 距離整個 ListView 最頂部的距離,要都是這樣還好處理,但是複用 item 的時候這個值又發生了變化。
總之就是,在使用 ListView 的時候,我還沒有好的實現方法。要是哪位知道怎麼實現,希望可以留言分享一下,不勝感激!