1. 程式人生 > >Android教程2020 - RecyclerView實際使用

Android教程2020 - RecyclerView實際使用

示例,用RecyclerView的item做出一個列表。

Android教程2020 - 系列總覽

本文連結

前面我們已經知道如何用RecyclerView顯示一列資料。這裡我們做出一個具體的例子。儘量做好看一點。

這個示例會分為以下幾個步驟:

  • 確定資料。這裡用的是模擬資料。
  • 設計UI和表現形式。
  • 編寫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>

準備顏色,尺寸等資源

相關的style和顏色,尺寸配置檔案,在res/values目錄下。

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的寬度。

顏色配置檔案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。

    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()是生成模擬的資料。

執行效果

執行起來即可看到效果。

使用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

也就是在include標籤中,如果要設定其他屬性,需要先設定layout_width和layout_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。
分別設定文字即可。

執行看看效果,是不是和前面的一樣。

工程放這裡: https://github.com/AnRFDev/Tutorial2020
相關閱讀
RecyclerView - 使用入門
RecyclerView點選事件 - 如何設定點選事件
RecyclerView示例 - 實際使用
RecyclerView獲取滑動距離
RecyclerView顯示多種i