Skip to content

Commit

Permalink
Add ViewDelegate that does not require ViewHolder (#296)
Browse files Browse the repository at this point in the history
This PR adds a new & simple `ItemViewDelegate` called `ViewDelegate` that does not require to declare and provide a `RecyclerView.ViewHolder`.

* Add ViewDelegate that does not require ViewHolder

* [sample] Add RichView & RichViewDelegate

* Add a small guide about the data binding

* Remove the square_border for RichView
  • Loading branch information
drakeet authored Dec 24, 2019
1 parent 9670a5d commit 3324c0c
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 93 deletions.
56 changes: 56 additions & 0 deletions library/src/main/kotlin/com/drakeet/multitype/ViewDelegate.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.drakeet.multitype


import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView

/**
* This is a simple [ItemViewDelegate] that does not require to declare and provide a [RecyclerView.ViewHolder].
* @since v4.2.0
* @author Drakeet Xu
*/
abstract class ViewDelegate<T, V : View> : ItemViewDelegate<T, ViewDelegate.Holder<V>>() {

abstract fun onCreateView(context: Context): V

abstract fun onBindView(view: V, item: T)

// Override this function if you need a parent ViewGroup
open fun onCreateView(context: Context, parent: ViewGroup): V {
return onCreateView(context)
}

// Override this function if you need a ViewHolder
open fun onBindView(holder: Holder<V>, view: V, item: T) {
onBindView(view, item)
}

override fun onCreateViewHolder(context: Context, parent: ViewGroup): Holder<V> {
return Holder(onCreateView(context, parent))
}

override fun onBindViewHolder(holder: Holder<V>, item: T) = onBindView(holder, holder.view, item)

class Holder<V : View>(val view: V) : RecyclerView.ViewHolder(view)

/**
* Warning: this property can only get the correct value in an item root view.
* @see RecyclerView.LayoutParams.getViewLayoutPosition
*/
protected val View.layoutPosition get() = recyclerLayoutParams.viewLayoutPosition

/**
* Warning: this property can only get the correct value in an item root view.
* @see RecyclerView.LayoutParams.getViewAdapterPosition
*/
protected val View.adapterPosition get() = recyclerLayoutParams.viewAdapterPosition

/**
* RecyclerView will automatically convert any original type of LayoutParam into [RecyclerView.LayoutParams],
* so for the item root view, its final LayoutParam must be [RecyclerView.LayoutParams].
* @see RecyclerView.LayoutManager.generateLayoutParams
*/
private val View.recyclerLayoutParams get() = layoutParams as RecyclerView.LayoutParams
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.drakeet.multitype.sample

import android.content.res.Resources

/**
* @author Drakeet Xu
*/
val Number.dp: Int get() = (toInt() * Resources.getSystem().displayMetrics.density).toInt()
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ class NormalActivity : MenuBaseActivity() {

adapter.register(TextItemViewBinder())
adapter.register(ImageItemViewBinder())
adapter.register(RichItemViewBinder())
// ✨✨✨
adapter.register(RichViewDelegate())
recyclerView.adapter = adapter

val textItem = TextItem("world")
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.drakeet.multitype.sample.normal

import android.content.Context
import android.graphics.Color
import android.view.Gravity
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.LinearLayout
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import com.drakeet.multitype.sample.R
import com.drakeet.multitype.sample.dp

/**
* @author Drakeet Xu
*/
class RichView(context: Context) : LinearLayout(context) {

val imageView = AppCompatImageView(context).apply {
addView(this, LayoutParams(72.dp, 72.dp))
}

val textView = AppCompatTextView(context).apply {
setTextColor(Color.BLACK)
addView(this, LayoutParams(WRAP_CONTENT, WRAP_CONTENT))
}

init {
orientation = VERTICAL
gravity = Gravity.CENTER
setPadding(16.dp, 16.dp, 16.dp, 16.dp)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2016-present. Drakeet Xu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.drakeet.multitype.sample.normal

import android.content.Context
import android.view.Gravity
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.LayoutParams
import com.drakeet.multitype.ViewDelegate
import com.drakeet.multitype.sample.dp

/**
* @author Drakeet Xu
*/
class RichViewDelegate : ViewDelegate<RichItem, RichView>() {

override fun onCreateView(context: Context): RichView {
return RichView(context).apply { layoutParams = LayoutParams(MATCH_PARENT, WRAP_CONTENT) }
}

override fun onBindView(view: RichView, item: RichItem) {
view.imageView.setImageResource(item.imageResId)
view.textView.text = item.text
// Or bind the data in the RichView by calling view.setRichItem(item)
}
}
46 changes: 0 additions & 46 deletions sample/src/main/res/layout/item_rich.xml

This file was deleted.

0 comments on commit 3324c0c

Please sign in to comment.