简单学习 RecyclerView

under Android  tag     Published on March 2nd , 2021 at 04:59 pm

RecyclerView 可以实现数据纵向滚动,也可以实现横向滚动。和 ListView 实现效果相同,但比 ListView 好一点点,因为 ListView 不能横向滚动。

使用 RecyclerView 先添加依赖库

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

纵向滚动

activity_main.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:layout_height="match_parent"
    tools:context=".MainActivity">

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

</LinearLayout>

Bean.java

package com.example.java;

public class Bean {
    private int imgId;
    private String name;

    public Bean(int imgId, String name) {
        this.imgId = imgId;
        this.name = name;
    }

    public int getImgId() {
        return imgId;
    }

    public void setImgId(int imgId) {
        this.imgId = imgId;
    }

    public String getName() {
        return name;
    }

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

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/image"
        android:layout_width="50dp"
        android:layout_height="50dp" />

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

Adapter.java

适配器需继承 RecyclerView.Adapter ,并把泛型指定为 Adapter.ViewHolder。

public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
    private List<Bean> list = null;

    public Adapter(List<Bean> list) {
        this.list = list;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Bean bean = list.get(position);
        holder.image.setBackgroundResource(bean.getImgId());
        holder.name.setText(bean.getName());
    }

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

    protected static class ViewHolder extends RecyclerView.ViewHolder {
        private ImageView image;
        private TextView name;

        public ViewHolder(View view) {
            super(view);
            image = (ImageView) view.findViewById(R.id.image);
            name = (TextView) view.findViewById(R.id.name);
        }
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private ArrayList<Bean> list = new ArrayList<>();

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

        recyclerView = findViewById(R.id.r_view);
        saveDate();

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        Adapter adapter = new Adapter(list);
        recyclerView.setAdapter(adapter);
    }

    private void saveDate() {
        for (int i = 0; i < 3; i++) {
            list.add(new Bean(R.drawable.gift, "111111q"));
            list.add(new Bean(R.drawable.gift, "222222q"));
            list.add(new Bean(R.drawable.gift, "333333q"));
            list.add(new Bean(R.drawable.gift, "444444q"));
            list.add(new Bean(R.drawable.gift, "555555q"));
        }
    }
}

LayoutManager 用于指定 RecyclerView 的布局方式。LinearLayoutManager 指的是线性布局。

运行效果:

1.png

横向滚动

修改纵向滚动中一点点代码即可

item.xml

只修改线性布局的宽。纵向宽为 match_parent 。

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

    <ImageView
        android:id="@+id/image"
        android:layout_width="50dp"
        android:layout_height="50dp" />

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

MainActivity.java

调用 setOrientation()把布局排列方式改为水平排列。
不多贴代码了,只添加了一句:

layoutManager.setOrientation(RecyclerView.HORIZONTAL);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(RecyclerView.HORIZONTAL);
        recyclerView.setLayoutManager(layoutManager);
        Adapter adapter = new Adapter(list);
        recyclerView.setAdapter(adapter);

运行效果:

2.png

除了 LinearLayoutManager,RecyclerView 还提供了 GridLayoutManager (网格布局)StaggeredGridLayoutManager(瀑布流布局)

GridLayoutManager (网格布局)

    /**
     * Creates a vertical GridLayoutManager
     *
     * @param context Current context, will be used to access resources.
     * @param spanCount The number of columns in the grid
     */
    public GridLayoutManager(Context context, int spanCount) {
        super(context);
        setSpanCount(spanCount);
    }

context 不解释,spanCount 是网格列数。实现效果和 GridView 相同,也只需要添加一行代码。

MainActivity.java

//    横向滚动的两行代码需要注释或删除
//        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
//        layoutManager.setOrientation(RecyclerView.HORIZONTAL);
        GridLayoutManager layoutManager = new GridLayoutManager(this,3);

运行效果:

3.png

StaggeredGridLayoutManager(瀑布流布局)

    /**
     * Creates a StaggeredGridLayoutManager with given parameters.
     *
     * @param spanCount   If orientation is vertical, spanCount is number of columns. If
     *                    orientation is horizontal, spanCount is number of rows.
     * @param orientation {@link #VERTICAL} or {@link #HORIZONTAL}
     */
    public StaggeredGridLayoutManager(int spanCount, int orientation) {
        mOrientation = orientation;
        setSpanCount(spanCount);
        mLayoutState = new LayoutState();
        createOrientationHelpers();
    }

先解释 orientation 吧, orientation 是布局排列方向。如果 orientation 是垂直排列( VERTICAL ),则 spanCount 是列数;如果是水平排列( HORIZONTAL ),则是行数。

MainActivity.java

//    记得注释或删除 GridLayoutManager
        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);

运行效果:

4.png

为了演示效果,我把 list 中 name 改长了。可以清楚的看出 GridLayoutManager 和StaggeredGridLayoutManager 的区别了。

GridLayoutManager 是会固定高度的,如果列表内容高度不统一,会留下很多空白区域。

StaggeredGridLayoutManager 并不会固定高度,不管列表内容的高度差距多大,下一行的数据还是会向上一行数据靠拢。

RecyclerView 中 item 的点击事件

虽然 RecyclerView 很好的实现了 ListView 和 GridView 的效果,但是并没有它们的 setOnItemClickListener 方法,所以要在自定义的 Adapter 中的 onBindViewHolder 方法中设置。

//view 是 onCreateViewHolder方法中的,提出来就能在这个方法里使用。
    view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(view.getContext(), "点击了"+list.get(position).getName(), Toast.LENGTH_SHORT).show();
            }
        });

本文由 surface 创作,采用 知识共享署名4.0 国际许可协议进行许可,转载前请务必署名
  文章最后更新时间为:October 15th , 2021 at 05:42 pm
分享到:Twitter  Weibo  Facebook