RecyclerView 是 Android L 新增的控件,被称为 ListView 的继任者

RecyclerView 概述

在开发 RecyclerView 时充分考虑了扩展性,因此用它可以创建想到的任何种类的的布局。但在使用上也稍微有些不便,比如使用步骤更加复杂,特别是一些控制点击、长压事件需要自己完成。使用 RecyclerView 开发的项目结构大致如下图所示:

从上图可以看到,要使用 RecyclerView,需要先了解清楚 LayoutManager 和 Adapter 元素,分别如下:

  • LayoutManager:用来确定每一个 item 如何进行排列摆放,何时展示和隐藏。回收或重用一个 View 的时候,LayoutManager 会向适配器请求新的数据来替换旧的数据,这种机制避免了创建过多的 View 和频繁的调用 findViewById 方法。目前 RecyclerView 库提供了如下三种子 Manager:
    • LinearLayoutManager:展示了水平或者垂直的滚动列表,相当于 ListView,但是没有页眉和页尾。
    • GridLayoutManager:在网格中展示条目,相当于 GridView。
    • StaggeredGridLayoutManager: 在错落的网格中展示条目,比如常见的瀑布流。

定义布局文件

Activity 中加入 RecyclerView

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_height="match_parent"
    tools:context=".RicyclerView">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/ReclyclerViewTest"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</androidx.constraintlayout.widget.ConstraintLayout>

定义每个 Item 子项

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

    <ImageView
        android:id="@+id/icon_img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginRight="6dp"
        android:contentDescription="null"
        android:maxWidth="20dp"
        android:maxHeight="20dp"
        android:src="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/title_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/icon_img"
        android:layout_alignParentTop="true"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="10dp"
        android:gravity="center_vertical"
        android:text="Title"
        android:textSize="20sp" />




</LinearLayout>

Tip.

  1. Item 每个子项的父布局,及 xml 最开头的 Layout,一定要是 Wrap_content,不然会出现每个 Item 条目占满一页的情况

编写适配器(Adapter)

示例代码

package top.zzgpro.calculate.Adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import org.w3c.dom.Text;

import java.util.ArrayList;

import top.zzgpro.calculate.ListItem.RecyclerItemData;
import top.zzgpro.calculate.R;

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
    private ArrayList<RecyclerItemData> mDatas = null;
    private LayoutInflater mInflater = null;
    public RecyclerViewAdapter(Context context, ArrayList<RecyclerItemData> datas) {
        this.mDatas = datas;
        this.mInflater = LayoutInflater.from(context);
    }
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view=this.mInflater.inflate(R.layout.recycler_item,parent,false);
        ViewHolder viewHolder=new ViewHolder(view);
        return viewHolder;
    }


    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        RecyclerItemData name = mDatas.get(position);
        holder.setImageView(name.getImage());
        holder.setTitle(name.getName());
//        holder.setCentent(name.getName());

    }

    @Override
    public int getItemCount() {
         return mDatas == null ? 0 : mDatas.size();
    }
    class ViewHolder extends RecyclerView.ViewHolder{
        private TextView title;
        private ImageView imageView;
        public TextView getTitle() {
            return title;
        }

        public void setTitle(String text) {
            this.title.setText(text);
        }

        public TextView getCentent() {
            return centent;
        }

        public void setCentent(String centent) {
            this.centent.setText(centent);
        }
        public void setImageView(int id){
            this.imageView.setImageResource(id);
        }
        private TextView centent;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            this.title=(TextView) itemView.findViewById(R.id.title_tv);
//            this.centent=(TextView) itemView.findViewById(R.id.content_tv);
            this.imageView=(ImageView) itemView.findViewById(R.id.icon_img);

        }
    }
}

关键方法

  1. 类要继承 RecyclerView.Adapter 类
  2. 要重写三个方法

onCreateViewHolder

目的:创建新 View,被 LayoutManager 所调用

onBindViewHolder

目的:将数据与界面进行绑定的操作

getItemCount

目的:获取数据数量

ViewHolder 内部类

示例代码

    class ViewHolder extends RecyclerView.ViewHolder{
        private TextView title;
        private ImageView imageView;
        public TextView getTitle() {
            return title;
        }

        public void setTitle(String text) {
            this.title.setText(text);
        }

        public TextView getCentent() {
            return centent;
        }

        public void setCentent(String centent) {
            this.centent.setText(centent);
        }
        public void setImageView(int id){
            this.imageView.setImageResource(id);
        }
        private TextView centent;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            this.title=(TextView) itemView.findViewById(R.id.title_tv);
//            this.centent=(TextView) itemView.findViewById(R.id.content_tv);
            this.imageView=(ImageView) itemView.findViewById(R.id.icon_img);

        }
    }
  1. 定义内部类,继承自 RecyclerView.ViewHolder
  2. 创建构造方法,调用父类构造方法
  3. 在 Adapter 中,继承 RecyclerView.Adapter<自定义 ViewHolder>
  4. 构造自己的逻辑

编写 Activity 后台代码

示例代码

package top.zzgpro.calculate;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;

import java.util.ArrayList;

import top.zzgpro.calculate.Adapter.RecyclerViewAdapter;
import top.zzgpro.calculate.ListItem.RecyclerItemData;

public class RicyclerView extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ricycler_view);
        RecyclerView recyclerView=(RecyclerView) findViewById(R.id.ReclyclerViewTest);
        LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
        //设置横向还是纵向
        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
//        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);
        RecyclerViewAdapter recyclerViewAdapter=new RecyclerViewAdapter(this,initDatas());
        recyclerView.setHasFixedSize(true);
        recyclerView.setAdapter(recyclerViewAdapter);
    }
    private ArrayList<RecyclerItemData> initDatas() {
       ArrayList<RecyclerItemData> mDatas = new ArrayList<>();
        mDatas.add(new RecyclerItemData(R.mipmap.meixi,"梅西"));
        mDatas.add(new RecyclerItemData(R.mipmap.cluo,"C罗"));
        mDatas.add(new RecyclerItemData(R.mipmap.guadi,"瓜迪奥拉"));
        mDatas.add(new RecyclerItemData(R.mipmap.debu,"德布罗意"));
        mDatas.add(new RecyclerItemData(R.mipmap.xiaobai,"小白"));
        mDatas.add(new RecyclerItemData(R.mipmap.sunke,"孙可"));
        return mDatas;
    }


}
  1. 使用 findviewbyid 找到 RecyclerView 的控件
  2. 创建一个 LayoutManager
  3. 将 LayoutManager 设置到 RecyclerView
  4. 实例化自定义的 RecyclerAdapter
  5. 传入数据
  6. 将 Adapter 注册到 RecyclerView

效果