【Android入门到项目实战--3.5】—— 滚动控件RecyclerView的使用

目录

序言

一、RecyclerView的基本用法

 二、实现横向滚动和瀑布流布局

1、横向滚动

2、瀑布流布局

二、RecyclerView的点击事件


本篇文章主要讲解滚动控件RecyclerView的使用,包括基本使用和点击事件。

序言

        上篇文章主要讲解了ListView的用法,但是ListView并不是完全没有缺点的,如:不使用技巧优化,性能会很差;还有,扩展性也不够好,它只能实现数据纵向滚动的效果。

        为此RecyclerView不仅可以轻松实现和ListView同样的效果,还优化了ListView中存在的各种不足,且Android官方也更加推荐使用RecyclerView。

一、RecyclerView的基本用法

        RecyclerView属于新增控件,被定义在了support库中,想要使用,需要在项目的build.gradle中添加相应的依赖库。

首先新建RecyclerView项目,并创建好活动。

打开app/build.gradle,在dependencies闭包中添加如下代码:

implementation 'androidx.recyclerview:recyclerview:1.2.1'

添加完后点击Sync Now来同步。

然后修改activity_main.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="match_parent">

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

接下来实现与前一文章的ListView相同的效果,直接将Image类、item.xml、image3.png复制过来(如有需要参考代码,请参考上一文章,链接:https://blog.csdn.net/Tir_zhang/article/details/129718771?spm=1001.2014.3001.5501)。

接下来为RecyclerView准备一个适配器,新建一个adapter类,代码如下:

        代码稍微有点长,但是比ListView适配器更好理解。

        首先定义一个内部类ViewHolder,继承自RecyclerView.ViewHolder,然后在构造函数中传入View参数,这个参数通常是RecyclerView子项的最外层布局,然后可以通过findViewById()方法来获取到布局中的ImageView和TextView实例了。

        adapter的构造函数,用于把展示的数据源传进来。

        adapter继承自RecyclerView.Adapter,需要重写onCreateViewHolder()、onBindViewHolder()、getItemCount()这3个方法。onCreateViewHolder()方法是用于创建ViewHolder实例的onBindViewHolder()方法用于对RecyclerView子项数据赋值,会在子项被滚动到屏幕内的时候执行,通过position参数获取到当前项的实例,再设置到ImageView和TextView当中;getItemCount()方法用于告诉RecyclerView一共有多少子项,直接返回长度。

public class adapter extends RecyclerView.Adapter<adapter.ViewHolder> {
    private List<Image> list;
    static class ViewHolder extends RecyclerView.ViewHolder{
        ImageView image;
        TextView name;
        public ViewHolder(View view){
            super(view);
            image = (ImageView) view.findViewById(R.id.image);
            name = (TextView) view.findViewById(R.id.name);
        }
    }

    public adapter(List<Image> list2){
        list = list2;
    }

    public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType){
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false);
        ViewHolder holder = new ViewHolder(view);
        return holder;
    }
    
    public void onBindViewHolder(ViewHolder holder,int position){
        Image image = list.get(position);
        holder.image.setImageResource(image.getImageId());
        holder.name.setText(image.getName());
    }
    
    public int getItemCount(){
        return list.size();
    }
}

准备好适配器,可以使用RecyclerView了,修改MainActivity中的代码,如下:

        下面的LayoutManager用于指定RecyclerView的布局方式,这里使用的LinearLayoutManager是线性布局的意思。

public class MainActivity extends AppCompatActivity {
    private List<Image> list = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();//初始化数据
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        adapter ad = new adapter(list);
        recyclerView.setAdapter(ad);
    }
    private void init(){
        for(int i = 0; i < 2; i++){
            Image a = new Image("A",R.drawable.image3);
            list.add(a);
            Image b = new Image("B",R.drawable.image3);
            list.add(b);
            Image c = new Image("C",R.drawable.image3);
            list.add(c);
            Image d = new Image("D",R.drawable.image3);
            list.add(d);
            Image e = new Image("E",R.drawable.image3);
            list.add(e);
        }
    }
}

效果如下:

 二、实现横向滚动和瀑布流布局

1、横向滚动

首先修改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/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

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

</LinearLayout>

接下来修改MainActivity代码,如下:

 只加入了一行代码:   layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

默认是纵向排列,调用setOrientation()方法来设置布局排列方向。

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();//初始化数据
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        
        recyclerView.setLayoutManager(layoutManager);
        adapter ad = new adapter(list);
        recyclerView.setAdapter(ad);
    }

效果如下:

2、瀑布流布局

    除LinearLayoutManager之外,还有GridLayoutManager和StaggeredGridLayoutManager这两种内置的布局方式。GridLayoutManager用来实现网格布局,StaggeredGridLayoutManager用来实现瀑布流布局,下面实现瀑布流布局。

修改item.xml代码,如下:

        这里只修改了两部分,首先将LinearLayout的宽度由100dp改成了match_parent,因为瀑布流的宽度应该是根据布局的列数自动适配,而不是固定值;另外,TextView的对齐方式改成了左对齐。

<?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/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"/>

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

</LinearLayout>

接着修改MainActivity.java代码,如下:

        首先,再onCreate方法中,创建StaggeredGridLayoutManager实例,构造函数接收两个参数,第一个参数用于指定布局的列数,第二个参数用于指定布局的排列方向

public class MainActivity extends AppCompatActivity {
    private List<Image> list = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();//初始化数据
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);

        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);

        recyclerView.setLayoutManager(layoutManager);
        adapter ad = new adapter(list);
        recyclerView.setAdapter(ad);
    }
    private void init(){
        for(int i = 0; i < 5; i++){
            Image a = new Image("AAAAAAAAAAAAAAAAAA",R.drawable.image3);
            list.add(a);
            Image b = new Image("BBBBBB",R.drawable.image3);
            list.add(b);
            Image c = new Image("CCCCCCCCCCC",R.drawable.image3);
            list.add(c);
            Image d = new Image("DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",R.drawable.image3);
            list.add(d);
            Image e = new Image("EEE",R.drawable.image3);
            list.add(e);
        }
    }
}

效果如下:

二、RecyclerView的点击事件

        RecyclerView的点击事件需要我们自己给子项具体的View去注册点击事件,比ListView实现要复杂一点。

        那么为什么RecyclerView设计的更复杂一点?假设以下场景:如果想要点击子项里具体的按钮,如何做?ListView的setOnItemClickListener()方法注册的是子项的点击事件,实现这个功能比较麻烦,为此,RecyclerView直接去除了子项点击事件的监听器,所有的点击事件都有具体的View去注册。

接下来尝试实现。

修改adapter中的代码,如下:

        下面加粗部分为新增代码。

        imageView变量用来保存子项最外层布局的实例,然后在onCreateViewHolder()方法中注册点击事件,这里为ImageView注册了点击事件。

public class adapter extends RecyclerView.Adapter<adapter.ViewHolder> {
    private List<Image> list;
    static class ViewHolder extends RecyclerView.ViewHolder{
        View imageView;
        ImageView image;
        TextView name;
        public ViewHolder(View view){
            super(view);
            imageView = view;
            image = (ImageView) view.findViewById(R.id.image);
            name = (TextView) view.findViewById(R.id.name);
        }
    }

    public adapter(List<Image> list2){
        list = list2;
    }

    public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType){
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false);
        final ViewHolder holder = new ViewHolder(view);
        holder.imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int position = holder.getAbsoluteAdapterPosition();
                Image image = list.get(position);
                Toast.makeText(view.getContext(), "你点击了"+image.getName(), Toast.LENGTH_SHORT).show();
            }
        });
        return holder;
    }

...

}

      效果如下:


希望本文章对你有帮助,如果你对Android开发感兴趣,请持续关注本专栏,帮助你从入门到项目实战,你将收获:Android基础开发、各种经典功能实现、项目实战、开发自己的APP、将APP上传应用商店、靠广告赚钱等等,持续更新ing......

猜你喜欢

转载自blog.csdn.net/Tir_zhang/article/details/129738494