Kotlin - RecycleView.Adapter結(jié)合DataBinding封裝

自帶頭部,底部投蝉,和空布局的recycleView.Adapter基類封裝相關說明:

1.適用于多種類型的條目類型(目前支持頭部养葵,底部,和空布局瘩缆,其他條目布局需要自己擴展)
2.支持空頁面展示和自定義空布局
3.支持頭部和底部的添加和自定義頭部和底部布局

下面對關鍵代碼進行分析:

重寫getItemViewType(position: Int) 方法关拒,根據(jù)不同的條目返回對應的布局類型在這里我定義了四種布局類型:默認條目類型,頭部庸娱,底部着绊,和空布局

override fun getItemViewType(position: Int) : Int {
    var head = 0
    if (isHeader) ++head
    if (isFooter) ++head
    if (isHeader && data.isNotEmpty() && position == 0) return headerType                   //數(shù)據(jù)為空時 頭部不顯示 若要頭部顯示,去除空判斷
    if (isFooter && data.isNotEmpty() && data.size+head == position+1) return footerType    //數(shù)據(jù)為空時 尾部不顯示 若要尾部顯示熟尉,去除空判斷
    if (isShowEmptyView && data.isEmpty()) return emptyViewType
    return super.getItemViewType(position)
}

重寫 getItemCount()方法归露,計算出需要的 item 數(shù)量,這里我在這里我通過判斷data數(shù)據(jù)源的數(shù)據(jù)來判斷當數(shù)據(jù)為空時不顯示頭部和底部臣樱,有需要顯示的可以修改這部分代碼

override fun getItemCount(): Int {
    var size = 0
    if (isHeader && data.isNotEmpty()) ++size   //數(shù)據(jù)為空時 頭部不顯示 若要頭部顯示靶擦,去除空判斷
    if (isFooter && data.isNotEmpty()) ++size   //數(shù)據(jù)為空時 尾部不顯示 若要尾部顯示,去除空判斷
    val len = data.size
    if (isShowEmptyView && len == 0) return 1
    return len+size
}

重寫onCreateViewHolder(parent: ViewGroup, viewType: Int)雇毫, 根據(jù)viewType來判斷創(chuàng)建不同的ViewHolder類型玄捕,這里頭部,底部和空頁面都通過了方法返回的方式來創(chuàng)建View,目的是為了方便自定義布局的使用(注意:頭部和底部要放到空頁面的前面判斷棚放,后面會有說明

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    return when(viewType) {
        headerType -> headerViewCreate(parent)
        footerType -> footViewCreate(parent)
        emptyViewType -> emptyViewCreate(parent)
        else -> ViewHolder<D>(DataBindingUtil.inflate<ViewDataBinding>(
            LayoutInflater.from(parent.context),
            layoutResId(),
            parent,
            false).root)
    }
}
    /**
     * 更換頭部部布局重寫此方法 其他方法類似
     */
    open fun headerViewCreate(parent:ViewGroup):ViewHolderHeader<ViewHeadBinding>{
    return ViewHolderHeader(DataBindingUtil.inflate<ViewHeadBinding>(
        LayoutInflater.from(parent.context),
        R.layout.view_head,
        parent,
        false).root)
}

重寫onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) 方法枚粘,在該方法中判斷布局類型,onBindView 是通用默認的類型飘蚯,onBindViews適用于頭部馍迄,底部和空頁面布局,大家可以根據(jù)自己的需要去改局骤。當然如果有頭部布局顯示攀圈,不要忘記position要減去1。頭部峦甩,底部的viewHolder 要在空布局的viewHolder之前判斷赘来,下面我會貼出原因:

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    when (holder) {
        is ViewHolder<*> -> {
            val i = if (isHeader) position-1 else position
            onBindView(holder.binding as D, data[i], i)
            checkClickListener(holder.binding as D, i)
            holder.binding.executePendingBindings()
        }
        is ViewHolderHeader<*> -> {
            onBindViews(holder.binding)
            holder.binding.executePendingBindings()
        }
        is ViewHolderFooter<*> -> {
            onBindViews(holder.binding)
            holder.binding.executePendingBindings()
        }
        is ViewHolderEmpty<*> -> {
            onBindViews(holder.binding)
            holder.binding.executePendingBindings()
        }
    }
}
    //原因
    open class ViewHolderEmpty<E :ViewDataBinding>(@NonNull itemView: View):  RecyclerView.ViewHolder(itemView){
        var binding : E = DataBindingUtil.getBinding(this.itemView)!!
    }
    class ViewHolderHeader<E : ViewDataBinding>(@NonNull itemView: View): ViewHolderEmpty<E>(itemView)
    class ViewHolderFooter<E : ViewDataBinding>(@NonNull itemView: View): ViewHolderEmpty<E>(itemView)

最后附上完整的代碼现喳,希望對大家有幫助,如果有不足的地方歡迎大家指正犬辰,謝謝嗦篱。

abstract class BaseRecycleViewAdapter<T,D : ViewDataBinding>(protected val data:MutableList<T>):RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val emptyViewType   = 1 //空頁面
private val headerType      = 2
private val footerType      = 3
private var isUseDefaultListener = true
private var isShowEmptyView      = true
private var isHeader = false
private var isFooter = false

private var onItemClickListener:OnItemClickListener ?= null

constructor(data:MutableList<T>, isUseDefaultListener:Boolean):this(data) {
    this.isUseDefaultListener = isUseDefaultListener
}

constructor(data: MutableList<T>,isUseDefaultListener: Boolean,isShowEmptyView:Boolean, isHeader:Boolean,isFooter:Boolean):this(data,isUseDefaultListener) {
    this.isShowEmptyView = isShowEmptyView
    this.isHeader = isHeader
    this.isFooter = isFooter
}

fun addOnItemClickListener(onItemClickListener: OnItemClickListener) {
    this.onItemClickListener = onItemClickListener
}

@LayoutRes
abstract fun layoutResId(): Int

abstract fun onBindView(binding: D, item:T?, position: Int)

/**
 * 頭部,底部和空布局數(shù)據(jù)展示在此方法中
 * 空布局要放在頭部和底部后面
 */
open fun onBindViews(binding: ViewDataBinding) {}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    return when(viewType) {
        headerType -> headerViewCreate(parent)
        footerType -> footViewCreate(parent)
        emptyViewType -> emptyViewCreate(parent)
        else -> ViewHolder<D>(DataBindingUtil.inflate<ViewDataBinding>(
            LayoutInflater.from(parent.context),
            layoutResId(),
            parent,
            false).root)
    }
}

/**
 * 更換頭部布局重寫此方法
 */
open fun headerViewCreate(parent: ViewGroup):ViewHolderHeader<ViewHeadBinding>{
    return ViewHolderHeader(DataBindingUtil.inflate<ViewHeadBinding>(
        LayoutInflater.from(parent.context),
        R.layout.view_head,
        parent,
        false).root)
}

/**
 * 更換底部布局重寫此方法
 */
open fun footViewCreate(parent: ViewGroup):ViewHolderFooter<ViewFootBinding>{
    return ViewHolderFooter(DataBindingUtil.inflate<ViewFootBinding>(
        LayoutInflater.from(parent.context),
        R.layout.view_foot,
        parent,
        false).root)
}

/**
 * 更換空布局重寫此方法
 */
open fun emptyViewCreate(parent: ViewGroup):ViewHolderEmpty<ViewEmptyBinding>{
    return ViewHolderEmpty(DataBindingUtil.inflate<ViewEmptyBinding>(
        LayoutInflater.from(parent.context),
        R.layout.view_empty,
        parent,
        false).root)
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    when (holder) {
        is ViewHolder<*> -> {
            val i = if (isHeader) position-1 else position
            onBindView(holder.binding as D, data[i], i)
            checkClickListener(holder.binding as D, i)
            holder.binding.executePendingBindings()
        }
        is ViewHolderHeader<*> -> {
            onBindViews(holder.binding)
            holder.binding.executePendingBindings()
        }
        is ViewHolderFooter<*> -> {
            onBindViews(holder.binding)
            holder.binding.executePendingBindings()
        }
        is ViewHolderEmpty<*> -> {
            onBindViews(holder.binding)
            holder.binding.executePendingBindings()
        }
    }
}

/**
 * 默認添加item點擊事件
 */
open fun checkClickListener(binding: D,position: Int) {
    if (isUseDefaultListener && null != onItemClickListener) {
        binding.root.setOnClickListener {
            onItemClickListener!!.onItemClickListener(binding.root,position)
        }
    }
}


/**
 * 返回條目數(shù)量
 */
override fun getItemCount(): Int {
    var size = 0
    if (isHeader && data.isNotEmpty()) ++size   //數(shù)據(jù)為空時 頭部不顯示 若要頭部顯示幌缝,去除空判斷
    if (isFooter && data.isNotEmpty()) ++size   //數(shù)據(jù)為空時 尾部不顯示 若要尾部顯示灸促,去除空判斷
    val len = data.size
    if (isShowEmptyView && len == 0) return 1
    return len+size
}

/**
 * 返回item類型
 * 添加新的類型重寫此方法
 */
override fun getItemViewType(position: Int): Int {
    var head = 0
    if (isHeader) ++head
    if (isFooter) ++head
    if (isHeader && data.isNotEmpty() && position == 0) return headerType                   //數(shù)據(jù)為空時 頭部不顯示 若要頭部顯示,去除空判斷
    if (isFooter && data.isNotEmpty() && data.size+head == position+1) return footerType    //數(shù)據(jù)為空時 尾部不顯示 若要尾部顯示涵卵,去除空判斷
    if (isShowEmptyView && data.isEmpty()) return emptyViewType
    return super.getItemViewType(position)
}


open class ViewHolder<D :ViewDataBinding>(@NonNull itemView: View): RecyclerView.ViewHolder(itemView) {
    var binding : D = DataBindingUtil.getBinding(this.itemView)!!
}

open class ViewHolderEmpty<E :ViewDataBinding>(@NonNull itemView: View):  RecyclerView.ViewHolder(itemView){
    var binding : E = DataBindingUtil.getBinding(this.itemView)!!
}
class ViewHolderHeader<E : ViewDataBinding>(@NonNull itemView: View): ViewHolderEmpty<E>(itemView)
class ViewHolderFooter<E : ViewDataBinding>(@NonNull itemView: View): ViewHolderEmpty<E>(itemView)
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末浴栽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子缘厢,更是在濱河造成了極大的恐慌吃度,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贴硫,死亡現(xiàn)場離奇詭異椿每,居然都是意外死亡,警方通過查閱死者的電腦和手機英遭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門间护,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人挖诸,你說我怎么就攤上這事汁尺《嗦桑” “怎么了痴突?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辽装。 經(jīng)常有香客問我,道長相味,這世上最難降的妖魔是什么丰涉? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任拓巧,我火速辦了婚禮肛度,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘投慈。我一直安慰自己承耿,他們只是感情好策吠,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著瘩绒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪带族。 梳的紋絲不亂的頭發(fā)上锁荔,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音蝙砌,去河邊找鬼阳堕。 笑死,一個胖子當著我的面吹牛择克,可吹牛的內(nèi)容都是我干的恬总。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼肚邢,長吁一口氣:“原來是場噩夢啊……” “哼壹堰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起骡湖,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤贱纠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后响蕴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谆焊,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年浦夷,在試婚紗的時候發(fā)現(xiàn)自己被綠了辖试。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡劈狐,死狀恐怖罐孝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情懈息,我是刑警寧澤肾档,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站辫继,受9級特大地震影響怒见,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜姑宽,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一遣耍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧炮车,春花似錦舵变、人聲如沸酣溃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赊豌。三九已至,卻和暖如春绵咱,著一層夾襖步出監(jiān)牢的瞬間碘饼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工悲伶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留艾恼,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓麸锉,卻偏偏與公主長得像钠绍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子花沉,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

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