Skip to content

RecyclerView实际使用

示例,用RecyclerView做出一个列表。显示测试数据。

前面我们已经知道如何用RecyclerView显示一列数据。这里我们做出一个具体的例子。尽量做好看一点。

这个示例会分为以下几个步骤:

  • 1.确定数据。这里用的是模拟数据。
  • 2.设计UI和表现形式。
  • 3.编写layout与适配器。

模拟数据

巧妇难为无米之炊,模拟数据就是模拟需求。

新建一个类DataTest,设计4个属性。

public class DataTest {
    private String timezone;
    private int number;
    private int personCount;
    private int count;

    public DataTest(String timezone, int number, int personCount, int count) {
        this.timezone = timezone;
        this.number = number;
        this.personCount = personCount;
        this.count = count;
    }
// getter setter...
}

设计item的布局

设计UI,在一行里显示4个属性值。item用的是item_recy2.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"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/tv1"
        style="@style/RePage2Header"
        android:layout_marginEnd="@dimen/re_2_half_gap" />

    <TextView
        android:id="@+id/tv2"
        style="@style/RePage2Header"
        android:layout_marginStart="@dimen/re_2_half_gap"
        android:layout_marginEnd="@dimen/re_2_half_gap" />

    <TextView
        android:id="@+id/tv3"
        style="@style/RePage2Header"
        android:layout_marginStart="@dimen/re_2_half_gap"
        android:layout_marginEnd="@dimen/re_2_half_gap" />

    <TextView
        android:id="@+id/tv4"
        style="@style/RePage2Header"
        android:layout_marginStart="@dimen/re_2_half_gap" />

</LinearLayout>

本例中的ui我们自由发挥。

准备颜色,尺寸等资源

相关的style和颜色,尺寸配置文件,在res/values目录下。

关于资源文件,可以参考res资源目录简介

style文件style.xml

<style name="RePage2Header">
    <item name="android:layout_width">0dp</item>
    <item name="android:layout_height">40dp</item>
    <item name="android:layout_weight">2</item>
    <item name="android:textColor">#ffffff</item>
    <item name="android:gravity">center</item>
    <item name="android:background">@color/rePage2Item</item>
</style>
我们给layout里的每个TextView都设置了layout_width为0dp。是为了使用layout_weight属性。 让它们4个TextView按比例分割父View的宽度。

这里的分割用到了LinearLayout的分割占比特性。

颜色配置文件color.xml,添加如下颜色设置。

<color name="rePage2Item">#082941</color>

尺寸配置dimens.xml

<dimen name="re_2_gap">4dp</dimen>
<dimen name="re_2_half_gap">2dp</dimen>

设计ViewHolder

资源文件和layout准备妥当,开始写对应的viewHolder。这里也是把VH类和Adapter类放在activity类里面。

private class VH extends RecyclerView.ViewHolder {
    TextView tv1;
    TextView tv2;
    TextView tv3;
    TextView tv4;

    public VH(@NonNull View itemView) {
        super(itemView);
        tv1 = itemView.findViewById(R.id.tv1);
        tv2 = itemView.findViewById(R.id.tv2);
        tv3 = itemView.findViewById(R.id.tv3);
        tv4 = itemView.findViewById(R.id.tv4);
    }
}

设计Adapter类

适配器Adapter类。

private class Adapter extends RecyclerView.Adapter<VH> {

    private List<DataTest> dataList = new ArrayList<>();

    public Adapter() {
    }

    public void setDataList(List<DataTest> dataList) {
        this.dataList = dataList; // 最好进行判空操作
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new VH(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recy2, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull VH holder, int position) {
        DataTest dataTest = dataList.get(position);
        holder.tv1.setText(dataTest.getTimezone());
        holder.tv2.setText(String.valueOf(dataTest.getNumber()));
        holder.tv3.setText(String.valueOf(dataTest.getPersonCount()));
        holder.tv4.setText(String.valueOf(dataTest.getCount()));
    }

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

配置RecyclerView

设置recyclerview。

// 在activity或者fragment里
private Adapter mAdapter = new Adapter();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.act_recy_2);
    RecyclerView recyclerView = findViewById(R.id.re_view);
    recyclerView.setLayoutManager(new LinearLayoutManager(this, RecyclerView.VERTICAL, false));
    recyclerView.setAdapter(mAdapter);
    mAdapter.setDataList(genDataTestList());
    recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
        @Override
        public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            outRect.top = getResources().getDimensionPixelOffset(R.dimen.re_2_gap);
        }
    });
}

// 生成模拟数据
private List<DataTest> genDataTestList() {
    List<DataTest> list = new ArrayList<>();
    for (int i = 1; i <= 60; i++) {
        DataTest d = new DataTest("时区" + i, i, i, i);
        list.add(d);
    }
    return list;
}
onCreate方法中配置recyclerView。 recyclerView.addItemDecoration方法是给item设置间隔样式。 getItemOffsets可以设置子项的间距。这里给子项底部一个间距值。具体数值设置在dimen中。 genDataTestList()是生成模拟的数据。

运行效果

运行起来即可看到效果。

运行效果图1

使用include修改layout

看到效果图,有的朋友问:表头和item的结构是一样的,可以复用吗?

其实是可以的。我们可以在layout中使用include标签,把另一个layout文件“包含”进来。 复制act_recy_2.xml粘贴得到act_recy_2_include.xml,把原来的表头的LinearLayout改成include。

<include layout="@layout/item_recy2" />
给include设定layout,即我们定义的item的布局item_recy2。 当我们想添加个margin-top的时候,比如这样
<include
    android:layout_marginTop="4dp"
    layout="@layout/item_recy2" />

as会弹出警告:

Layout parameter layout_marginTop ignored unless both layout_width and layout_height are also specified on tag

也就是在include标签中,如果要设置其他属性,需要先设置layout_widthlayout_height

修改一下,再加个id,变成这样。

<include
    android:id="@+id/header"
    layout="@layout/item_recy2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="4dp" />

让Activity使用这个layout。修改一下RecyclerViewDemo2Act

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.act_recy_2_include);
    initHeader();
    // 配置RecyclerView的部分
}

private void initHeader() {
    View header = findViewById(R.id.header);
    TextView tv1 = header.findViewById(R.id.tv1);
    tv1.setText("时区");
    TextView tv2 = header.findViewById(R.id.tv2);
    tv2.setText("序号");
    TextView tv3 = header.findViewById(R.id.tv3);
    tv3.setText("人员");
    TextView tv4 = header.findViewById(R.id.tv4);
    tv4.setText("数量");
}
我们添加了一个方法initHeader()。里面先把header找到,通过header找到它的子view,也就是那4个TextView。 分别设置文字即可。

运行看看效果,是不是和前面的一样。

作者: RustFisher
联系: rf.cs@foxmail.com
博客: rustfisher.com | RustFisher cnblog
示例: AndroidTutorial Gitee, Tutorial Github
链接: https://www.an.rustfisher.com/android/ui/view/recyclerView/demo1/
一家之言,仅当抛砖引玉。如有错漏,还请指出。