YasuoRecyclerViewAdapter!讓你在Android中快樂的實現列表!

圖片來自:https://www.zcool.com.cn/work/ZNDU0NzA2MTY=.html

1、前言

自從我開始作安卓開發以來,我就得了一種病,Adapter編寫焦慮症。在現現在的安卓App開發中,你們用得最多的ViewGroup,那必定是身爲老大哥的RecyclerView,單佈局列表,多佈局列表,網格列表,瀑布流列表,摺疊列表,吸頂列表,甚至一個無需滾動的頁面,出於屏幕高度適配考慮,都有可能作成列表形式。這足以證實RecyclerView在實際開發中的重要性。html

那麼這樣一個如此重要的組件,一般狀況下咱們須要怎麼實現呢?vue

第一步:在佈局中添加RecyclerVIew 第二步:建立item佈局及其實體類 第三步:繼承RecyclerView.Adapter類,編寫自定義Adapter 第四步:綁定Adapter到RecyclerViewjava

以上即是實現一個完整的列表所需的步驟,其中第三步可謂是整個流程中最爲複雜的,目前的一些三方庫,在必定程度上簡化了第三步,讓開發者在繼承了他們自定義的Adapter以後,能夠少些很大一部分的代碼,從而提高開發效率,我之前也是用過這些優秀的庫,好比安卓界使用最普遍BRVAH,爲開發者們大大減小了開發時間,讓你們有時間回家陪陪家人,首先在這裏感謝各位大佬的貢獻。git

可是,因爲我接觸kotlin比較早,2016年7月開始從事Android開發,2017年初開始接觸kotlin,而後在17年5月google開始正式欽定kotlin以後便開始正式使用kotlin作項目,從那時起,我就被kotlin的dsl所吸引,便開始嘗試將這些優秀的第三方庫進行dsl的改造,奈何當時的能力不足,這種幾乎重寫的改造宣告失敗。既然大型改造不行,那我能不能去找一些別人寫好的adapter dsl呢?因而通過個人不斷搜索,終於在github上找到了一些庫,好比kotlin-adapterYasha程序員

這兩個都是優秀的庫,曾經我也在項目中使用過他們,可是漸漸地我發現他們已經沒法知足個人一些需求了,我便開始嘗試寫一個本身用的庫。當時這個庫仍是存在於個人私有項目中,我在項目中遇到的問題就能夠及時改,直到19年的上半年爲止,這個庫基本能夠用於大多很多天常開發,當時我就考慮將它進行一些完善工做後開源,可是世事難料,因爲工做緣由,19年的7月,我去了一趟柬埔寨,沒錯,就是程序員們口誅筆伐的東南亞國家之一。github

去那邊以後,由於人手問題,我不得不學習了vue開發,flutter開發,以及後端開發,幾乎沒有時間來搞這個庫的開源工做。時間到了20年的9月,因爲工做安排,又回到了重慶,又通過幾個月的忙碌後,終於在最近抽出了一些時間,來繼續進行做業。後端

當我從新審視這個庫的時候,我發現了不少能夠優化的點,這表明我這一年可能是在進步,我很高興,而後花了兩三週的空餘時間將其優化完善,新增一些功能後,我決定在今天將它發佈出來,但願你們可以喜歡。api

很差意思,前言有點囉嗦,但依舊不妨礙後續的精彩。markdown

2、正片

簡單介紹一下這個庫:YasuoRecyclerViewAdapter ,爲何要取名爲Yasuo,由於亞索==快樂!這個庫就是爲了讓你們在寫代碼的時候感覺到快樂而存在的!app

一、功能特點

①、List,Grid,StaggeredGrid類型的正常佈局及多佈局

②、空白頁/頭部/尾部

③、加載更多

④、摺疊佈局(支持多級摺疊)

⑤、拖拽、橫向滑動刪除

⑥、附送兩個ItemDecoration,可根據不一樣需求選擇

⑦、採用ObservableList做爲數據源,無需手動notify

⑧、支持findViewById,ViewBinding,DataBinding三種模式,可根據你現有項目模式或喜愛隨意更換!

⑨、動畫的高可配置(綜合考慮後採用recyclerView的itemAnimator方案,若有須要請自行依賴mikepenz大神的ItemAnimators庫)

⑩、吸頂(採用sticky-layoutmanager的方案,低耦合adapter和item,因爲原庫的position獲取有一些bug,便將其集成到本項目中並修復了bug)

二、依賴,最新版本請看github或者jitpack

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
複製代碼
dependencies {
    implementation 'com.github.q876625596:YasuoRecyclerViewAdapter:x.y.z'
}
複製代碼

二、示例展現

若是想直接Ctrl CV代碼,快速上手的同窗,請直接移步sample

吸頂.gif

加載更多.gif

空佈局,header,footer.gif

摺疊.gif

拖拽,側滑刪除.gif

三、詳細介紹

1)數據源

必須使用YasuoList或其子類做爲數據源,YasuoList繼承自ObservableArrayList,新增了部分經常使用方法,並在adapter內部作了監聽處理,所以使用該類型數據源能夠不用手動notify

2)簡單寫法(單佈局/多佈局/header/footer)
fun findViewByIdMode(){
        //數據源
        val list = YasuoList<Any>()
        val headerList = YasuoList<Any>()
        val footerList = YasuoList<Any>()
        binding.myRV.layoutManager = GridLayoutManager(this, 3)
        //findViewById模式
        binding.myRV.adapterBinding(this,list){
            //do something
            //綁定文本佈局
            //只須要給對應的佈局配置holderConfig,便可實現多佈局,header,footer
            holderConfig(R.layout.item_layout_text, TextBean::class) {
                onHolderBind { holder, item ->
                    holder.getView<TextView>(R.id.itemText).apply {
                        text = item.text.value
                    }
                }
            }
        }
        //ViewBinding模式
        binding.myRV.adapterViewBinding(this,list){
            //do something
            //配置文本佈局
            //只須要給對應的佈局配置holderConfig,便可實現多佈局,header,footer
            holderConfig(R.layout.item_layout_text, TextBean::class, { ItemLayoutTextBinding.bind(it) }) {
                onHolderBind { holder, item ->
                    itemText.text = item.text.value
                }
            }
        }
        //DataBinding模式
        binding.myRV.adapterDataBinding(this,list){
            //do something
            //配置文本佈局
            //只須要給對應的佈局配置holderConfig,便可實現多佈局,header,footer
            holderConfig(R.layout.item_layout_text_data_binding, TextBean::class, ItemLayoutTextDataBindingBinding::class) {
                onHolderBind { holder ->
                    //dataBInding模式已在xml中綁定了數據,無需手動設置
                }
            }
        }
    }
複製代碼

以上三種模式的差別就只有這麼一點,相互切換也至關的方便。

3)空佈局

空佈局的使用也很是簡單,先將空佈局的holderConfig配置以後,再調用adapter.showEmptyLayout就好了。

binding.myRV.adapterViewBinding(this,list){
            //do something
            holderConfig(R.layout.item_layout_text, TextBean::class, { ItemLayoutTextBinding.bind(it) }) {
                onHolderBind { holder, item ->
                    itemText.text = item.text.value
                    itemText.setOnClickListener {
                        showEmptyLayout(/*空佈局實體*/EmptyBeanTwo(), /*是否清空header*/true, /*是否清空footer*/true)
                    }
                }
            }
        }
複製代碼
4)對佈局設置佔比

設置佔比有兩種方式,第一種,給一種類型的佈局設置佔比:

binding.myRV.adapterViewBinding(this,list){
            //do something
            holderConfig(R.layout.item_layout_text, TextBean::class, { ItemLayoutTextBinding.bind(it) }) {
                //do something
                //給某個itemViewType的佈局統一設置
                //瀑布流佔滿一行
                staggeredGridFullSpan = true
                //網格佈局佔比
                gridSpan = 3
            }
        }
複製代碼

第二種,針對某個item單獨設置佔比:

list.add(ImageBean(MutableLiveData(ContextCompat.getDrawable(this@MainActivity, R.drawable.eee))).apply {
                    //給某個item單獨設置
                    //瀑布流佔滿一行
                    staggeredGridFullSpan = true
                    //網格佈局佔比
                    gridSpan = 3
        }
複製代碼

判斷優先級:單個item設置 > 類型設置

5)加載更多

加載更多和空佈局相似,也是先將加載更多佈局的holderConfig配置以後,再調用adapter.showLoadMoreLayout使空佈局顯示出來,最後添加adapter.onLoadMoreListener監聽便可。

binding.myRV.adapterViewBinding(this,list){
            //展現加載更多
            showLoadMoreLayout(DefaultLoadMoreItem())
            //設置加載更多的監聽
            onLoadMoreListener(binding.myRV) {
                //請求數據...
            }
            //do something
        }
複製代碼
6)拖拽/側滑刪除

只須要使用adapter.enableDragOrSwipe便可啓用拖拽,同時也能夠設置監聽,設置手勢方向,以及對某些特定佈局禁用等

binding.myRV.adapterViewBinding(this,list){
            //拖拽/側滑刪除
            enableDragOrSwipe(binding.myRV, isLongPressDragEnable = true, isItemViewSwipeEnable = true)
            //do something
        }
複製代碼
7)吸頂

首先設置layoutManager:StickyLinearLayoutManagerStickyGridLayoutManagerStickyStaggeredGridLayoutManager 吸頂有兩種方式,第一種,對某一個類型的佈局設置吸頂

binding.myRV.adapterViewBinding(this,list){
            //do something
            holderConfig(R.layout.item_layout_text, TextBean::class, { ItemLayoutTextBinding.bind(it) }) {
                //給某個itemViewType的佈局統一設置
                //吸頂,注意,吸頂會默認佔滿一行
                sticky = true
                //do something
            }
        }
複製代碼

第二種,針對某個item設置吸頂

list.add(ImageBean(MutableLiveData(ContextCompat.getDrawable(this@MainActivity, R.drawable.eee))).apply {
        //給某個item單獨設置
        //吸頂,注意,吸頂會默認佔滿一行
        sticky = true
}
複製代碼

判斷優先級:單個item設置 > 類型設置

8)摺疊佈局

摺疊佈局須要數據類繼承YasuoFoldItem,以後只須要使用adapter.expandOrFoldItem來展開/收起便可,支持多級摺疊,若是須要刪除或添加摺疊佈局中的某個item,建議使用adapter.removeAndFoldListItemadapter.addAndFoldListItem方法

9)動畫配置

動畫採用mikepenz大神的ItemAnimators庫,若有須要,請先自行依賴該庫。

binding.myRV.itemAnimator = SlideLeftAlphaAnimator()
複製代碼
10)附送的itemDecoration

支持爲每條邊單獨設置樣式

binding.myRV.addYasuoDecoration {
            setDecoration(R.layout.item_layout_text, this@MainActivity, defaultRes)
            setDecoration(R.layout.item_layout_image, this@MainActivity, defaultRes)
        }
複製代碼

額外附一個span相等的網格佈局專用空白分隔ItemDecoration

binding.myRV.addItemDecoration(GridSpacingItemDecoration(3, 20, true))
複製代碼

四、api展現

1)adapter可配置屬性/方法一覽
屬性名/方法名 介紹 默認值
itemList 主體列表 YasuoList()
headerList 頭部列表 YasuoList()
footerList 尾部列表 YasuoList()
showLoadMoreLayout(loadMoreItem: T) 配置並顯示加載更多佈局 ------
removeLoadMore() 移除加載更多佈局 ------
enableLoadMoreListener() 啓用列表滾動到底部時加載更多的監聽 ------
disableLoadMoreListener() 禁用列表滾動到底部時加載更多的監聽 ------
isShowEmptyLayout() 判斷當前是不是顯示空佈局狀態 ------
showEmptyLayout(emptyItem: T, clearHeader: Boolean = false, clearFooter: Boolean = false) 判斷當前是不是顯示空佈局狀態 ------
expandOrFoldItem(item: YasuoFoldItem) 展開/摺疊某個item ------
removeAndFoldListItem(childItem: Any, foldList: YasuoList? = null) 移除一個item的同時移除其摺疊列表的相同item ------
getAllListSize() 獲取所有列表的長度 ------
getItemListTrueSize() 獲取[itemList]的實際長度 ------
getHeaderListTrueSize() 獲取[headerList]的實際長度 ------
getFooterListTrueSize() 獲取[footerList]的實際長度 ------
getHeaderTruePosition(position: Int) 獲取[headerList]的真實position ------
getItemTruePosition(position: Int) 獲取[itemList]的真實position ------
getFooterTruePosition(position: Int) 獲取[footerList]的真實position ------
inHeaderList(position: Int) 判斷position在[headerList]內 ------
inItemList(position: Int) 判斷position在[itemList]內 ------
inFooterList(position: Int) 判斷position在[footerList]內 ------
setAfterDataChangeListener(listener: () -> Unit) 列表數據發生改變後的監聽,在notify以後觸發 ------
enableDragOrSwipe(...) 設置item是否可拖拽、滑動刪除 ------
onLoadMoreListener(...) 設置加載更多的監聽 ------
holderConfig(...) 配置holder,創建數據類與佈局文件之間的匹配關係 ------
2)holderConfig可配置屬性/方法一覽
屬性名/方法名 介紹 默認值
sticky 該類型佈局是否吸頂 false
isFold 該類型佈局是否支持展開摺疊 false
gridSpan 該類型佈局在grid中的佔比 0
staggeredGridFullSpan 該類型佈局在staggeredGrid中是否佔滿 false
holderCreateListener 該類型Holder建立時的監聽 null
holderBindListener 該類型的Holder綁定時的監聽 null
createBindingFun ViewBinding的建立方法,僅ViewBinding模式 null
variableId xml中對應的數據id,僅DataBinding模式 BR.item
3)YasuoNormalItem可配置屬性/方法一覽
屬性名/方法名 介紹 默認值
sticky 該item是否吸頂 false
gridSpan 該item在grid中的佔比 0
staggeredGridFullSpan 該item在staggeredGrid中是否佔滿 false
4)YasuoNormalItem可配置屬性/方法一覽
屬性名/方法名 介紹 默認值
list 下一級列表 YasuoList()
isExpand 是否已展開 false
parentHash 父級hash,展開後纔會賦值 false
sticky 該item是否吸頂 false
gridSpan 該item在grid中的佔比 0
staggeredGridFullSpan 該item在staggeredGrid中是否佔滿 false

3、結語

首先感謝你們的閱讀,立刻就要過年了,在這裏也祝你們新年快樂,但願這個庫可以對大家有所幫助。若是你喜歡**YasuoRecyclerViewAdapter**這個庫,但願能在github上給一個star,做爲我進步的動力! 若是他有不足或須要新增的功能,能夠向我提issue或添加個人qq:876625596

相關文章
相關標籤/搜索