前边说过了RecyclerView的使用,这时候可能满足不了我们的开发需求。list view 可以实现头部添加,那么RecyclerView 也一样可以实现。系统没有为我们提供源生的方法来实现这步骤; 这时候就需要来实现
这里我们的解决方案和网上你能搜到的大多数方案一样,是通过控制Adapter的itemType来设置的,思路就是根据不同的itemType去加载不同的布局。这时候只需要指定加载在item 的 第零位置即可 ;这时候我们我们模仿list view ,一样吧添加的布局写在activity 里,这时候布局要进入到适配器,就需要适配新设置一个方法来把布局传传递进来,有了这样的思路就可以去实现了;
在原有适配器的基础上,
1 定义两个常量,来为不同布局做标记,在定义一个view 来作为要添加的布局;
View headView;
static final int TYPE_HODE = 0;
static final int TYPE_NOMAL = 1;
2 我们还需要添加一个方法,来供activity 调用,传入view
并且调用系统的 notifyItemInserted(); 让插入的位置在第 0 位
该方法在 notifyDataSetChanged();之前掉用
public void setHeadView(View headView) {
this.headView = headView;
notifyItemInserted(0);//在position位置插入数据的时候更新
}
3 因为是和list view 实现多布局一样, 所以我们需要重写 getItemViewType ();
在该方法返回不同布局样式(是我们做的标记) 默认为没添加头部
@Override
public int getItemViewType(int position) {
if (headView == null) return TYPE_NOMAL;
if (position == 0) return TYPE_HODE;
return TYPE_NOMAL;
}
4 为了方便我们后边使用,我们这里还需要 定义一个方法,来计算item 下标,因为添加了头部的布局,所以 position-1
public int getRealPosition(RecyclerView.ViewHolder holder) {
int position = holder.getLayoutPosition();
return headView == null ? position : position - 1;
}
4 为了满足添加头部布局,和没有添加头部布局可以使用同样的adapter
接下来就需要改造源来的适配器三个方法,
分别给他们判断,默情况是没有加载头部。
具体实现看完整代码
activity
public class RecyclerViewActivity extends Activity {
RecyclerView recyclerRV;
List<Photo> photos = new ArrayList<>();
RecyclerViewAdapter recyclerViewAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recyclerview);
recyclerRV = (RecyclerView) findViewById(R.id.recyclerRV);
initData();
//设置布局显示方式
LinearLayoutManager mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyclerRV.setLayoutManager(mLayoutManager);
//设置添加删除item时候的动画
recyclerRV.setItemAnimator(new DefaultItemAnimator());
recyclerViewAdapter = new RecyclerViewAdapter(this);
recyclerRV.setAdapter(recyclerViewAdapter);
setHeader();
//接口回调实现监听
recyclerViewAdapter.setListViewClick(new RecyclerViewAdapter.ListViewClick() {
@Override
public void listItemClick(View view, int position) {
Toast.makeText(RecyclerViewActivity.this, "点击了" + position, Toast.LENGTH_SHORT).show();
}
@Override
public void listItemLongClick(View view, int position) {
Toast.makeText(RecyclerViewActivity.this, "长按了" + position, Toast.LENGTH_SHORT).show();
}
});
}
//头部添加
private void setHeader() {
View header = LayoutInflater.from(this).inflate(R.layout.rv_item, null);
recyclerViewAdapter.setHeadView(header);
// 这里可以获得的头部布局具体控件,并进行操作
}
private void initData() {
for (int i = 0; i < 20; i++) {
Photo photo = new Photo();
photo.setName("名字");
photo.setAge("15");
photos.add(photo);
}
}
}
adapter
package com.xiang.generalexercisesproject;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
List<Photo> photos = new ArrayList<>();
Context context;
ListViewClick listViewClick;
//定义 判断要传入的布局标记
static final int TYPE_HODE = 0;
static final int TYPE_NOMAL = 1;
//要添加的布局
View headView;
public RecyclerViewAdapter(Context context) {
this.context = context;
}
//从activity传入需要 添加的布局
public void setHeadView(View headView) {
this.headView = headView;
notifyItemInserted(0);//在position位置插入数据的时候更新
}
//返回 item 布局个数 添加的头也是一个item 因此需要加1
@Override
public int getItemCount() {
return headView == null ? photos.size() : photos.size() + 1;
}
// 返回多布局样式 ,与定义type 标记一样对应
@Override
public int getItemViewType(int position) {
if (headView == null) return TYPE_NOMAL;
if (position == 0) return TYPE_HODE;
return TYPE_NOMAL;
}
// 生成为每个Item inflater出一个View, 法返回的是一个ViewHolder
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (headView != null && viewType == TYPE_HODE) {
return new MyViewHolder(headView);}
else {
View holder = LayoutInflater.from(context).inflate(R.layout.item_recycle, parent, false);
return new MyViewHolder(holder);}
}
//该方法主要是对item 下标进行判断,当添加有头,position - 1 ,在以后调用就不用考虑position所在位置
public int getRealPosition(RecyclerView.ViewHolder holder) {
int position = holder.getLayoutPosition();
return headView == null ? position : position - 1;
}
//对获得布局里控件进行操作,传入数据,监听
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
if (getItemViewType(position) == TYPE_HODE) {
return;
}
final int pos = getRealPosition(holder);
if (holder instanceof MyViewHolder) {
holder.nameTV.setText(photos.get(pos).getName());
holder.ageTV.setText(photos.get(pos).getAge());
}
//短按
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//自己定义变量是因为自己可以可以增加头和未 这里的点击位置保持
int pos = holder.getLayoutPosition();
listViewClick.listItemClick(holder.itemView, pos);
}
});
//长按
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
int pos = holder.getLayoutPosition();
listViewClick.listItemLongClick(holder.itemView, pos);
return false;
}
});
}
//内部类初始化item 布局控件
class MyViewHolder extends RecyclerView.ViewHolder {
TextView nameTV;
TextView ageTV;
public MyViewHolder(View itemView) {
super(itemView);
if (itemView == headView) return;
nameTV = (TextView) itemView.findViewById(R.id.nameTV);
ageTV = (TextView) itemView.findViewById(R.id.ageTV);
}
}
//定义接口
public interface ListViewClick {
void listItemClick(View view, int position);
void listItemLongClick(View view, int position);
}
//定义方法,暴露接口(参数为接口方法)
public void setListViewClick(ListViewClick listViewClick) {
this.listViewClick = listViewClick;
}
}
以上就完成了头部布局的添加