高级UI之RecyclerView头部和尾部添加

在ListView中,可以添加头部和尾部,其添加方法也是十分的简单,直接调用listview.addHeaderView(view);listview.addFooterView(view);即可,但在RecyclerView中却没有这样的方法,那么要在RecyclerView中使用这种方法怎么办呢,这就是本文要讲明的地方

原理

查看ListView源代码,得知其头部和尾部,实质上就是对原来的adapter添加了一个头和一个尾,也就是包装了一层,那么我们要在RecyclerView中使用头部和尾部的话,可以按照ListView的方法,依葫芦画瓢做一个头,做一个尾

实现

自定义一个RecyclerView布局,增加头部和尾部的添加方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class WrapRecyclerView extends RecyclerView {

private ArrayList<View> mHeaderViewInfos = new ArrayList<View>();
private ArrayList<View> mFooterViewInfos = new ArrayList<View>();
private Adapter mAdapter;

public WrapRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

public void addHeaderView(View v) {
mHeaderViewInfos.add(v);
if (mAdapter != null) {
if (!(mAdapter instanceof HeaderViewRecyclerAdapter)) {
mAdapter = new HeaderViewRecyclerAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
}
}
}

public void addFooterView(View v) {
mFooterViewInfos.add(v);
if (mAdapter != null) {
if (!(mAdapter instanceof HeaderViewRecyclerAdapter)) {
mAdapter = new HeaderViewRecyclerAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
}
}
}

@Override
public void setAdapter(Adapter adapter) {
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewRecyclerAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
super.setAdapter(mAdapter);
}
}

布局中使用到的适配器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
public class HeaderViewRecyclerAdapter extends Adapter {
private Adapter mAdapter;
ArrayList<View> mHeaderViewInfos;
ArrayList<View> mFooterViewInfos;

public HeaderViewRecyclerAdapter(ArrayList<View> headerViewInfos,
ArrayList<View> footerViewInfos, Adapter adapter) {
mAdapter = adapter;
if (headerViewInfos == null) {
mHeaderViewInfos = new ArrayList<View>();
} else {
mHeaderViewInfos = headerViewInfos;
}
if (footerViewInfos == null) {
mFooterViewInfos = new ArrayList<View>();
} else {
mFooterViewInfos = footerViewInfos;
}
}

@Override
public int getItemCount() {
if (mAdapter != null) {
return getFootersCount() + getHeadersCount() + mAdapter.getItemCount();
} else {
return getFootersCount() + getHeadersCount();
}
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
int numHeaders = getHeadersCount();
//head
if (position < numHeaders) {
return;
}
//body
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getItemCount();
if (adjPosition < adapterCount) {
mAdapter.onBindViewHolder(holder, adjPosition);
return;
}
}
//footer
}

@Override
public int getItemViewType(int position) {
//判断当前条目是什么类型
int numHeaders = getHeadersCount();
if (position < numHeaders) {
return RecyclerView.INVALID_TYPE;
}
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getItemCount();
if (adjPosition < adapterCount) {
return mAdapter.getItemViewType(adjPosition);
}
}
return RecyclerView.INVALID_TYPE - 1;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//header
if (viewType == RecyclerView.INVALID_TYPE) {
return new HeaderViewHolder(mHeaderViewInfos.get(0));
} else if (viewType == RecyclerView.INVALID_TYPE - 1) {//footer
return new HeaderViewHolder(mFooterViewInfos.get(0));
}
//Footer
return mAdapter.onCreateViewHolder(parent, viewType);
}

public int getHeadersCount() {
return mHeaderViewInfos.size();
}

public int getFootersCount() {
return mFooterViewInfos.size();
}

private static class HeaderViewHolder extends ViewHolder {
public HeaderViewHolder(View view) {
super(view);
}
}
}

在布局文件中使用增加的自定义布局

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.cj5785.wraprecyclerview.WrapRecyclerView
android:id="@+id/wrap_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</RelativeLayout>

编写适配器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

private List<String> list;

public MyAdapter(List<String> list) {
this.list = list;
}

class MyViewHolder extends RecyclerView.ViewHolder{
private TextView textView;
public MyViewHolder(View view) {
super(view);
textView = (TextView) view.findViewById(R.id.tv);
}
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View view = layoutInflater.inflate(R.layout.list_item,parent,false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.textView.setText(list.get(position));
}

@Override
public int getItemCount() {
return list.size();
}
}

适配器的Item布局

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tv"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center" />

在主活动在调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class MainActivity extends AppCompatActivity {

private WrapRecyclerView wrapRecyclerView;
private LayoutParams params;
private List<String> list;
private MyAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wrapRecyclerView = (WrapRecyclerView) findViewById(R.id.wrap_recyclerview);
params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
TextView header = new TextView(this);
header.setGravity(Gravity.CENTER);
header.setLayoutParams(params);
header.setText("Header");
wrapRecyclerView.addHeaderView(header);
TextView footer = new TextView(this);
footer.setGravity(Gravity.CENTER);
footer.setLayoutParams(params);
footer.setText("Footer");
wrapRecyclerView.addFooterView(footer);
list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add("item " + i);
}
adapter = new MyAdapter(list);
wrapRecyclerView.setLayoutManager(new LinearLayoutManager(this));
wrapRecyclerView.setAdapter(adapter);
}
}

运行结果

Donate comment here