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不一致的情况。