1. 程式人生 > >基於RecyclerView的分組列表

基於RecyclerView的分組列表

基於RecyclerView的分組列表

一、實現效果

基於RecyclerView的分組列表

演示APK

SectionList.java

演示工程專案

二、使用方式

1. 建立SectionList例項

必須傳入SectionListAdapterCallback例項,當SectionList內部發生變化時(展開、摺疊、……)通知adapter

this.sectionList = new SectionList(new SectionListAdapterCallback(adapter));

2. 新增分組

新增分組資料由3個部分組成。

  • Object userObject分組自身的資料
  • boolean expand初始狀態,展開或者摺疊
  • ClazzAdapterProvider provider
    分組資料提供者,獲取分組下的子資料
sectionList.add(entranceSection, true, entranceSection);
sectionList.add(favoriteSection, true, favoriteSection);
sectionList.add(tagSection, true, tagSection);

3. 資料關聯到Adapter

這裡使用了二次封裝的Adapter,簡化了RecyclerView.Adapter的使用。

this.adapter = new BridgeAdapter(getActivity(),
new SectionListProvider());
private class SectionListProvider implements BridgeAdapterProvider {

    @Override
    public Object get(int position) {
    return sectionList.get(position);
    }

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

三、設計思路

與《基於RecyclerView的樹形結構》同樣的設計思路,沒有提供特定的資料結構。只需要將資料遷移到SectionList,並且實現ClazzAdapterProvider介面,提供分組的子資料,完全不需要改動ViewHolder,調整部分Adapter程式碼,即可實現分組列表功能。

四、程式碼分析

1. 核心屬性

ArrayList<Section> list; // 分組資料

SectionList.Callback callback; // 回撥介面

2. Section分組類

儲存分組的資料以及摺疊/展開狀態。

private static class Section {

    boolean expand;

    Object userObject;
    ClazzAdapterProvider provider;

    public Section(Object userObject, boolean expand, ClazzAdapterProvider provider) {
        this.expand = expand;

        this.userObject = userObject;
        this.provider = provider; 
    }

    public Object getUserObject() {
        return userObject;
    }

    void setExpand(boolean value) {
        if (!(expand ^ value)) {
            return;
        }

        this.expand = value;
    }

    boolean isExpand() {
        return expand;
    }

    Object get(int index) {
        return provider.get(index);
    }

    int size() {
        return provider.size();
    }

}

3. 獲取列表資料

TreeList不同,沒有將資料儲存到列表中,而是採用遍歷Section的方式獲取資料。

public Object get(int position) {
    Object obj = null;

    for (Section s : list) {
        if (position == 0) {
            obj = s.getUserObject();
            break;
        }

        position -= 1;
        if (s.isExpand() && position < s.size()) {
            obj = s.get(position);
            break;
        }

        if (s.isExpand()) {
            position -= s.size();
        }
    }

    return obj;
}

4. 獲取總數

同樣採用遍歷Section的方式來獲取。

public int size() {
    int size = 0;
    for (Section s : list) {
        size += 1;

        if (s.isExpand()) {
            size += s.size();
        }
    }

    return size;
}

5. balabalabala……

程式碼很簡單,懶得寫了,自己看:)

SectionList.java