Andriod RecyclerView 适配器与点击事件

1 RecyclerView 简介

  • RecyclerView是Android5.0后谷歌推出的一个用于在有限的窗口中展示大量数据集的控件,它可以称为增强版的listview
  • 不仅可以轻松实现和listview一样的效果,同时又优化了listview的不足之处

1.1 RecyclerView 特点

  1. 支持局部刷新
  2. 可以自定义item增删时的动画
  3. 能够实现item拖拽和侧滑删除等功能
  4. 默认已实现View的复用,而且回收机制更加完善

1.2 基本使用

  • 由于RecyclerView 不再Andriod SDK中, 所以要使用androidx.recyclerview.widget.RecyclerView 进行引用
<?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:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"

        />

</LinearLayout>

2 创建ReCyclerView 适配器

  • 继承于RecyclerView.Adapter<VH>
  • 其中VH是我们创建的一个继承于RecyclerView.ViewHolder的静态内部类

该适配器类主要有3个方法和1个自定义ViewHolder组成

  1. onCreateViewHolder: 创建ViewHolder并返回,后续item布局里控件都是从ViewHolder中取出
  2. onBindViewHolder:通过方法提供的ViewHolder,将数据绑定到ViewHolder
  3. getItemCount:获取数据源总长度
  • 使用时,设置到RecyclerViewrecycleview.setAdapter(adapter);

2.1 FruitAdapter 实例

  1. 在构造函数中public FruitAdapter(List<Fruit> fruits) 传入数据源

  2. 创建ViewHolder 内部类: public class ViewHolder extends RecyclerView.ViewHolder

  3. 重写RecyclerAdapter的三个方法

  • public FruitAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 中进行布局填充,并保存到ViewHoler; 可以对ViewHolder中的控件设置监听事件
  • public void onBindViewHolder(@NonNull FruitAdapter.ViewHolder holder, int position) 中设置ViewHoder 中控件的内容
  • public int getItemCount() 中获取数据源的长度
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

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

import java.util.List;

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
    /**
     * 1. FruitAdapter 继承与RecyclerAdapter,
     * */
    private List<Fruit> fruits;
    // 1. 构造方法传入数据源
    public FruitAdapter(List<Fruit> fruits) {
        this.fruits = fruits;
    }

    @NonNull
    @Override
    // 创建ViewHolder实例, 将加载的布局放到构造函数中,并将View返回
    public FruitAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        // 将填充的view放到viewHolder中
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_layout_staggered, parent, false);
        ViewHolder holder = new ViewHolder(view);

        // 1. 在创建的时候进行点击事件
        // 从viewHolder中获取子空间, 添加点击事件

        // 1.1 子布局的点击事件
        holder.getFruitView().setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view1) {
                // 获取点击的位置,定位数组并输出信息
                int adapterPosition = holder.getAdapterPosition();
                Fruit fruit = fruits.get(adapterPosition);
                Toast.makeText(view1.getContext(), "点击的布局,其中内容为: " + fruit.getName(), Toast.LENGTH_SHORT).show();

            }
        });

        // 1.2 获取图片的点击事件
        holder.getFruitImage().setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view2) {
                int adapterPosition = holder.getAdapterPosition();
                Fruit fruit = fruits.get(adapterPosition);
                Toast.makeText(view2.getContext(), "点击图片的水果名称为: " + fruit.getName(), Toast.LENGTH_SHORT).show();
            }
        });

        // 1.3 为文本框指定点击事件
        holder.getFruitName().setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view3) {
                String name = ((TextView)view3.findViewById(R.id.fruit_name)).getText().toString();
                Toast.makeText(view3.getContext(), name, Toast.LENGTH_SHORT).show();
            }
        });

        return holder;
    }

    @Override
    // 2. 每个子项滚动到屏幕内执行,通过 positon 得到当前项的实例,然后显示图片和文字,填充布局
    public void onBindViewHolder(@NonNull FruitAdapter.ViewHolder holder, int position) {
        Fruit fruit = fruits.get(position);
        holder.getFruitImage().setImageResource(fruit.getImageID());
        holder.getFruitName().setText(fruit.getName());
        holder.getFruitPrice().setText("$" + (double)fruit.getPrice()/100 + "/Kg");
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder{
        // 添加ViewHolder中的控件
        private View fruitView;
        private ImageView fruitImage;
        private TextView fruitName;
        private TextView fruitPrice;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            this.fruitView = itemView;
            this.fruitImage = itemView.findViewById(R.id.fruit_image);
            this.fruitName = itemView.findViewById(R.id.fruit_name);
            this.fruitPrice = itemView.findViewById(R.id.fruit_price);
        }


        public void setFruitView(View fruitView) {
            this.fruitView = fruitView;
        }

        public void setFruitImage(ImageView fruitImage) {
            this.fruitImage = fruitImage;
        }

        public void setFruitName(TextView fruitName) {
            this.fruitName = fruitName;
        }

        public void setFruitPrice(TextView fruitPrice) {
            this.fruitPrice = fruitPrice;
        }

        public ImageView getFruitImage() {
            return fruitImage;
        }

        public TextView getFruitName() {
            return fruitName;
        }

        public TextView getFruitPrice() {
            return fruitPrice;
        }

        public View getFruitView() {
            return fruitView;
        }

    }
}

3 为适配器中的控件指定布局

  • 相对于ListView 只能使用线性布局的局限,RecyclerView 能自定义布局,并通过不同的布局管理器来控制item的排列顺序,负责item元素的布局和复用

RecyclerView提供了三种布局管理器:

  1. LinearLayoutManager:线性布局,以垂直戒水平滚动列表方式显示项目
// 5.1 创建垂直的线性布局
LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
recyclerView.setLayoutManager(layoutManager);
  1. GridLayoutManager:网格布局,在网格中显示项目
// 5.2 创建横向的线性布局
LinearLayoutManager linearLayoutManagerHorizontal = new LinearLayoutManager(this);
linearLayoutManagerHorizontal.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(linearLayoutManagerHorizontal);
  1. StaggeredGridLayoutManager:瀑布流布局,在分散对齐网格中显示项目
// 5.3 创建瀑布布局
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(staggeredGridLayoutManager);

4 布局layout文件

4.1 垂直线性子布局xml文件

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

    <ImageView
        android:layout_width="100dp"
        android:layout_height="80dp"
        android:id="@+id/fruit_image"
        android:src="@drawable/apple"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/fruit_name"
        android:text="name"
        android:textSize="30sp"
        android:textColor="#000000"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="20dp"
        />
    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/fruit_price"
        android:text="name"
        android:textSize="30sp"
        android:textColor="#ff0000"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="40dp"
        />

</LinearLayout>

4.2 水平线性子布局xml文件

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

    <ImageView
        android:layout_width="100dp"
        android:layout_height="80dp"
        android:layout_gravity="center_horizontal"
        android:id="@+id/fruit_image"
        android:src="@drawable/apple"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/fruit_name"
        android:text="name"
        android:textSize="24sp"
        android:textColor="#000000"
        android:layout_gravity="center"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/fruit_price"
        android:text="12.00"
        android:textSize="12sp"
        android:textColor="#ff0000"
        android:layout_gravity="center"
        />

</LinearLayout>

4.3 瀑布布局xml文件

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

    <ImageView
        android:layout_width="100dp"
        android:layout_height="80dp"
        android:layout_gravity="center_horizontal"
        android:id="@+id/fruit_image"
        android:src="@drawable/apple"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/fruit_name"
        android:text="name"
        android:textSize="24sp"
        android:textColor="#000000"
        android:layout_gravity="center"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/fruit_price"
        android:text="12.00"
        android:textSize="12sp"
        android:textColor="#ff0000"
        android:layout_gravity="center"
        />

</LinearLayout>

5 Fruit封装数据类

package com.hlq.sz_ch06_recycler_view;

public class Fruit {

    private int imageID;
    private String name;
    private long price;

    public void setImageID(int imageID) {
        this.imageID = imageID;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPrice(long price) {
        this.price = price;
    }

    public int getImageID() {
        return imageID;
    }

    public String getName() {
        return name;
    }

    public long getPrice() {
        return price;
    }

    public Fruit(int imageID, String name, long price) {
        this.imageID = imageID;
        this.name = name;
        this.price = price;
    }

    public Fruit() {
    }
}


6 MainActivity 主界面

package com.hlq.sz_ch06_recycler_view;

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

import android.os.Bundle;
import android.widget.LinearLayout;

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

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;

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

        // 1. 绑定控件
        recyclerView = this.findViewById(R.id.recycler_view);

        // 2. 准备数据
        List<Fruit> fruits = new ArrayList<>();

        for (int i = 0; i < 10; ++i) {

            Fruit pineApple = new Fruit(R.drawable.pineapple, "菠萝", 1690);
            fruits.add(pineApple);
            Fruit mango = new Fruit(R.drawable.mango, "芒果", 2990);
            fruits.add(mango);
            Fruit grape = new Fruit(R.drawable.grape, "葡萄", 1990);
            fruits.add(grape);
            Fruit pomegranate = new Fruit(R.drawable.pomegranate, "石榴", 1500);
            fruits.add(pomegranate);
            Fruit apple =  new Fruit(R.drawable.apple, "苹果", 2000);
            fruits.add(apple);
            Fruit watermelon = new Fruit(R.drawable.watermelon, "西瓜", 2880);
            fruits.add(watermelon);
            Fruit orange = new Fruit(R.drawable.orange, "橘子", 1880);
            fruits.add(orange);

        }
        // 3. 设计子布局

        // 4. 创建自定义适配器
        FruitAdapter adapter = new FruitAdapter(fruits);
        // 5. 创建布局管理器,将RecyclerView中的布局以布局管理器中的布局进行管理

//        // 5.1 创建垂直的线性布局
//        LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
//        recyclerView.setLayoutManager(layoutManager);

//        // 5.2 创建横向的线性布局
//        LinearLayoutManager linearLayoutManagerHorizontal = new LinearLayoutManager(this);
//        linearLayoutManagerHorizontal.setOrientation(LinearLayoutManager.HORIZONTAL);
//        recyclerView.setLayoutManager(linearLayoutManagerHorizontal);

        // 5.3 创建瀑布布局
        StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(staggeredGridLayoutManager);

        // 6 绑定 布局-控制-数据的适配器
        recyclerView.setAdapter(adapter);

    }
}

7 结果

在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值