给RecyclerView 添加HeadView

本文介绍如何在RecyclerView中添加HeadView。由于RecyclerView本身不提供类似ListView的addHeadView方法,我们需要通过自定义实现。核心思路是利用getItemViewType方法来判断加载不同布局。首先准备AdaperParam Bean,然后在适配器中根据是否有头部布局进行判断。最后通过代码实现,此处使用了InitRecyclerView工具类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ListView为我们提供了addHeadView方法添加头部,RecyclerView没有该方法,下面我们来做这个工作。主要的思路还是根据getItemViewType的返回值加载不同的布局文件。

第一步:准备bean——AdaperParam,适配器需要的几个参数,如下

<span style="font-size:14px;">package com.dfsebook.myrecycleradapter.bean;

import java.util.List;


public class AdapterParam <T,V>{

    private V headData;//头部绑定数据

    private List<T> mDatas;//items绑定数据

    private int headLayoutId;//头部对应的布局文件

    private int itemLayouyId;//item对应的布局文件

    private int headBrId;//头部对应的资源

    private int itemBrId;//item对应的资源

    public V getHeadData() {
        return headData;
    }

    public void setHeadData(V headData) {
        this.headData = headData;
    }

    public List<T> getmDatas() {
        return mDatas;
    }

    public void setmDatas(List<T> mDatas) {
        this.mDatas = mDatas;
    }

    public int getHeadLayoutId() {
        return headLayoutId;
    }

    public void setHeadLayoutId(int headLayoutId) {
        this.headLayoutId = headLayoutId;
    }

    public int getItemLayouyId() {
        return itemLayouyId;
    }

    public void setItemLayouyId(int itemLayouyId) {
        this.itemLayouyId = itemLayouyId;
    }

    public int getHeadBrId() {
        return headBrId;
    }

    public void setHeadBrId(int headBrId) {
        this.headBrId = headBrId;
    }

    public int getItemBrId() {
        return itemBrId;
    }

    public void setItemBrId(int itemBrId) {
        this.itemBrId = itemBrId;
    }
}</span>
第二步:改写上篇Adapter

<span style="font-size:14px;">package com.dfsebook.myrecycleradapter.adapter;

import android.databinding.DataBindingUtil;
import android.databinding.ViewDataBinding;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.dfsebook.myrecycleradapter.bean.AdapterParam;

public class WithItemClickAdapter<T>
        extends RecyclerView.Adapter<WithItemClickAdapter.ViewHolder>{

    public static final int TYPE_HEADER = 0;

    public static final int TYPE_NORMAL = 1;

    private AdapterParam adapterParam;

    private ItemClickLister itemClickLister;

    public void setItemClickLister(ItemClickLister itemClickLister) {
        this.itemClickLister = itemClickLister;
    }

    public WithItemClickAdapter(AdapterParam adapterParam) {
        this.adapterParam = adapterParam;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        ViewDataBinding binding;
        if (viewType == TYPE_HEADER)
            binding = DataBindingUtil.inflate(inflater,adapterParam.getHeadLayoutId(), parent, false);
        else
            binding = DataBindingUtil.inflate(inflater, adapterParam.getItemLayouyId(), parent, false);
        ViewHolder viewHolder = new ViewHolder(binding.getRoot());
        viewHolder.setBinding(binding);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(WithItemClickAdapter.ViewHolder holder, int position) {
        if (adapterParam.getHeadLayoutId() == 0)
            holder.getBinding().setVariable(adapterParam.getItemBrId(), adapterParam.getmDatas().get(position));
        else {
            if (position == 0)
                holder.getBinding().setVariable(adapterParam.getHeadBrId(), adapterParam.getHeadData());
            else
                holder.getBinding().setVariable(adapterParam.getItemBrId(), adapterParam.getmDatas().get(position - 1));
        }
        holder.getBinding().executePendingBindings();
    }

    @Override
    public int getItemCount() {
        if (adapterParam.getHeadLayoutId() == 0)
            return adapterParam.getmDatas() == null ? 0 : adapterParam.getmDatas().size();
        else
            return adapterParam.getmDatas() == null ? 1 : adapterParam.getmDatas().size() + 1;
    }

    @Override
    public int getItemViewType(int position) {
        if (adapterParam.getHeadLayoutId() > 0)
            return position == 0 ? TYPE_HEADER : TYPE_NORMAL;
        else
            return TYPE_NORMAL;
    }

    public class ViewHolder extends RecyclerView.ViewHolder
            implements View.OnClickListener{

        private View itemView;

        private ViewDataBinding binding;

        public ViewDataBinding getBinding() {
            return binding;
        }

        public void setBinding(ViewDataBinding binding) {
            this.binding = binding;
        }

        public ViewHolder(View itemView) {
            super(itemView);
            this.itemView = itemView;
            this.itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            if(itemClickLister != null)
                itemClickLister.onItemClick(getLayoutPosition());
        }
    }

    public interface ItemClickLister{
        void onItemClick(int position);
    }
}</span>

这里边加了adapterParam.getHeadLayoutId()是否为0的判断,也就是有没有添加头部,此文中虽然我们是为RecyclerView添加头部,但我想的是一个通用的类,所以加入了上述判断。

第三步:代码实现,仍让使用上篇的InitRecyclerView工具类

package com.dfsebook.myrecycleradapter.activity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.widget.Toast;

import com.dfsebook.myrecycleradapter.BR;
import com.dfsebook.myrecycleradapter.R;
import com.dfsebook.myrecycleradapter.adapter.WithItemClickAdapter;
import com.dfsebook.myrecycleradapter.bean.AdapterParam;
import com.dfsebook.myrecycleradapter.bean.Student;
import com.dfsebook.myrecycleradapter.utils.InitRecyclerView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity
        implements WithItemClickAdapter.ItemClickLister{

    private List<Student> students;

    private AdapterParam adapterParam;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.show_list);
        InitRecyclerView.initLinearLayoutVERTICAL(this,recyclerView);
        students = new ArrayList<>();
        Student student = new Student(R.drawable.tx2,"Kate");
        students.add(student);
        student = new Student(R.drawable.tx3,"Alen");
        students.add(student);
        student = new Student(R.drawable.tx4,"Johnson");
        students.add(student);
        student = new Student(R.drawable.tx5,"Make");
        students.add(student);

        adapterParam = new AdapterParam();
        adapterParam.setHeadLayoutId(R.layout.head_item);
        adapterParam.setItemLayouyId(R.layout.student_item);
        adapterParam.setHeadBrId(BR.head);
        adapterParam.setItemBrId(BR.student);
        adapterParam.setHeadData("welcome!");
        adapterParam.setmDatas(students);
        WithItemClickAdapter adapter = new WithItemClickAdapter<>(adapterParam);
        adapter.setItemClickLister(this);
        recyclerView.setAdapter(adapter);
    }

    @Override
    public void onItemClick(int position) {
        if(adapterParam.getHeadLayoutId() == 0)
            Toast.makeText(MainActivity.this, students.get(position).getName(), Toast.LENGTH_SHORT).show();
        else {
            if (position > 0)
                Toast.makeText(MainActivity.this, students.get(position - 1).getName(), Toast.LENGTH_SHORT).show();
            else
                Toast.makeText(MainActivity.this, "click header", Toast.LENGTH_SHORT).show();
        }
    }

基本功能就实现了,但当我们更改RecyclerView的LayoutManager为GridLayoutManager及StaggeredGridLayoutManager时,头部出现怪异现象,具体可以参看 亓斌的这篇文章  。在这儿引用这位大仙的代码,在Adapter中重写下面两个方法:

 

 @Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if(manager instanceof GridLayoutManager) {
            final GridLayoutManager gridManager = ((GridLayoutManager) manager);
            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    return getItemViewType(position) == TYPE_HEADER
                            ? gridManager.getSpanCount() : 1;
                }
            });
        }
    }

    @Override
    public void onViewAttachedToWindow(WBJAdapter.ViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
        if(lp != null
                && lp instanceof StaggeredGridLayoutManager.LayoutParams
                && holder.getLayoutPosition() == 0) {
            StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
            p.setFullSpan(true);
        }
    }
再试正常了,下一篇我们解决item不一致的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值