RecyclerView控件讲解(实现纵向/横向滚动以及瀑布流布局)

与ListView对比优势:

  1.运行效率更高。

  2.能实现横向滚动与瀑布流布局。

  官方更加推荐Recycler控件,但因为后期加入又要使所有版本的Android都能使用,所以把它放入了support库当中,所以使用的第一步,是在项目的build.gradle中添加相应的依赖库。

打开app/build.gradle文件,在dependencies中添加

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

不同项目不同版本的依赖库版本号不同,截图给大家参考下我现在的,不必模仿:

点击Sync Now同步。

  那么如何使用这个控件呢?点击activity_main.xml,修改代码:

<?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=".MainActivity">

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

</androidx.constraintlayout.widget.ConstraintLayout>

中间的这段代码,就是调用RecyclerView控件。因为它并不是内置在SDK中的控件,所以使用时要写出完整的路径名。

接下来我们以水果列表显示为例分别实现四个功能,每个功能讲解结束都会附上Demo,请自行下载:

1:实现纵向滚动

2:实现横向滚动

3:实现瀑布流布局

4:实现recyclerView点击事件

功能一:实现纵向滚动

  先创建一个Fruit类Fruit.java,代码如下:

package com.example.recyclerviewtest;

public class Fruit {
    private String name;
    private int imageId;

    public Fruit(String name, int imageId) {
        this.name = name;
        this.imageId = imageId;
    }

    public String getName() {
        return name;
    }

    public int getImageId() {
        return imageId;
    }
}

  再创建对于一个水果,它的单个布局文件fruit_item.xml。

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

    <ImageView
        android:id="@+id/fruit_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"/>

</LinearLayout>

接下来为RecyclerView准备一个适配器,新建FruitAdapter类文件FruitAdapter.java,让这个个适配器继承自RecyclerView.Adapter,并将泛型指定为FruitAdapter.ViewHolder。其中ViewHolder是我们在FruitAdapter中定义的一个内部类,代码如下:

package com.example.recyclerviewtest;

import android.media.Image;
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.List;

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {

    private List<Fruit> mFruitList;

    //传入view参数,这个参数就是RecyclerView的子项布局,这样就能找到里面各个控件的id
    static class ViewHolder extends RecyclerView.ViewHolder {
        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            fruitImage = (ImageView)itemView.findViewById(R.id.fruit_image);
            fruitName = (TextView)itemView.findViewById(R.id.fruit_name);
        }
    }

    //将要展示的数据源传入
    public FruitAdapter(List<Fruit> fruitList) {
        mFruitList = fruitList;
    }

    //下面三个函数必须要重写

    //载入fruit_item布局,创建ViewHolder实例
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }

    //为每个RecylerView对象赋值
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitName.setText(fruit.getName());
        holder.fruitImage.setImageResource(fruit.getImageId());
    }

    //计算一共多少个子项
    @Override
    public int getItemCount() {
        return mFruitList.size();
    }

}

适配器已经准备好了,我们现在可以使用RecyclerView了,修改MainActivity.java:

package com.example.recyclerviewtest;

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

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

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

public class MainActivity extends AppCompatActivity {

    private List<Fruit> fruitList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruits();
        //获取recyclerView实例
        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
        //创建LinerLayoutManager对象,其中LayoutManager用于指定RecyclerView的布局方式
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        //设置布局
        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        //关联RecyclerView与数据
        recyclerView.setAdapter(adapter);
    }

    private void initFruits() {
        for(int i = 0; i < 2; i++) {
            Fruit apple = new Fruit("Apple", R.drawable.apple_pic);
            fruitList.add(apple);
            Fruit banana = new Fruit("Banana", R.drawable.banana_pic);
            fruitList.add(banana);
            Fruit orange = new Fruit("Orange", R.drawable.orange_pic);
            fruitList.add(orange);
            Fruit watermelon = new Fruit("Watermelon", R.drawable.watermelon_pic);
            fruitList.add(watermelon);
            Fruit pear = new Fruit("Pear", R.drawable.pear_pic);
            fruitList.add(pear);
            Fruit grape = new Fruit("Grape", R.drawable.grape_pic);
            fruitList.add(grape);
            Fruit pineapple = new Fruit("Pineapple", R.drawable.pineapple_pic);
            fruitList.add(pineapple);
            Fruit strawberry = new Fruit("Strawberry", R.drawable.strawberry_pic);
            fruitList.add(strawberry);
            Fruit cherry = new Fruit("Cherry", R.drawable.cherry_pic);
            fruitList.add(cherry);
            Fruit mango = new Fruit("Mango", R.drawable.mango_pic);
            fruitList.add(mango);
        }
    }
}

接下来就可以运行了,以后如果需要不同的内容,结构,更改部分代码即可,代码结构不会改变。下面是运行效果:

功能一Demo文件下载:https://download.csdn.net/download/qq_38367681/12167275

功能二:实现横向滚动

  要实现横向拉动其实很简单,因为ListView的布局是由自身去管理的,而RecyclerView把这个工作交给了LayoutManager,LayoutManager中制定了一套可扩展的布局排列接口,子类只要按照接口的规范来实现,就能定制出各种不同排列的布局了。

  第一步,肯定要先改写子项的布局,使它横向排列看起来更舒服,所以修改fruit_item.xml.

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

    <ImageView
        android:id="@+id/fruit_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"/>

</LinearLayout>

第二部,只需要调整layoutManager的排列方向。默认是垂直方向,所以纵向排列的代码并没有加入方向调整,实现功能二,我们只需要加入一行代码,设置排列方向为水平:

layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

所以MainActivity.java代码变成如下:

package com.example.recyclerviewtest;

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

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

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

public class MainActivity extends AppCompatActivity {

    private List<Fruit> fruitList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruits();
        //获取recyclerView实例
        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
        //创建LinerLayoutManager对象,其中LayoutManager用于指定RecyclerView的布局方式
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        //设置线性布局为水平线性布局,默认为垂直,所以不设置效果会跟listview一样
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        //设置布局
        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        //关联RecyclerView与数据
        recyclerView.setAdapter(adapter);
    }

    private void initFruits() {
        for(int i = 0; i < 2; i++) {
            Fruit apple = new Fruit("Apple", R.drawable.apple_pic);
            fruitList.add(apple);
            Fruit banana = new Fruit("Banana", R.drawable.banana_pic);
            fruitList.add(banana);
            Fruit orange = new Fruit("Orange", R.drawable.orange_pic);
            fruitList.add(orange);
            Fruit watermelon = new Fruit("Watermelon", R.drawable.watermelon_pic);
            fruitList.add(watermelon);
            Fruit pear = new Fruit("Pear", R.drawable.pear_pic);
            fruitList.add(pear);
            Fruit grape = new Fruit("Grape", R.drawable.grape_pic);
            fruitList.add(grape);
            Fruit pineapple = new Fruit("Pineapple", R.drawable.pineapple_pic);
            fruitList.add(pineapple);
            Fruit strawberry = new Fruit("Strawberry", R.drawable.strawberry_pic);
            fruitList.add(strawberry);
            Fruit cherry = new Fruit("Cherry", R.drawable.cherry_pic);
            fruitList.add(cherry);
            Fruit mango = new Fruit("Mango", R.drawable.mango_pic);
            fruitList.add(mango);
        }
    }
}

运行结果如下:

功能二Demo文件下载:https://download.csdn.net/download/qq_38367681/12168921

功能三:实现瀑布流布局

  同功能二,为了瀑布流布局更美观,肯定是先修改fruit_item.xml文件,然后再修改MainActivity.java中的LayoutManager,使其变成瀑布流布局。当然也只是一行代码:

StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
共接收两个参数,第一个参数是列数,第二个参数是布局的排列方向。

fruit_item.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="wrap_content"
    android:layout_margin="5dp">

    <ImageView
        android:id="@+id/fruit_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:layout_marginTop="10dp"/>

</LinearLayout>

MainActivity.java代码如下:

package com.example.recyclerviewtest;

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 List<Fruit> fruitList = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruits();
        //获取recyclerView实例
        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
        //创建一个StaggeredGridLayoutManager实例,共接收两个参数,第一个参数是列数,第二个参数是布局的排列方向
        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
        //设置布局
        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        //关联RecyclerView与数据
        recyclerView.setAdapter(adapter);
    }

    private void initFruits() {
        for(int i = 0; i < 2; i++) {
            Fruit apple = new Fruit("Apple", R.drawable.apple_pic);
            fruitList.add(apple);
            Fruit banana = new Fruit("BananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBananaBanana", R.drawable.banana_pic);
            fruitList.add(banana);
            Fruit orange = new Fruit("Orange", R.drawable.orange_pic);
            fruitList.add(orange);
            Fruit watermelon = new Fruit("Watermelon", R.drawable.watermelon_pic);
            fruitList.add(watermelon);
            Fruit pear = new Fruit("Pear", R.drawable.pear_pic);
            fruitList.add(pear);
            Fruit grape = new Fruit("GrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrapeGrape", R.drawable.grape_pic);
            fruitList.add(grape);
            Fruit pineapple = new Fruit("Pineapple", R.drawable.pineapple_pic);
            fruitList.add(pineapple);
            Fruit strawberry = new Fruit("Strawberry", R.drawable.strawberry_pic);
            fruitList.add(strawberry);
            Fruit cherry = new Fruit("Cherry", R.drawable.cherry_pic);
            fruitList.add(cherry);
            Fruit mango = new Fruit("Mango", R.drawable.mango_pic);
            fruitList.add(mango);
        }
    }
}

运行结果如下:

功能三Demo文件下载:https://download.csdn.net/download/qq_38367681/12169036

功能四:RecyclerView的点击事件。

  RecyclerView所有的点击事件都需要具体的View控件去注册,其实这样反而会更舒服,我们可以为任何我们想要触发点击事件的控件,布局,甚至是RecyclerView列表子项添加点击事件。为RecyclerView子项添加点击监听时,我们在ViewHolder中添加fruitView变量用来保存子项最外层的布局实例,然后在onCreateViewHolder()方法中注册点击事件即可。为子项的控件添加点击监听时,直接用viewholder里的布局控件注册点击即可。代码如下:

FruitAdapter.java

package com.example.recyclerviewtest;

import android.media.Image;
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 org.w3c.dom.Text;

import java.util.List;

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {

    private List<Fruit> mFruitList;

    //传入view参数,这个参数就是RecyclerView的子项布局,这样就能找到里面各个控件的id
    static class ViewHolder extends RecyclerView.ViewHolder {
        //整个子项布局
        View fruitView;

        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            fruitView = itemView;
            fruitImage = (ImageView)itemView.findViewById(R.id.fruit_image);
            fruitName = (TextView)itemView.findViewById(R.id.fruit_name);
        }
    }

    //将要展示的数据源传入
    public FruitAdapter(List<Fruit> fruitList) {
        mFruitList = fruitList;
    }

    //下面三个函数必须要重写

    //载入fruit_item布局,创建ViewHolder实例
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
        final ViewHolder holder = new ViewHolder(view);

        //为子项的实例布局添加点击监听
        holder.fruitView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(), "you clicked view" + fruit.getName(), Toast.LENGTH_SHORT).show();
            }
        });

        //为每个子项的图片添加点击监听
        holder.fruitImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(), "you clicked image" + fruit.getName(), Toast.LENGTH_SHORT).show();
            }
        });
        return holder;
    }

    //为每个RecylerView对象赋值
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitName.setText(fruit.getName());
        holder.fruitImage.setImageResource(fruit.getImageId());
    }

    //计算一共多少个子项
    @Override
    public int getItemCount() {
        return mFruitList.size();
    }

}

运行结果如下:

点击图片时 

当点击文字(其实代表的是图片文字整个子项被点击,因为给图片注册了点击监听,所以只能点文字表明点击了整个子项)

功能四Demo文件下载:https://download.csdn.net/download/qq_38367681/12169120

直接复制使用吧,祝愉快

发布了113 篇原创文章 · 获赞 33 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_38367681/article/details/104370115
今日推荐