自從我開始作安卓開發以來,我就得了一種病,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-adapter和Yasha。程序員
這兩個都是優秀的庫,曾經我也在項目中使用過他們,可是漸漸地我發現他們已經沒法知足個人一些需求了,我便開始嘗試寫一個本身用的庫。當時這個庫仍是存在於個人私有項目中,我在項目中遇到的問題就能夠及時改,直到19年的上半年爲止,這個庫基本能夠用於大多很多天常開發,當時我就考慮將它進行一些完善工做後開源,可是世事難料,因爲工做緣由,19年的7月,我去了一趟柬埔寨,沒錯,就是程序員們口誅筆伐的東南亞國家之一。github
去那邊以後,由於人手問題,我不得不學習了vue開發,flutter開發,以及後端開發,幾乎沒有時間來搞這個庫的開源工做。時間到了20年的9月,因爲工做安排,又回到了重慶,又通過幾個月的忙碌後,終於在最近抽出了一些時間,來繼續進行做業。後端
當我從新審視這個庫的時候,我發現了不少能夠優化的點,這表明我這一年可能是在進步,我很高興,而後花了兩三週的空餘時間將其優化完善,新增一些功能後,我決定在今天將它發佈出來,但願你們可以喜歡。api
很差意思,前言有點囉嗦,但依舊不妨礙後續的精彩。markdown
簡單介紹一下這個庫:YasuoRecyclerViewAdapter ,爲何要取名爲Yasuo,由於亞索==快樂!這個庫就是爲了讓你們在寫代碼的時候感覺到快樂而存在的!app
①、List,Grid,StaggeredGrid類型的正常佈局及多佈局
②、空白頁/頭部/尾部
③、加載更多
④、摺疊佈局(支持多級摺疊)
⑤、拖拽、橫向滑動刪除
⑥、附送兩個ItemDecoration,可根據不一樣需求選擇
⑦、採用ObservableList做爲數據源,無需手動notify
⑧、支持findViewById,ViewBinding,DataBinding三種模式,可根據你現有項目模式或喜愛隨意更換!
⑨、動畫的高可配置(綜合考慮後採用recyclerView的itemAnimator方案,若有須要請自行依賴mikepenz大神的ItemAnimators庫)
⑩、吸頂(採用sticky-layoutmanager的方案,低耦合adapter和item,因爲原庫的position獲取有一些bug,便將其集成到本項目中並修復了bug)
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
複製代碼
dependencies {
implementation 'com.github.q876625596:YasuoRecyclerViewAdapter:x.y.z'
}
複製代碼
若是想直接Ctrl CV代碼,快速上手的同窗,請直接移步sample
必須使用YasuoList或其子類做爲數據源,YasuoList繼承自ObservableArrayList,新增了部分經常使用方法,並在adapter內部作了監聽處理,所以使用該類型數據源能夠不用手動notify
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中綁定了數據,無需手動設置
}
}
}
}
複製代碼
以上三種模式的差別就只有這麼一點,相互切換也至關的方便。
空佈局的使用也很是簡單,先將空佈局的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)
}
}
}
}
複製代碼
設置佔比有兩種方式,第一種,給一種類型的佈局設置佔比:
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設置 > 類型設置
加載更多和空佈局相似,也是先將加載更多佈局的holderConfig配置以後,再調用adapter.showLoadMoreLayout使空佈局顯示出來,最後添加adapter.onLoadMoreListener監聽便可。
binding.myRV.adapterViewBinding(this,list){
//展現加載更多
showLoadMoreLayout(DefaultLoadMoreItem())
//設置加載更多的監聽
onLoadMoreListener(binding.myRV) {
//請求數據...
}
//do something
}
複製代碼
只須要使用adapter.enableDragOrSwipe便可啓用拖拽,同時也能夠設置監聽,設置手勢方向,以及對某些特定佈局禁用等
binding.myRV.adapterViewBinding(this,list){
//拖拽/側滑刪除
enableDragOrSwipe(binding.myRV, isLongPressDragEnable = true, isItemViewSwipeEnable = true)
//do something
}
複製代碼
首先設置layoutManager:StickyLinearLayoutManager,StickyGridLayoutManager,StickyStaggeredGridLayoutManager 吸頂有兩種方式,第一種,對某一個類型的佈局設置吸頂
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設置 > 類型設置
摺疊佈局須要數據類繼承YasuoFoldItem,以後只須要使用adapter.expandOrFoldItem來展開/收起便可,支持多級摺疊,若是須要刪除或添加摺疊佈局中的某個item,建議使用adapter.removeAndFoldListItem和adapter.addAndFoldListItem方法
動畫採用mikepenz大神的ItemAnimators庫,若有須要,請先自行依賴該庫。
binding.myRV.itemAnimator = SlideLeftAlphaAnimator()
複製代碼
支持爲每條邊單獨設置樣式
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))
複製代碼
屬性名/方法名 | 介紹 | 默認值 |
---|---|---|
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,創建數據類與佈局文件之間的匹配關係 | ------ |
屬性名/方法名 | 介紹 | 默認值 |
---|---|---|
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 |
屬性名/方法名 | 介紹 | 默認值 |
---|---|---|
sticky | 該item是否吸頂 | false |
gridSpan | 該item在grid中的佔比 | 0 |
staggeredGridFullSpan | 該item在staggeredGrid中是否佔滿 | false |
屬性名/方法名 | 介紹 | 默認值 |
---|---|---|
list | 下一級列表 | YasuoList() |
isExpand | 是否已展開 | false |
parentHash | 父級hash,展開後纔會賦值 | false |
sticky | 該item是否吸頂 | false |
gridSpan | 該item在grid中的佔比 | 0 |
staggeredGridFullSpan | 該item在staggeredGrid中是否佔滿 | false |
首先感謝你們的閱讀,立刻就要過年了,在這裏也祝你們新年快樂,但願這個庫可以對大家有所幫助。若是你喜歡**YasuoRecyclerViewAdapter**這個庫,但願能在github上給一個star,做爲我進步的動力! 若是他有不足或須要新增的功能,能夠向我提issue或添加個人qq:876625596