前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RecyclerView详解

RecyclerView详解

作者头像
下码看花
发布2019-09-12 11:34:33
2.9K0
发布2019-09-12 11:34:33
举报
文章被收录于专栏:AndroidStudio初识AndroidStudio初识

前言

Hello 艾维巴蒂,今天给大家介绍一下 ListViewGridView的“大哥“— RecyclerView,这个控件是当下最流行且最常用的一个控件,并且在实战项目中它随处可见,而为什么将它称为“大哥”,请听我们娓娓道来~

简介

RecyclerViewGoogle在API 21下 support.V7包里的控件,用来替代 ListViewGridView。官网对它的描述为:A flexible view for providing a limited window into a large data set。它是从Android5.0出现的全新列表组件,更加强大和灵活。

RecyclerViewsupport 包里默认提供了三个 LayoutManager,分别是下列三个,可用于实现大部分场景的布局需求:线性布局、网格布局、瀑布流布局等等。

1、 LinearLayoutManager 现行管理器,支持横向、纵向。

2、 GridLayoutManager 网格布局管理器

3、 StaggeredGridLayoutManager 瀑布流式布局管理器

基本用法

1.引入依赖

代码语言:javascript
复制
implementation 'com.android.support:recyclerview-v7:27.1.1'

2.布局中添加RecyclerView

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".recyclerview.RecyclerViewActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white" />
</LinearLayout>

如果想去掉可滑动控件滑动到边缘的光晕效果,小伙伴们可以这样试试:

代码语言:javascript
复制
//在xml中设置
android:overScrollMode="never"
//在代码中设置
rvView.setOverScrollMode(View.OVER_SCROLL_NEVER);

3.Adapter适配器设置

在使用的时候更新需要使用 Adapter适配器。但是 RecyclerView使用的适配器并不是之前的 BaseAdapter了。RecyclerView使用的适配器需要继承 RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder>。这里 <>可能有些小白不知道是什么意思,大概说一下, <>这个是泛型,在箭括号里可以写自己定义好的适配器,因为而RecyclerView.ViewHolder本身是一个抽象类,我们往往自己继承这个抽象类,然后绑定我们的布局控件对象。继承该类时必须传入一个itemView,表示这个item显示的View,我这里自定义的适配器命名为MyViewHolder

Adapter中必须实现的三个方法:

a、//列表页需要知道有多少个条目publicintgetItemCount()

b、//创建一个ViewHolder,我们可以根据viewType的不同而创建不同的ViewHolder实现列表页各种不一样的itempublicRecyclerView.ViewHolderonCreateViewHolder(@NonNullViewGroupparent,intviewType)

c、//在ViewHolder中绑定数据publicvoidonBindViewHolder(@NonNullRecyclerView.ViewHolderholder,intposition)

这里我写了一个简单的聊天列表样式,并且对头像添加了点击事件

代码语言:javascript
复制
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {

    private Context mContext;
    private List<String> mList = new ArrayList<String>();
    private RecyclerViewAdapter.OnItemChatClickLitener mOnItemClickLitener;

    public RecyclerViewAdapter(Context context, RecyclerViewAdapter.OnItemChatClickLitener mLitener) {
        this.mContext = context;
        this.mOnItemClickLitener = mLitener;
    }

    public List<String> getData() {
        return mList;
    }

    @Override
    public RecyclerViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = View.inflate(mContext, R.layout.adapter_recyclerview_layout, null);
        return new RecyclerViewAdapter.MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final RecyclerViewAdapter.MyViewHolder holder, final int position) {
        final String str = mList.get(position);
        //判断String传值是否为空
        if (!TextUtils.isEmpty(str)) {
            //给姓名赋值
            holder.tvName.setText(str);
            //头像设置点击事件
            holder.ivHeadPortrait.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mOnItemClickLitener != null) {
                        mOnItemClickLitener.onItemClick(position);
                    }
                }
            });
        }
    }

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

    public interface OnItemChatClickLitener {
        void onItemClick(int position);
    }

    /**
     * 新建一个适配器类,同时内部新建一个ViewHolder类并继承相相应的类
     */
    public class MyViewHolder extends RecyclerView.ViewHolder {

        TextView tvName;
        ImageView ivHeadPortrait;

        public MyViewHolder(View itemView) {
            // 这里很重要,参数中的View对象也很重要
            super(itemView);
            ivHeadPortrait = itemView.findViewById(R.id.iv_headportrait);
            tvName = itemView.findViewById(R.id.tv_name);
        }
    }
}

item的布局 R.layout.adapter_recyclerview_layout代码如下:

代码语言:javascript
复制
<?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="wrap_content"
    android:background="@color/white"
    android:paddingLeft="10dp"
    android:paddingRight="10dp">

    <ImageView
        android:id="@+id/iv_headportrait"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="10dp"
        android:src="@mipmap/moren_icon" />

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:layout_toRightOf="@id/iv_headportrait"
        android:text="小红"
        android:textColor="@color/black"
        android:textSize="14sp"
        android:textStyle="bold" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/iv_headportrait"
        android:layout_toRightOf="@id/iv_headportrait"
        android:text="你领取了谁的红包"
        android:textColor="@color/color_9A9A9A"
        android:textSize="14sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_marginTop="15dp"
        android:text="7分钟前"
        android:textColor="@color/color_9A9A9A"
        android:textSize="13sp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:layout_below="@id/iv_headportrait"
        android:background="@color/color_9A9A9A" />
</RelativeLayout>

4.在activity中初始化RecyclerView,并配置具体用法已在代码中标注,如下:

代码语言:javascript
复制
public class RecyclerViewActivity extends AppCompatActivity {

    private List<String> mList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recyclerview);
        RecyclerView rvView = (RecyclerView) findViewById(R.id.rv_view);
        RecyclerViewAdapter rvAdapter = new RecyclerViewAdapter(this, new RecyclerViewAdapter.OnItemChatClickLitener() {
            @Override
            public void onItemClick(int position) {
                //对头像添加了点击事件
                Toast.makeText(RecyclerViewActivity.this, "点击了:" + mList.get(position), Toast.LENGTH_SHORT).show();
            }
        });

        //LinearLayoutManager是用来做列表布局,也就是单列的列表
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        //设置为垂直布局,默认是垂直的(垂直:LinearLayoutManager.VERTICAL,水平:LinearLayoutManager.HORIZONTAL)
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        //设置布局管理器
        rvView.setLayoutManager(linearLayoutManager);
        //对RecyclerView设置Adapter
        rvView.setAdapter(rvAdapter);
        //给列表初始化数据
        setListData();
        rvAdapter.getData().addAll(mList);
        rvAdapter.notifyDataSetChanged();
    }

    /**
     * 给列表初始化数据
     */
    private void setListData() {
        mList = new ArrayList<String>();
        mList.add("小红");
        mList.add("imageview");
        mList.add("小蓝");
        mList.add("小绿");
        mList.add("小明");
        mList.add("TextView");
        mList.add("小花");
        mList.add("嘿嘿");
        mList.add("是你呀");
        mList.add("editview");
        mList.add("listview");
        mList.add("gridview");
        mList.add("ConstraintLayout");
        mList.add("Service");
        mList.add("Activity");
        mList.add("RelativeLayout");
        mList.add("嗯嗯");
        mList.add("小粉");
    }
}
代码语言:javascript
复制
**步骤:**
    **1.获取RecyclerView对象 。**
    **2.初始化数据 。**
    **3.适配器实例化 。**
    **4.设置LayoutManager**
    **5.设置Adapter 。**
    注意敲黑板了:
    rvView.setLayoutManager(linearLayoutManager);
    要给recyclerview设置布局管理器,否则不显示内容

具体效果如下:

水平RecyclerView:

代码语言:javascript
复制
//LinearLayoutManager是用来做列表布局,也就是单列的列表
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
//设置为垂直布局,默认是垂直的(垂直:LinearLayoutManager.VERTICAL,水平:LinearLayoutManager.HORIZONTAL)
linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
//设置布局管理器
rvView.setLayoutManager(linearLayoutManager);

这里我们换一个布局样式:R.layout.adapter_rv_horizontal_layout

代码语言:javascript
复制
<?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="wrap_content"
    android:background="@color/white"
    android:paddingLeft="10dp"
    android:paddingRight="10dp">

    <ImageView
        android:id="@+id/iv_headportrait"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="10dp"
        android:src="@mipmap/moren_icon" />

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/iv_headportrait"
        android:layout_centerHorizontal="true"
        android:gravity="center_horizontal"
        android:text="小红"
        android:textColor="@color/black"
        android:textSize="14sp"
        android:textStyle="bold" />
</RelativeLayout>

具体效果如下:

上面我们已经初步体验了下 LinearLayoutManager,接下来看 GridLayoutManager

设置网格布局GridLayoutManager

日常开发经常需要有多行或多列的形式来展示各个卡位信息,而一些类似于九宫格之类的布局也可以用这个实现。只需要修改设置布局管理器即可,还是很nice的。

代码语言:javascript
复制
//设置网格布局
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 4);
//设置布局管理器
rvView.setLayoutManager(gridLayoutManager);

效果如下:

*设置竖直瀑布流布局StaggeredGridLayoutManager *

这里同样还是修改设置布局管理器即可,秒秒钟的事情

代码语言:javascript
复制
//设置竖直瀑布流布局
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL);
//设置布局管理器
rvView.setLayoutManager(staggeredGridLayoutManager);

效果如下:

瀑布流样式和网格样式的区别

也许有人会疑惑,瀑布流就是设置下几行或者几列,然后设定下方向而已。网格样式时不也一样是设置下几行或几列,也一样是要再设置个方向。那么为什么瀑布流不可以直接用网格样式来实现呢?它们两者有什么区别么?

有去尝试过的就清楚了,这是两种完全不一样的布局样式。下面以两者都设置为竖直方向多列的样式来区分:

1、网格样式每一行中的所有 item 高度是一致的,不同行可以不一样,但同行的都是一样的,因此它就实现不了瀑布流的样式了;瀑布流所有的 item 高度都允许不一样,所有能实现瀑布流样式。

2、网格样式支持 item 占据多列的宽度;瀑布流支持 item 占据总列数的宽度,不支持只占据其中几列。

3、当设置为水平方向样式时,以上结论中行列对调,宽度高度对调。

使用RecyclerView的优缺点

优点:

1、提供 ViewHolder模式,使得开发者真正操作的是 ViewHolder,而不是像 ListView中的 GridView,需要开发者自己 setTagview.getTag

2、同时支持列表布局和网格布局,而 ListView只能支持列表布局,网格布局需要用 GridView

3、支持瀑布流布局。我们不在需要为实现瀑布流效果而苦恼

4、操作动画。在对列表进行增加、删除时的动画。并且 Adapter提供了增加删除某个 item的方法

5、性能与拓展性。RecyclerView听起来像是回收的view,事实上, RecyclerView本身就不关心 View相关的显示、 View显示什么内容( ViewHolder来管理), View怎么摆放( LayoutManager来管理),也不关心动画( ItemAmator来管理),甚至连分割线它都不管(由 ItemDecoration来管理) 而它关心 View的回收复用,这跟性能有关系。所以名字用 Recycle也是有道理的。这样的好处是,把各个环节工作交付给了不同的类,类似“插件化”。特别方便拓展,自定义各种各样的差异化,而从这其中解耦出来

缺点:需要自己实现 OnItemClickListener点击事件(这么实用的需求,Google竟然让我们自己实现...,不过还好我们自己写)

结语

本篇完,如果你觉得本篇对你有所帮助,欢迎转载分享,标志出处即可,谢谢支持。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 下码看花 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 简介
  • 基本用法
  • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档