RecyclerView-->添加頭布局和底布局


效果圖:


參考文章:
Android 優(yōu)雅的為RecyclerView添加HeaderView和FooterView

該功能主要是對(duì)adapter使用了裝飾者模式,具體代碼看下面的分析:

  • HeaderAndFooterActivity.java
public class HeaderAndFooterActivity extends AppCompatActivity {

    @BindView(R.id.recyclerView)
    RecyclerView mRecyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_header_and_footer);
        ButterKnife.bind(this);
        setTitle("添加Header和Footer");
        //創(chuàng)建處理正常數(shù)據(jù)的adapter
        HeaderAndFotterAdapter adapter = new HeaderAndFotterAdapter(this);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        //創(chuàng)建負(fù)責(zé)處理Header和footer的adpapter
        HeaderAndFooterWrapper headerAndFooterWrapper = new HeaderAndFooterWrapper(adapter);
        TextView t1 = new TextView(this);
        t1.setText("Header 1");
        TextView t2 = new TextView(this);
        t2.setText("Header 2");
        TextView t3 = new TextView(this);
        t3.setText("Header 3");
        TextView t4 = new TextView(this);
        t4.setText("Header 4");
        headerAndFooterWrapper.addHeaderView(t1);
        headerAndFooterWrapper.addHeaderView(t2);
        headerAndFooterWrapper.addFooterView(t3);
        headerAndFooterWrapper.addFooterView(t4);
        mRecyclerView.setLayoutManager(linearLayoutManager);
        //RecyclerView的Adapter被賦值為headerAndFooterWrapper,
        // 而正常處理數(shù)據(jù)的adapter在headerAndFooterWrapper中被調(diào)用
        mRecyclerView.setAdapter(headerAndFooterWrapper);
    }
}

上面代碼很簡(jiǎn)單,主要就是初始化兩個(gè)adpater和創(chuàng)建頭布局和底布局。

  • HeaderAndFooterWrapper.java
public class HeaderAndFooterWrapper  extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
    public static final int BASE_ITEM_TYPE_HEADER = 100000;
    public static final int BASE_ITEM_TYPE_FOOTER = 200000;
    private SparseArrayCompat<View> mHeaderViews = new SparseArrayCompat<>();
    private SparseArrayCompat<View> mFooterViews = new SparseArrayCompat<>();

    private RecyclerView.Adapter mInnerAdapter;

    public HeaderAndFooterWrapper(RecyclerView.Adapter innerAdapter) {
        mInnerAdapter = innerAdapter;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (mHeaderViews.get(viewType) != null){
            return new MyViewHolder(mHeaderViews.get(viewType));
        }else if (mFooterViews.get(viewType) != null){
            return new MyViewHolder(mFooterViews.get(viewType));
        }
        return mInnerAdapter.onCreateViewHolder(parent,viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (isHeaderViewPos(position))
            return;
        if (isFooterViewPos(position))
            return;
        mInnerAdapter.onBindViewHolder(holder,position - getHeadersCount());
    }

    @Override
    public int getItemCount() {
        return getHeadersCount() + getFootersCount() + getRealItemCount();
    }

    @Override
    public int getItemViewType(int position) {
        if (isHeaderViewPos(position)){
            return mHeaderViews.keyAt(position);
        }else if (isFooterViewPos(position)){
            return mFooterViews.keyAt(position - getHeadersCount() - getRealItemCount());
        }
        return mInnerAdapter.getItemViewType(position - getHeadersCount());
    }

    /**
     * 獲取正常數(shù)據(jù)的size
     * @return
     */
    private int getRealItemCount(){
        return mInnerAdapter.getItemCount();
    }

    /**
     * 判斷是否是Header
     * @param position
     * @return
     */
    private boolean isHeaderViewPos(int position){
        return position < getHeadersCount();
    }

    /**
     * 判斷是否是Footer
     * @param position
     * @return
     */
    private boolean isFooterViewPos(int position){
        return position >= getHeadersCount() + getRealItemCount();
    }


    public void addHeaderView(View view){
        mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER,view);
    }
    public void addFooterView(View view){
        mFooterViews.put(mFooterViews.size() + BASE_ITEM_TYPE_FOOTER,view);
    }
    private int getHeadersCount(){
        return mHeaderViews.size();
    }
    public int getFootersCount(){
        return mFooterViews.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{
        public MyViewHolder(View itemView) {
            super(itemView);
        }
    }
}

上面我們使用了線性布局,如果我們使用了網(wǎng)格和瀑布流,就有可能出問題咯,比如頭布局不能占據(jù)一行的問題。


下面是關(guān)于適配網(wǎng)格和瀑布流布局的解決方案:
在HeaderAndFooterWrapper.java中重寫下面的方法:

    /**
     * 適配網(wǎng)格布局
     * @param recyclerView
     */
    @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        mInnerAdapter.onAttachedToRecyclerView(recyclerView);
        final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager){
            final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    return isHeaderViewPos(position) || isFooterViewPos(position) ? ((GridLayoutManager) layoutManager).getSpanCount() : 1;
                }
            });
        }
    }

上面只解決了網(wǎng)格布局的,下面我們?cè)贖eaderAndFooterWrapper.java中可以重寫onViewAttachedToWindow方法解決瀑布流的問題。

    @Override
    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {

        mInnerAdapter.onViewAttachedToWindow(holder);
        int position = holder.getLayoutPosition();
        if (isHeaderViewPos(position)||isFooterViewPos(position)){
            ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
            if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams){
                StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
                p.setFullSpan(true);
            }
        }
    }

完整demo地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 又到了更新博文的時(shí)間了,最近在看一本很不錯(cuò)的心理學(xué)書籍,名字叫做 《拖延心理學(xué)》,封面長(zhǎng)下面這樣子 書的內(nèi)容主要是...
    ec95b5891948閱讀 57,895評(píng)論 38 472
  • 【Android 控件 RecyclerView】 概述 RecyclerView是什么 從Android 5.0...
    Rtia閱讀 308,455評(píng)論 27 440
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,039評(píng)論 25 709
  • 昨天早上,出門,竟然發(fā)現(xiàn)前幾天被我放到院子里的花,不但沒死,而且長(zhǎng)的越來越好了,有的還冒出了新葉。 想想,在屋里放...
    成長(zhǎng)之魚閱讀 220評(píng)論 0 0
  • 清晨 咸陽的月光 西安的晨曦 伴著古老的風(fēng)和光降臨 而我登上車 帶著 現(xiàn)代的科技 新潮的思想 看著長(zhǎng)存的天和地到來...
    堅(jiān)志閱讀 387評(píng)論 0 0

友情鏈接更多精彩內(nèi)容