1. 程式人生 > >RecyclerView粘性頭部控制元件

RecyclerView粘性頭部控制元件

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">最近使用了一個粘性頭部控制元件sticky-headers-recyclerview,期間也遇到了不少問題,稍微介紹一下這個控制元件的使用和問題。</span>

animated gif demo

匯入方法:

compile 'com.timehop.stickyheadersrecyclerview:library:[latest.version.number]@aar'

或者直接引入自己專案,結構如下:


使用方法:

這個控制元件方便之處在於不用大改原Adapter,加入頭部就行了,也不需要用getItemViewType()來判斷ITEM型別。

原Adapter需要implements StickyRecyclerHeadersAdapter,然後重寫以下方法

1、

    @Override
    public long getHeaderId(int position) {
        return getGroupPosition(position);
    }

這個方法是用來固定頭部的,有著相同的HeaderId的Item的頭部將會是同一個,這個ID可以自己設定

getGroupPosition(position)是自定義的方法,用於根據子ITEM的position來獲取伺服器返回的List的父項位置。根據這個特性同時用來當HeaderID。

如果有不是資料裡的特殊的頭部,置頂之類的,可以設定-1之類的。

2、

    @Override
    public ViewHolder onCreateHeaderViewHolder(ViewGroup parent) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_head_choose, parent, false);
        return new HeaderViewHolder(view);
    }
這個很明確,載入佈局檔案就行了。

3、

    @Override
    public void onBindHeaderViewHolder(ViewHolder holder, int position) {
    }
和普通的一樣,繫結資料,要注意的是這個position是子項的,因為此控制元件機制是新增分割線addItemDecoration,所以新增頭部後不會影響原位置。

在Recyclerview中

StickyRecyclerHeadersDecoration headersDecor = new StickyRecyclerHeadersDecoration(adapter); //繫結之前的adapter

adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
            @Override
            public void onChanged() {
                headersDecor.invalidateHeaders();
            }
        });  //重新整理資料的時候回重新整理頭部
新增頭部:
rcv.addItemDecoration(headersDecor);

注意只能新增一次,要更行資料使用
headersDecor.invalidateHeaders();

否則一直會加頭部。

如果你的需求只是顯示粘性頭部,那麼到這裡已經可以顯示了

但是當點選粘性頭部的時候,就會有一些問題了。

<span style="white-space:pre">	</span>//頭部點選事件
        StickyRecyclerHeadersTouchListener touchListener = new StickyRecyclerHeadersTouchListener(rcv, headersDecor);
        touchListener.setOnHeaderClickListener(new StickyRecyclerHeadersTouchListener.OnHeaderClickListener() {
            @Override
            public void onHeaderClick(View header, int position, long headerId) {
                //這邊的坑在於,在頂上的粘性頭部,position和headerId都會是0,這樣就無法獲取到這個頭部的資料了。
                //在這裡我們要用mLayoutManager.findFirstVisibleItemPosition()來獲取到目前頂部子項資料,然後進一步推算出頭部的資料
                //如果進行了頭部資料更新,重新整理頭部headersDecor.invalidateHeaders();
            }
        });
        rcv.addOnItemTouchListener(touchListener);

還有我的頭部因為有小圖片的存在,使用的是Glide載入圖片,結果發現,圖片經常會卡在隱現狀態,或者壓根沒出來,他就這麼卡住了。。。

估計是控制元件本身的bug,後來只能採取取巧的方法

rcv.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                headersDecor.invalidateHeaders();
            }
        });
在滑動的時候,重新整理頭部,就能完全顯示資料了。因為頭部內容其實並不多,所以也不是特別消耗效能。如果大家有更好的方法可以提出來。

專案趕得太緊,只能看到啥用啥了。