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

原理

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

实现

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

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);
}
}

布局中使用到的适配器

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);
}
}
}

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

<?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>

编写适配器

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布局

<?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" />

在主活动在调用

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);
}
}

运行结果

高级UI-RecyclerView头部和尾部添加的更多相关文章

  1. Android 高级UI设计笔记07:RecyclerView 的详解

    1. 使用RecyclerView       在 Android 应用程序中列表是一个非常重要的控件,适用场合非常多,如新闻列表.应用列表.消息列表等等,但是从Android 一出生到现在并没有非常 ...

  2. iOS开发——高级UI&带你玩转UITableView

    带你玩装UITableView 在实际iOS开发中UITableView是使用最多,也是最重要的一个控件,如果你不会用它,那别说什么大神了,菜鸟都不如. 其实关于UItableView事非常简单的,实 ...

  3. 024 如何让html引用公共的头部和尾部(多个html文件公用一个header.html和footer.html)

    前端静态html页面,封装公共的头文件(header:顶部页眉,顶部导航栏等部分)和尾部文件(footer:CopyRight.友情链接等部分) 当前方法:通过load()函数,引入公共头部和尾部文件 ...

  4. Android 高级编程 RecyclerView 控件的使用

    RecyclerView 是Android 新添加的一个用来取代ListView的控件,它的灵活性与可替代性比listview更好. 看一下继承关系: ava.lang.Object    ↳ and ...

  5. table头部、尾部固定;中间内容定高自适应滚动

    table头部.尾部固定;中间内容定高自适应滚动 很多时候,需要使用到表格做数据分析,不管是前端展现,还是后台管理系统节点展现 工作过程中遇到了,作为一个小笔记,备忘! 如下图所示 --------- ...

  6. 用phpcms如何将静态页面制作成企业网站,头部加尾部

    首先,先要准备好这个静态网页的源文件,如图 bs里面是一些css和js的文件,img则是放图片的,文件中的index是网页的首页 运行一下,看看 是这样的 然后打开phpcms文件,上篇博客中有提到, ...

  7. vue引用公用的头部和尾部文件。

    我创建了一个header.vue和fotter.vue,用来做于网站的头部和尾部,每个页面都需要引用这两个,我以组件的方式,来引用这样只需要添加注册的组件就可以了. 第一步.在components文件 ...

  8. iOS开发UI篇—在UIImageView中添加按钮以及Tag的参数说明

    ios开发UI篇—在ImageView中添加按钮以及Tag的参数说明 一.tag参数 一个视图通常都只有一个父视图,多个子视图,在开发中可以通过使用子视图的tag来取出对应的子视图.方法为Viewwi ...

  9. 如何在HTML不同的页面中,共用头部与尾部?

    一.asp语言和PHP语言 首先制作一个头部文件head.asp,或者一个底部文件foot.asp.如主页是index.asp,调用头部代码是在index.asp文件代码的开始位置(第一个标记后面,& ...

随机推荐

  1. 洛谷 P2580 于是他错误的点名开始了 题解

    每日一题 day10 打卡 Analysis trie树模板题,只需用到简单的插入和查询就好了 如果想要学trie树,见信息学奥赛一本通·提高篇P82 #include<iostream> ...

  2. 后台(一)vue+element-ui (按需加载)

    vue init webpack    项目名称 npm install axios                    //先安装! npm install --save axios vue-ax ...

  3. @ControllerAdvice 和 @ExceptionHandler

    @ExceptionHandler的作用是把对不同异常处理抽取到不同的方法中. @ControllerAdvice的作用是把控制器中 @ExceptionHandler.@InitBinder.@Mo ...

  4. 如果对方网站反爬取,封IP了怎么办?

    放慢抓取熟速度,减小对目标网站造成的压力,但是这样会减少单位时间内的数据抓取量 使用代理IP(免费的可能不稳定,收费的可能不划算)

  5. mysql IFNULL函数和COALESCE函数使用技巧

    IFNULL() 函数      IFNULL() 函数用于判断第一个表达式是否为 NULL,如果为 NULL 则返回第二个参数的值,如果不为 NULL 则返回第一个参数的值. IFNULL() 函数 ...

  6. Tkinter 之MessageBox弹出框

    一.参数说明 语法 作用 截图 tk.messagebox.showwarning(title='提示', message='你确定要删除吗?') 警告信息弹窗   tk.messagebox.sho ...

  7. 搭建vue-cli

    https://www.cnblogs.com/wisewrong/p/8570309.html https://www.jianshu.com/p/1ee1c410dc67

  8. 'internalField' 和'boundaryField'的区别?【翻译】

    翻译自:CFD-online 帖子地址:http://www.cfd-online.com/Forums/openfoam/84322-difference-between-internalfield ...

  9. [mysql] Mysql数据分组GROUP BY 和HAVING,与WHERE组合使用

    理解分组,可以这样:对GROUP BY子句后面跟随的列名进行分组,然后对每一个分组而不是整个表进行操作. 举例:在产品表中,检索每一个供应商提供的商品的数量. mysql> SELECT ven ...

  10. fdisk创立主分区过程

    [root@localhost ~]# fdisk /dev/sdb …省略部分输出… Command (m for help): p #显示当前硬盘的分区列表 Disk /dev/sdb: 21.5 ...