Android 技术学习中关于 RecyclerView 的一些使用心得

背景

RecyclerView 控件和 ListView 控件类似,用来在一个页面展示大量数据用的。但是RecyclerView 的使用更加的灵活和方便。可以支持

  • LinerLayoutManager:以垂直或者水平列表方式展示Item、
  • GridLayoutManager:以网格方式展示Item、
  • StaggeredGridLayoutManager:以瀑布流方式展示Item。

而且自带控件缓存的实现,非常的棒!所以项目开发中涉及到展示大量数据的时候, RecyclerView 控件绝对是你独一无二的选择。但是实际开发中需要对其进行相关功能的扩展,这里记录一下,方便自己日后温习并加深理解。


RecyclerView 概述

官方介绍,RecyclerView用于在有限的窗口展现大量的数据,其实早已经有了类似的控件,如ListView、GridView,那么相比它们,RecyclerView有什么样优势呢?
RecyclerView标准化了ViewHolder,而且异常的灵活,可以轻松实现ListView实现不了的样式和功能,通过布局管理器LayoutManager可控制Item的布局方式,通过设置Item操作动画自定义Item添加和删除的动画,通过设置Item之间的间隔样式,自定义间隔。


RecyclerView 的使用

添加依赖

implementation 'com.android.support:recyclerview-v7:27.1.1'

依赖添加完,同步gradle后就可以在xml布局文件中引用 RecyclerView 控件了。


控件引用

在xml文件中引用控件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:padding="10dp"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_demo"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v7.widget.RecyclerView>

</LinearLayout>

图示如下:

在这里插入图片描述


itemView 布局的创建

recyclerView 展示的数据,是由很多的item所组成的,所以我们需要创建一个itemView的xml布局文件,这里我在布局中只简单的创建了一个TextView来作展示,recyclerview_item_demo.xml 如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="60dp">

    <TextView
        android:background="@drawable/item_selector"
        android:textSize="16sp"
        android:id="@+id/tv_content"
        android:textColor="@android:color/black"
        android:text="demo"
        android:padding="10dp"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

图示如下:

在这里插入图片描述


继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder

这里我们自定义MyRecyclerViewAdapter 继承 RecyclerView.Adapter并重写相关方法,MyRecyclerViewAdapter 类如下:

// 第一步:继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
    class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{

        private List<String> listData;
        private List<Integer> heightList;// 瀑布流效果使用,用于保存生产的随机高度

        public MyRecyclerViewAdapter(List<String> listTemp) {
            this.listData = listTemp;
//            getRandomHeight(listTemp.size());// 随机高度设置,瀑布流效果的recyclerView有用
        }

        /**
         * 随机高度设置
         * @param length item的个数
         */
        public void getRandomHeight(int length){
            heightList = new ArrayList<>();
            for (int i = 0;i < length;i++){
                int randomH = new Random().nextInt(400) + 200;// 200-600之间的随机int类型数值
                heightList.add(randomH);
            }
        }

        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            // 使用布局泵构建itemView的布局
            View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item_demo, parent, false);
            // 创建MyViewHolder对象
            MyViewHolder holder = new MyViewHolder(view);
            // 返回MyViewHolder对象
            return holder;
        }

        @Override
        public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
            // 给瀑布流效果的item设置随机高度
//            ViewGroup.LayoutParams params = holder.tv_content.getLayoutParams();
//            params.height = heightList.get(position);
//            holder.tv_content.setLayoutParams(params);

            String content = listData.get(position);// 获取数据
            holder.tv_content.setText(content);// 给item设置数据

        }

        @Override
        public int getItemCount() {
            return listData.size();// 返回item的个数
        }

        /**
         * 创建MyViewHolder继承RecyclerView.ViewHolder
         * 在内部方法MyViewHolder中缓存itemView中的控件
         */
        class MyViewHolder extends RecyclerView.ViewHolder{

            TextView tv_content;// itemView中的 TextView 控件

            public MyViewHolder(View itemView) {
                super(itemView);
                // 缓存控件
                tv_content = itemView.findViewById(R.id.tv_content);
            }
        }
    }

上面的代码中有几行代码和方法我将其注释了,后面展示瀑布流效果的时候在将这些注释的代码放出来吧!这里先实现线性布局的效果。

到这里我们可以看到RecyclerViewAdapter的内部有自己的控件缓存实现,而不需要我们再像以前一样自己写代码去实现缓存控件的功能了。这也算是我喜欢用 RecyclerView 控件的原因之一吧!请原谅我的喜新厌旧,不过我是对技术说的!


MainActivity 中的主代码实现

适配器写好后,我们就可以获取 recyclerView 控件,并给其设置 adapter 即可。MainActivity 类代码如下:

package com.example.administrator.recyclerviewdemo;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import butterknife.BindView;
import butterknife.ButterKnife;

public class MainActivity extends Activity{

    @BindView(R.id.rv_demo)RecyclerView rv_demo;// RecyclerView控件

    private List<String> list = new ArrayList<>();
    private MyRecyclerViewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        initData();// 初始化模拟数据

    }

    /**
     * 初始化数据
     */
    private void initData() {
        for (int i = 0;i < 40;i++){
            list.add("demo item" + (i+1));
        }

        show();// 使用 RecyclerView 展示数据
    }

    /**
     * 使用recyclerView展示数据
     */
    private void show() {
        // 第一步:创建 MyRecyclerViewAdapter
        adapter = new MyRecyclerViewAdapter(list);
        // 第二步:设置布局管理器,控制布局效果
        // 线性垂直布局
        rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));

        // 线性水平布局
//        rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false));

        // 网格布局
//        rv_demo.setLayoutManager(new GridLayoutManager(MainActivity.this, 3));

        // 瀑布流布局
//        rv_demo.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));

        // 第三步:设置adapter
        rv_demo.setAdapter(adapter);

        rv_demo.setItemAnimator(new DefaultItemAnimator());// 设置系统默认的动画效果

    }


    // 第一步:继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
    class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{

        private List<String> listData;
        private List<Integer> heightList;// 瀑布流效果使用,用于保存生产的随机高度

        private OnItemClickListener onItemClickListener;

        public MyRecyclerViewAdapter(List<String> listTemp) {
            this.listData = listTemp;
//            getRandomHeight(listTemp.size());// 随机高度设置,瀑布流效果的recyclerView有用
        }

        /**
         * 随机高度设置
         * @param length item的个数
         */
        public void getRandomHeight(int length){
            heightList = new ArrayList<>();
            for (int i = 0;i < length;i++){
                int randomH = new Random().nextInt(400) + 200;// 200-600之间的随机int类型数值
                heightList.add(randomH);
            }
        }

        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            // 使用布局泵构建itemView的布局
            View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item_demo, parent, false);
            // 创建MyViewHolder对象
            MyViewHolder holder = new MyViewHolder(view);
            // 返回MyViewHolder对象
            return holder;
        }

        @Override
        public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
            // 给瀑布流效果的item设置随机高度
//            ViewGroup.LayoutParams params = holder.tv_content.getLayoutParams();
//            params.height = heightList.get(position);
//            holder.tv_content.setLayoutParams(params);

            String content = listData.get(position);// 获取数据
            holder.tv_content.setText(content);// 给item设置数据

        }

        @Override
        public int getItemCount() {
            return listData.size();// 返回item的个数
        }

        /**
         * 创建MyViewHolder继承RecyclerView.ViewHolder
         * 在内部方法MyViewHolder中缓存itemView中的控件
         */
        class MyViewHolder extends RecyclerView.ViewHolder{

            TextView tv_content;// itemView中的 TextView 控件

            public MyViewHolder(View itemView) {
                super(itemView);
                // 缓存控件
                tv_content = itemView.findViewById(R.id.tv_content);
            }
        }
    }

}

简单的说一下我的实现思路:

  • 首先获取 recyclerView 控件,
  • 初始化数据,然后创建 MyRecyclerViewAdapter ,
  • 设置item 呈现的布局效果(线性、网格和瀑布流三种),
  • 设置adapter,当然可以加上默认的动画。

我们现在运行一下看看效果:

在这里插入图片描述

成功的用 recyclerView 控件展示了数据(这里是线性布局垂直展示效果),基本的实现就是上面的几个步骤,下面我们来看看其他布局的效果。


线性布局水平展示效果

将对应注释的代码放开后,show() 方法的代码如下:

/**
     * 使用recyclerView展示数据
     */
    private void show() {
        // 第一步:创建 MyRecyclerViewAdapter
        adapter = new MyRecyclerViewAdapter(list);
        // 第二步:设置布局管理器,控制布局效果
        // 线性垂直布局
//        rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));

        // 线性水平布局
        rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false));

        // 网格布局
//        rv_demo.setLayoutManager(new GridLayoutManager(MainActivity.this, 3));

        // 瀑布流布局
//        rv_demo.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));

        // 第三步:设置adapter
        rv_demo.setAdapter(adapter);

        rv_demo.setItemAnimator(new DefaultItemAnimator());// 设置系统默认的动画效果

    }

效果图示如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这里可以看到可以实现了线性布局的水平滑动效果。


网格布局效果实现

将对应注释的代码放开后,show() 方法的代码如下:

/**
     * 使用recyclerView展示数据
     */
    private void show() {
        // 第一步:创建 MyRecyclerViewAdapter
        adapter = new MyRecyclerViewAdapter(list);
        // 第二步:设置布局管理器,控制布局效果
        // 线性垂直布局
//        rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));

        // 线性水平布局
//        rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false));

        // 网格布局
        rv_demo.setLayoutManager(new GridLayoutManager(MainActivity.this, 3));

        // 瀑布流布局
//        rv_demo.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));

        // 第三步:设置adapter
        rv_demo.setAdapter(adapter);

        rv_demo.setItemAnimator(new DefaultItemAnimator());// 设置系统默认的动画效果

    }

上面代码中网格布局设置为了3列,效果展示如下:

在这里插入图片描述


瀑布流效果实现

这里除了 show() 方法需要放开对应注释后,还要在MyRecyclerViewAdapter 中将随机高度设置这部分代码的注释也放开,所以代码如下:

package com.example.administrator.recyclerviewdemo;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import butterknife.BindView;
import butterknife.ButterKnife;

public class MainActivity extends Activity{

    @BindView(R.id.rv_demo)RecyclerView rv_demo;// RecyclerView控件

    private List<String> list = new ArrayList<>();
    private MyRecyclerViewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        initData();// 初始化模拟数据

    }

    /**
     * 初始化数据
     */
    private void initData() {
        for (int i = 0;i < 40;i++){
            list.add("demo item" + (i+1));
        }

        show();// 使用 RecyclerView 展示数据
    }

    /**
     * 使用recyclerView展示数据
     */
    private void show() {
        // 第一步:创建 MyRecyclerViewAdapter
        adapter = new MyRecyclerViewAdapter(list);
        // 第二步:设置布局管理器,控制布局效果
        // 线性垂直布局
//        rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));

        // 线性水平布局
//        rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false));

        // 网格布局
//        rv_demo.setLayoutManager(new GridLayoutManager(MainActivity.this, 3));

        // 瀑布流布局
        rv_demo.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));

        // 第三步:设置adapter
        rv_demo.setAdapter(adapter);

        rv_demo.setItemAnimator(new DefaultItemAnimator());// 设置系统默认的动画效果

    }


    // 第一步:继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
    class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{

        private List<String> listData;
        private List<Integer> heightList;// 瀑布流效果使用,用于保存生产的随机高度

        private OnItemClickListener onItemClickListener;

        public MyRecyclerViewAdapter(List<String> listTemp) {
            this.listData = listTemp;
            getRandomHeight(listTemp.size());// 随机高度设置,瀑布流效果的recyclerView有用
        }

        /**
         * 随机高度设置
         * @param length item的个数
         */
        public void getRandomHeight(int length){
            heightList = new ArrayList<>();
            for (int i = 0;i < length;i++){
                int randomH = new Random().nextInt(400) + 200;// 200-600之间的随机int类型数值
                heightList.add(randomH);
            }
        }

        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            // 使用布局泵构建itemView的布局
            View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item_demo, parent, false);
            // 创建MyViewHolder对象
            MyViewHolder holder = new MyViewHolder(view);
            // 返回MyViewHolder对象
            return holder;
        }

        @Override
        public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
            // 给瀑布流效果的item设置随机高度
            ViewGroup.LayoutParams params = holder.tv_content.getLayoutParams();
            params.height = heightList.get(position);
            holder.tv_content.setLayoutParams(params);

            String content = listData.get(position);// 获取数据
            holder.tv_content.setText(content);// 给item设置数据

        }

        @Override
        public int getItemCount() {
            return listData.size();// 返回item的个数
        }

        /**
         * 创建MyViewHolder继承RecyclerView.ViewHolder
         * 在内部方法MyViewHolder中缓存itemView中的控件
         */
        class MyViewHolder extends RecyclerView.ViewHolder{

            TextView tv_content;// itemView中的 TextView 控件

            public MyViewHolder(View itemView) {
                super(itemView);
                // 缓存控件
                tv_content = itemView.findViewById(R.id.tv_content);
            }
        }
    }

}

同时需要将itemView的xml布局总根布局的固定高度设置为自适应(即wrap_content),如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:background="@drawable/item_selector"
        android:textSize="16sp"
        android:id="@+id/tv_content"
        android:textColor="@android:color/black"
        android:text="demo"
        android:padding="10dp"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

运行一下,我们看看展示效果:

在这里插入图片描述

到这里瀑布流效果也实现了。

可以看到recyclerView 可以很方便的实现listView、gridView的功能,非常的方便,还有额外的瀑布流效果,使用习惯后我也相信你会喜欢这样的新控件。


RecyclerView 设置 Item 点击事件

这里只实现item的单击事件,因为item的长按事件也是一样。两个我就实现一个,另外一个也是依葫芦画瓢。理解才能更好的使用,大家一定要好好掌握,看我在代码中的注释去慢慢的分析掌握这部分,会对你很有用的,因为很多场景都可以借鉴该方法来获取数据(也就是回调)。

  • 声明 MyItemClickListener 接口如下:
package com.example.administrator.recyclerviewdemo;

import android.view.View;

/**
 * 接口中声明一个item的点击事件方法,参数带 View对象 和 item的位置
 */
public interface MyItemClickListener {

    void onItemClick(View view, int position);// 声明item点击方法

}

  • 在adapter中写方法用来注册 MyItemClickListener 监听器,如下:
// 第一步:继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
    class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{

        private List<String> listData;
        private List<Integer> heightList;// 瀑布流效果使用,用于保存生产的随机高度

        private MyItemClickListener listener;

        private MyItemClickListener onItemClickListener;

        public MyRecyclerViewAdapter(List<String> listTemp) {
            this.listData = listTemp;
            getRandomHeight(listTemp.size());// 随机高度设置,瀑布流效果的recyclerView有用
        }

        /**
         * 提供给开发者调用,注册监听器
         * @param listener
         */
        public void setMyItemClickListener(MyItemClickListener listener){
            this.listener = listener;
        }

        /**
         * 随机高度设置
         * @param length item的个数
         */
        public void getRandomHeight(int length){
            heightList = new ArrayList<>();
            for (int i = 0;i < length;i++){
                int randomH = new Random().nextInt(400) + 200;// 200-600之间的随机int类型数值
                heightList.add(randomH);
            }
        }

        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            // 使用布局泵构建itemView的布局
            View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item_demo, parent, false);
            // 创建MyViewHolder对象
            MyViewHolder holder = new MyViewHolder(view);
            // 返回MyViewHolder对象
            return holder;
        }

        @Override
        public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
            // 给瀑布流效果的item设置随机高度
            ViewGroup.LayoutParams params = holder.tv_content.getLayoutParams();
            params.height = heightList.get(position);
            holder.tv_content.setLayoutParams(params);

            String content = listData.get(position);// 获取数据
            holder.tv_content.setText(content);// 给item设置数据

        }

        @Override
        public int getItemCount() {
            return listData.size();// 返回item的个数
        }

        /**
         * 创建MyViewHolder继承RecyclerView.ViewHolder
         * 在内部方法MyViewHolder中缓存itemView中的控件
         */
        class MyViewHolder extends RecyclerView.ViewHolder{

            TextView tv_content;// itemView中的 TextView 控件

            public MyViewHolder(View itemView) {
                super(itemView);
                // 缓存控件
                tv_content = itemView.findViewById(R.id.tv_content);
            }
        }
    }
  • 然后在 onCreateViewHolder 方法中,创建MyViewHolder对象的时候,通过构造方法将 listener
    监听器对象传递给 MyViewHolder,然后在 MyViewHolder 类中itemView的点击事件中调用 listener
    的方法即可。如下:
// 第一步:继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
    class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{

        private List<String> listData;
        private List<Integer> heightList;// 瀑布流效果使用,用于保存生产的随机高度

        private MyItemClickListener listener;

        private MyItemClickListener onItemClickListener;

        public MyRecyclerViewAdapter(List<String> listTemp) {
            this.listData = listTemp;
            getRandomHeight(listTemp.size());// 随机高度设置,瀑布流效果的recyclerView有用
        }

        /**
         * 提供给开发者调用,注册监听器
         * @param listener
         */
        public void setMyItemClickListener(MyItemClickListener listener){
            this.listener = listener;
        }

        /**
         * 随机高度设置
         * @param length item的个数
         */
        public void getRandomHeight(int length){
            heightList = new ArrayList<>();
            for (int i = 0;i < length;i++){
                int randomH = new Random().nextInt(400) + 200;// 200-600之间的随机int类型数值
                heightList.add(randomH);
            }
        }

        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            // 使用布局泵构建itemView的布局
            View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item_demo, parent, false);
            // 创建MyViewHolder对象
            MyViewHolder holder = new MyViewHolder(view, listener);
            // 返回MyViewHolder对象
            return holder;
        }

        @Override
        public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
            // 给瀑布流效果的item设置随机高度
            ViewGroup.LayoutParams params = holder.tv_content.getLayoutParams();
            params.height = heightList.get(position);
            holder.tv_content.setLayoutParams(params);

            String content = listData.get(position);// 获取数据
            holder.tv_content.setText(content);// 给item设置数据

        }

        @Override
        public int getItemCount() {
            return listData.size();// 返回item的个数
        }

        /**
         * 创建MyViewHolder继承RecyclerView.ViewHolder
         * 在内部方法MyViewHolder中缓存itemView中的控件
         */
        class MyViewHolder extends RecyclerView.ViewHolder{

            TextView tv_content;// itemView中的 TextView 控件

            public MyViewHolder(final View itemView, final MyItemClickListener listener) {
                super(itemView);
                // 缓存控件
                tv_content = itemView.findViewById(R.id.tv_content);

                // item单击实现
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (listener != null){
                            listener.onItemClick(itemView, getAdapterPosition());
                        }
                    }
                });
                
            }
        }
    }
  • 到这里准备工作就做好了,下面是我们开发者的工作了,我们只需要注册这个监听器即可,如下:
// recyclerView 的item单击事件监听实现
        adapter.setMyItemClickListener(new MyItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(MainActivity.this, "开发者点击了:"+ list.get(position), Toast.LENGTH_LONG).show();
            }
        });

最后给出完整的代码,如下:

package com.example.administrator.recyclerviewdemo;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import butterknife.BindView;
import butterknife.ButterKnife;

public class MainActivity extends Activity{

    @BindView(R.id.rv_demo)RecyclerView rv_demo;// RecyclerView控件

    private List<String> list = new ArrayList<>();
    private MyRecyclerViewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        initData();// 初始化模拟数据

        setListeners();// 设置监听
    }

    /**
     * 设置监听
     */
    private void setListeners() {

        // recyclerView 的item单击事件监听实现
        adapter.setMyItemClickListener(new MyItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(MainActivity.this, "开发者点击了:"+ list.get(position), Toast.LENGTH_LONG).show();
            }
        });

    }

    /**
     * 初始化数据
     */
    private void initData() {
        for (int i = 0;i < 40;i++){
            list.add("demo item" + (i+1));
        }

        show();// 使用 RecyclerView 展示数据
    }

    /**
     * 使用recyclerView展示数据
     */
    private void show() {
        // 第一步:创建 MyRecyclerViewAdapter
        adapter = new MyRecyclerViewAdapter(list);
        // 第二步:设置布局管理器,控制布局效果
        // 线性垂直布局
//        rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));

        // 线性水平布局
//        rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false));

        // 网格布局
//        rv_demo.setLayoutManager(new GridLayoutManager(MainActivity.this, 3));

        // 瀑布流布局
        rv_demo.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));

        // 第三步:设置adapter
        rv_demo.setAdapter(adapter);

        rv_demo.setItemAnimator(new DefaultItemAnimator());// 设置系统默认的动画效果

    }


    // 第一步:继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
    class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{

        private List<String> listData;
        private List<Integer> heightList;// 瀑布流效果使用,用于保存生产的随机高度

        private MyItemClickListener listener;

        private MyItemClickListener onItemClickListener;

        public MyRecyclerViewAdapter(List<String> listTemp) {
            this.listData = listTemp;
            getRandomHeight(listTemp.size());// 随机高度设置,瀑布流效果的recyclerView有用
        }

        /**
         * 提供给开发者调用,注册监听器
         * @param listener
         */
        public void setMyItemClickListener(MyItemClickListener listener){
            this.listener = listener;
        }

        /**
         * 随机高度设置
         * @param length item的个数
         */
        public void getRandomHeight(int length){
            heightList = new ArrayList<>();
            for (int i = 0;i < length;i++){
                int randomH = new Random().nextInt(400) + 200;// 200-600之间的随机int类型数值
                heightList.add(randomH);
            }
        }

        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            // 使用布局泵构建itemView的布局
            View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item_demo, parent, false);
            // 创建MyViewHolder对象
            MyViewHolder holder = new MyViewHolder(view, listener);
            // 返回MyViewHolder对象
            return holder;
        }

        @Override
        public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
            // 给瀑布流效果的item设置随机高度
            ViewGroup.LayoutParams params = holder.tv_content.getLayoutParams();
            params.height = heightList.get(position);
            holder.tv_content.setLayoutParams(params);

            String content = listData.get(position);// 获取数据
            holder.tv_content.setText(content);// 给item设置数据

        }

        @Override
        public int getItemCount() {
            return listData.size();// 返回item的个数
        }

        /**
         * 创建MyViewHolder继承RecyclerView.ViewHolder
         * 在内部方法MyViewHolder中缓存itemView中的控件
         */
        class MyViewHolder extends RecyclerView.ViewHolder{

            TextView tv_content;// itemView中的 TextView 控件

            public MyViewHolder(final View itemView, final MyItemClickListener listener) {
                super(itemView);
                // 缓存控件
                tv_content = itemView.findViewById(R.id.tv_content);

                // item单击实现
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (listener != null){
                            listener.onItemClick(itemView, getAdapterPosition());
                        }
                    }
                });

            }
        }
    }

}

运行后的效果图示如下:

在这里插入图片描述

在这里插入图片描述


总结

这里简单的讲了recyclerView 的简单使用,并给大家实现了 item点击事件。你只要掌握了这篇文章,那么你应该可以在项目中很熟练的使用 RecyclerView了。

RecyclerView 远不止我现在介绍的这些,还有很多其他的可扩展的功能,只能开发者在以后的实战中自己去慢慢掌握和学习了。加油哦!


A little bit of progress every day!Come on!

发布了132 篇原创文章 · 获赞 217 · 访问量 65万+

猜你喜欢

转载自blog.csdn.net/csdnzouqi/article/details/82793033