AndroidStudio-3.2.1(十)RecyclerView

本篇介绍列表视图中RecyclerView的用法。

RecyclerView用来展现各种列表视图,它不仅是ListView的升级,之前的Gallery、GridView的效果它也都可以实现。下面通过一个示例来展示RecyclerView的用法。

  • 基本设置
  • 不同布局样式
  • 添加分割线
  • 点击事件

基本设置

先看最终实现的界面效果:
在这里插入图片描述
1、首先添加一个Activity,并编辑布局文件如下。可以看到RecyclerView属于v7-支持库,如果你的androidsdk版本较旧的话,需要单独添加引用。

dependencies {
implementation ‘com.android.support:recyclerview-v7:27.1.1’
}

<?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">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

2、RecyclerView的基本方法有两个。

   mRecyclerView.setLayoutManager(linearLayoutManager);
   mRecyclerView.setAdapter(mMyAdapter);

分别需要一个继承自RecyclerView.Adapter的mMyAdapter(需自己编写)和一个继承自RecyclerView.LayoutManager的布局管理器,系统已经给了3个常用的:LinearLayoutManager、GridLayoutManager、StaggeredGridLayoutManager(瀑布布局)。
3、开始编写mMyAdapter的类RecycleAdapter

public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.NormalHolder>

在继承RecyclerView.Adapter时,发现需要指定一个继承自RecyclerView.ViewHolder的类。这里解释一下ViewHolder,它封装了列表子项中用到的具体控件,对每个列表子项的实例进行缓存,负责显示子项。我们不能再像ListView那样直接操作View并且处理缓存,这里改为操作ViewHolder即可,而且ViewHolder已经帮我们实现了缓存。
4、实现ViewHolder类
从效果图上可以看出列表子项里包括一个ImageView、一个大TextView、一个小TextView。对应的实现代码如下:

 public class NormalHolder extends RecyclerView.ViewHolder {
        public ImageView icon;
        public TextView title;
        public TextView des;

        public NormalHolder(@NonNull View itemView) {
            super(itemView);
            icon = itemView.findViewById(R.id.imgIcon);
            title = itemView.findViewById(R.id.txtName);
            des = itemView.findViewById(R.id.txtDes);
        }
    }

列表子项的界面代码 custom_listcell.xml :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:orientation="horizontal">
    <ImageView
        android:id="@+id/imgIcon"
        android:layout_width="60dp"
        android:layout_height="60dp" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">
        <TextView
            android:id="@+id/txtName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20dp" />
        <TextView
            android:id="@+id/txtDes"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="10dp" />
    </LinearLayout>
</LinearLayout>

列表子项的实体类代码 ListCellData.java:

public class ListCellData {
    private String controlName = "";
    private String controlDes = "";
    private int imgID;

    public ListCellData(String cn, String des, int imgid) {
        this.controlName = cn;
        this.controlDes = des;
        this.imgID = imgid;
    }

    public String getControlaName() { return controlName;}

    public String getControlDes() { return controlDes; }

    public void setControlDes(String controlDes) { this.controlDes = controlDes; }

    public int getImgID() { return imgID;}

    public void setImgID(int imgID) { this.imgID = imgID;}
}

5、具体实现RecycleAdapter (RecycleAdapter.java)

public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.NormalHolder> {

    private Context context;
    List<ListCellData> datasource;//用来接收列表数据源

    public RecycleAdapter(Context ct, List<ListCellData> ds) {
        context = ct;
        datasource = ds;
    }
    
    //创建ViewHolder,这里返回我们自己编写的NormalHolder
    @NonNull
    @Override
    public NormalHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new NormalHolder(LayoutInflater.from(context).inflate(R.layout.custom_listcell, null));
    }

    //填充视图,根据posotion取得具体数据项,并填充到界面上
    @Override
    public void onBindViewHolder(@NonNull final NormalHolder holder, int position)       {
        holder.title.setText(datasource.get(position).getControlaName());
        holder.des.setText(datasource.get(position).getControlDes());
        holder.icon.setImageResource(datasource.get(position).getImgID());
    }

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

6、最后给出主Activity的代码(RecyclerActivity.java)。运行之后,就是本篇开始给出的效果了。

  private RecyclerView mRecyclerView;
  private RecycleAdapter mMyAdapter;
  private LinearLayoutManager linearLayoutManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler);
        initData();
        mRecyclerView = findViewById(R.id.recyclerView);
        mMyAdapter = new RecycleAdapter(this,datasource);
        linearLayoutManager = new LinearLayoutManager(this,OrientationHelper.VERTICAL,false);
       
        mRecyclerView.setLayoutManager(linearLayoutManager);
        mRecyclerView.setAdapter(mMyAdapter);
    }

分割线

添加分割线

mRecyclerView.addItemDecoration(new DividerItemDecoration(
                getActivity(), DividerItemDecoration.HORIZONTAL_LIST));

效果图:
在这里插入图片描述
当然我们可以自定义分割线的样式,通过查看DividerItemDecoration的源码可知,它会读取系统主题中的@android:attr/listDivider作为 Item 的分割线(实质 Drawable ),同时还提供 setDrawable()方法,允许我们为分割线指定样式。感兴趣的可以自己写一个Drawable,设置代码如下:

//改成如下:
DividerItemDecoration decoration = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL);
decoration.setDrawable(getResources().getDrawable(R.drawable.divider,null));
mRecyclerView.addItemDecoration(decoration);

不同布局样式

切换不同的布局样式,只需设定不同的LayoutManager即可。
1、开篇给出了最常用的竖向LinearLayoutManager,下面演示横向的;

linearLayoutManager = new LinearLayoutManager(this,OrientationHelper.HORIZONTAL,false);

效果如图:
在这里插入图片描述
2、GridLayoutManager.构造函数里需要指定Grid的列数。

 gridLayoutManager = new GridLayoutManager(this,3);
 mRecyclerView.setLayoutManager(gridLayoutManager );

效果图:
在这里插入图片描述
3、最后是瀑布式布局,构造函数里需要指定列数和方向。

staggeredGridLayoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(staggeredGridLayoutManager);

为了展示出瀑布的效果,我们需要子项有不同的高度,在RecycleAdapter的RecycleAdapter方法里,我们加一个随机高度:

 ViewGroup.LayoutParams layoutParams = holder.title.getLayoutParams();
 layoutParams.height = new Random().nextInt(100) + 60;
 holder.title.setLayoutParams(layoutParams);

效果图:
在这里插入图片描述

点击事件

RecyclerView 本身不提供点击事件,需要在onBindViewHolder事件里,自己配置控件的点击事件。虽然ListView 提供了点击事件,但是只能针对子项。而RecyclerView 可按需对任意子项 设置点击监听。
1、首先在RecycleAdapter中,添加点击监听事件:

 public interface IItemClickListener {
        void onItemClick(View view, int position);
        void onItemLongClick(View view, int posiition);
    }

    private IItemClickListener iItemClickListener;
    public void setOnItemClickListener(IItemClickListener listener) {
        iItemClickListener = listener;
    }

2、在onBindViewHolder中,将点击事件注册到控件上:

 if (iItemClickListener != null) {
            holder.title.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int pos = holder.getLayoutPosition();
                    iItemClickListener.onItemClick(holder.title, pos);
                }
            });
            holder.title.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    int pos = holder.getLayoutPosition();
                    iItemClickListener.onItemLongClick(holder.title, pos);
                    return  false;
                }
            });
        }

3、在RecyclerActivity中,设置点击事件的具体实现,并传入RecycleAdapter

mMyAdapter.setOnItemClickListener(new RecycleAdapter.IItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(RecyclerActivity.this, ((TextView)view).getText() + " click", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onItemLongClick(View view, int posiition) {
                Toast.makeText(RecyclerActivity.this, posiition + " Long click", Toast.LENGTH_SHORT).show();
                mMyAdapter.removeData(posiition);
            }
        });

我们对列表子项中的title(大TextView)控件设置了点击和长按事件,运行后即可看效果。

猜你喜欢

转载自blog.csdn.net/SHENCHEN1987/article/details/88774807