Android 三級和多級 ExpandableListView 列表的實現(xiàn)

相關(guān)鏈接

Android 打造任意層級樹形控件 考驗?zāi)愕臄?shù)據(jù)結(jié)構(gòu)和設(shè)計
android ListView 實現(xiàn)3級節(jié)點 (可拓展N級)

第一篇年代有點久了仇奶,需要約束數(shù)據(jù)格式押赊;第二篇來自這篇的靈感即舌,只是邏輯不一樣嘲叔,萬惡的轉(zhuǎn)載萬惡的百度奠支,文章各網(wǎng)站都是晕讲,一開始找到的源碼亂碼拳缠,找到原文時自己都寫好了墩新,原理都是對數(shù)據(jù)進(jìn)行包裝處理。本篇是自己迭代時刪除窟坐,相對來說效率更高海渊,同時增加展開全部和折疊全部绵疲。原文章是調(diào)用系統(tǒng)removeAll()刪除,removeAll()最終也是迭代刪除切省,只是在邏輯上跟容易理解最岗。

源碼實現(xiàn)

數(shù)據(jù)模型

package com.silicar.sample;

import android.content.Intent;

import java.util.List;

/**
 * Created by Brady on 2016/7/9.
 */
public class DataVo {
    String title;
    Intent intent;
    List<DataVo> dataVoList;

    public DataVo() {
    }

    public DataVo(String title, Intent intent, List<DataVo> dataVoList) {
        this.title = title;
        this.intent = intent;
        this.dataVoList = dataVoList;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Intent getIntent() {
        return intent;
    }

    public void setIntent(Intent intent) {
        this.intent = intent;
    }

    public List<DataVo> getDataVoList() {
        return dataVoList;
    }

    public void setDataVoList(List<DataVo> dataVoList) {
        this.dataVoList = dataVoList;
    }
}

數(shù)據(jù)包裝

package com.silicar.sample;

import java.util.List;

/**
 * Created by Brady on 2016/7/8.
 */
public class DataWrapper<T> {
    //存在下級列表
    private boolean hasChild;
    //折疊狀態(tài)
    private boolean isExpand;
    //列表等級
    private int level;
    //上一級位置
    private int parentPosition;
    //當(dāng)前等級位置
    private int position;
    //數(shù)據(jù)
    private T data;
    //下級數(shù)據(jù)
    private List<T> childList;

    public DataWrapper() {
    }

    public DataWrapper(boolean hasChild, boolean isExpand, int level, int parentPosition, int position, T data) {
        this.hasChild = hasChild;
        this.isExpand = isExpand;
        this.level = level;
        this.parentPosition = parentPosition;
        this.position = position;
        this.data = data;
    }

    public boolean isHasChild() {
        return hasChild;
    }

    public void setHasChild(boolean hasChild) {
        this.hasChild = hasChild;
    }

    public boolean isExpand() {
        return isExpand;
    }

    public void setExpand(boolean expand) {
        isExpand = expand;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public int getParentPosition() {
        return parentPosition;
    }

    public void setParentPosition(int parentPosition) {
        this.parentPosition = parentPosition;
    }

    public int getPosition() {
        return position;
    }

    public void setPosition(int position) {
        this.position = position;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public List<T> getChildList() {
        return childList;
    }

    public void setChildList(List<T> childList) {
        this.childList = childList;
    }
}

Adapter實現(xiàn)

package com.silicar.sample;

import android.content.Context;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.silicar.library.adapter.CommonAdapter;
import com.silicar.library.adapter.CommonViewHolder;
import com.silicar.library.adapter.ModelCommonAdapter;
import com.silicar.sample.databinding.ItemSampleListBinding;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Created by Brady on 2016/7/8.
 */
public class SampleListAdapter extends ModelCommonAdapter<DataWrapper> {

    public SampleListAdapter(Context context) {
        this(context, R.layout.item_sample_list);
    }

    public SampleListAdapter(Context context, int layoutId) {
        super(context, layoutId);
        adapter = new CommonAdapter<DataWrapper>(context, list, layoutId) {
            @Override
            public void onBindViewHolder(CommonViewHolder holder, DataWrapper item, int position) {
                ItemSampleListBinding binding = holder.getBinding();
                holder.itemView.setTag(POSITION, position);
                holder.itemView.setOnClickListener(mOnItemClickListener);
            }
        };
    }

    /**
     * 改變展開狀態(tài)
     *
     * @param position
     * @return
     */
    public boolean changeExpand(int position) {
        DataWrapper<DataVo> vo = list.get(position);
        //Log.e("Expand", "~" + vo.isExpand());
        //Log.e("HasChild", "~" + vo.isHasChild());
        if (vo.isHasChild()) {
            if (!vo.isExpand()) {
                addList(vo.getChildList(), vo.getLevel() + 1, vo.getPosition());
            } else {
                removeList(vo.getLevel(), vo.getPosition());
            }
            vo.setExpand(!vo.isExpand());
            return true;
        }
        return false;
    }

    /**
     * 添加(展開)列表
     *
     * @param dataVoList 列表
     * @param level      等級
     * @param parentPosition   上一級位置
     */
    public void addList(List<DataVo> dataVoList, int level, int parentPosition) {

        List<DataWrapper> dataWrapperList = new ArrayList<>();
        for (int i = 0; i < dataVoList.size(); i++) {
            DataVo vo = dataVoList.get(i);
            DataWrapper<DataVo> dataWrapper = new DataWrapper<>(false, false, level, parentPosition, i, vo);
            if (vo.getDataVoList() != null && !vo.getDataVoList().isEmpty()) {
                dataWrapper.setHasChild(true);
                dataWrapper.setChildList(vo.getDataVoList());
                //addList(vo.getDataVoList(), level + 1, i);
            }
            dataWrapperList.add(dataWrapper);
        }
        if (level == 1) {
            list.addAll(dataWrapperList);
        } else {
            DataWrapper<DataVo> vo;
            for (int i = 0; i < list.size(); i++) {
                vo = list.get(i);
                if (vo.getLevel() == level - 1 && vo.getPosition() == parentPosition) {
                    list.addAll(i + 1, dataWrapperList);
                    break;
                }
            }
        }
    }

    /**
     * 刪除(折疊)列表
     *
     * @param level    等級
     * @param parentPosition 位置
     */
    public void removeList(int level, int parentPosition) {
        Iterator<DataWrapper> iterator = list.iterator();
        removeList(iterator, level, parentPosition, -1);
    }

    /**
     * 刪除(折疊)列表
     *
     * @param iterator
     * @param level       等級
     * @param parentPosition    位置
     * @param oldPosition 上一級位置
     */
    private void removeList(Iterator<DataWrapper> iterator, int level, int parentPosition, int oldPosition) {
        DataWrapper<DataVo> vo;
        while (iterator.hasNext()) {
            vo = iterator.next();
            Log.e("level", "~" + vo.getLevel());
            Log.e("ParentPosition", "~" + vo.getParentPosition());
            Log.e("position", "~" + parentPosition);
            if (vo.getLevel() == level + 1 && vo.getParentPosition() == parentPosition) {
                iterator.remove();
                //存在下級并且已展開
                if (vo.isHasChild() && vo.isExpand()) {
                    removeList(iterator, vo.getLevel(), vo.getPosition(), parentPosition);
                }
            } else if (vo.getLevel() == level && vo.getParentPosition() == oldPosition) {
                //存在待刪除的上一級(只有-1位置表示不存在上一級)
                iterator.remove();
                break;
            } else if (vo.getLevel() == level && vo.getPosition() > parentPosition) {
                //超出刪除位置,結(jié)束遍歷
                break;
            }
        }
    }

    //展開全部
    public void expandAll(List<DataVo> dataVoList, int level, int parentPosition) {
        removeList(level, parentPosition);
        List<DataWrapper> dataWrapperList = new ArrayList<>();
        addExpandAll(dataVoList, dataWrapperList, level, parentPosition);
        if (level == 1) {
            list.addAll(dataWrapperList);
        } else {
            DataWrapper<DataVo> vo;
            for (int i = 0; i < list.size(); i++) {
                vo = list.get(i);
                if (vo.getLevel() == level - 1 && vo.getPosition() == parentPosition) {
                    list.addAll(i + 1, dataWrapperList);
                    break;
                }
            }
        }
    }

    private void addExpandAll(List<DataVo> dataVoList, List<DataWrapper> dataWrapperList, int level, int parentPosition){
        for (int i = 0; i < dataVoList.size(); i++) {
            DataVo vo = dataVoList.get(i);
            DataWrapper<DataVo> dataWrapper = new DataWrapper<>(false, false, level, parentPosition, i, vo);
            if (vo.getDataVoList() != null && !vo.getDataVoList().isEmpty()) {
                dataWrapper.setHasChild(true);
                dataWrapper.setChildList(vo.getDataVoList());
                addExpandAll(vo.getDataVoList(), dataWrapperList, level + 1, i);
            }
            dataWrapperList.add(dataWrapper);
        }
    }

    //折疊全部
    public void foldAll(int level, int parentPosition) {
        Iterator<DataWrapper> iterator = list.iterator();
        DataWrapper<DataVo> vo;
        while (iterator.hasNext()) {
            vo = iterator.next();
            if (vo.getLevel() == level && vo.getParentPosition() == parentPosition) {
                if (vo.isHasChild() && vo.isExpand()) {
                    removeList(iterator, vo.getLevel(), vo.getPosition(), parentPosition);
                }
            } else if (vo.getLevel() == level -1 && vo.getPosition() > parentPosition) {
                break;
            }
        }
    }

    @Override
    protected void onItemClick(View view, int position) {
        Toast.makeText(mContext, "" + position, Toast.LENGTH_SHORT).show();
    }

    @Override
    protected boolean onItemLongClick(View view, int position) {
        return false;
    }

    @Override
    protected void onChildClick(View view, int position) {

    }

    @Override
    protected boolean onChildLongClick(View view, int position) {
        return false;
    }
}

后記

完整內(nèi)容或源碼呢朝捆?
伸手黨就當(dāng)路過沒看見般渡,本文很早之前的文章沒寫完,現(xiàn)在不想繼續(xù)寫了芙盘,以上貼出的代碼已經(jīng)給出關(guān)鍵的代碼并有注釋驯用,請自行實現(xiàn)。

本作品采用知識共享署名-非商業(yè)性使用-相同方式共享 4.0 國際許可協(xié)議進(jìn)行許可儒老。轉(zhuǎn)載請保留作者及原文鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蝴乔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子驮樊,更是在濱河造成了極大的恐慌薇正,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件囚衔,死亡現(xiàn)場離奇詭異挖腰,居然都是意外死亡,警方通過查閱死者的電腦和手機练湿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門猴仑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肥哎,你說我怎么就攤上這事辽俗。” “怎么了篡诽?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵崖飘,是天一觀的道長。 經(jīng)常有香客問我杈女,道長朱浴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任碧信,我火速辦了婚禮赊琳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘砰碴。我一直安慰自己躏筏,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布呈枉。 她就那樣靜靜地躺著趁尼,像睡著了一般埃碱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上酥泞,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天砚殿,我揣著相機與錄音,去河邊找鬼芝囤。 笑死似炎,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的悯姊。 我是一名探鬼主播羡藐,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼悯许!你這毒婦竟也來了仆嗦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤先壕,失蹤者是張志新(化名)和其女友劉穎瘩扼,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體垃僚,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡集绰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了冈在。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倒慧。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡按摘,死狀恐怖包券,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情炫贤,我是刑警寧澤溅固,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站兰珍,受9級特大地震影響侍郭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掠河,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一亮元、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧唠摹,春花似錦爆捞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盗温。三九已至,卻和暖如春成肘,著一層夾襖步出監(jiān)牢的瞬間卖局,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工双霍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留砚偶,地道東北人。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓洒闸,卻偏偏與公主長得像蟹演,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子顷蟀,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,081評論 25 707
  • 已經(jīng)是連續(xù)的第三天開始失眠了酒请,一天比一天嚴(yán)重,今天的結(jié)果就是鸣个,凌晨三點多的我還清醒著羞反。 好幾次去伸手拿手機看時間,...
    晴未末閱讀 305評論 0 0
  • 11.3文明是原始欲望的升華 隨著教育科技的不斷提升人類早已進(jìn)去文明社會囤萤。同樣隨著文明的到來人們對欲望的索取也...
    徐猛_Merlin閱讀 365評論 0 0
  • 今天休息在家跟孩子吃完早餐后昼窗,孩子在拼圖,還要我一定要幫她照相呢涛舍。幫孩子檢查作業(yè)澄惊,這學(xué)期又接近尾聲了,孩子的成績還...
    黃泳儀閱讀 105評論 0 1