diff options
Diffstat (limited to 'fastadapter-viewbinding')
-rw-r--r-- | fastadapter-viewbinding/.gitignore | 1 | ||||
-rw-r--r-- | fastadapter-viewbinding/build.gradle | 21 | ||||
-rw-r--r-- | fastadapter-viewbinding/consumer-rules.pro | 0 | ||||
-rw-r--r-- | fastadapter-viewbinding/proguard-rules.pro | 21 | ||||
-rw-r--r-- | fastadapter-viewbinding/src/main/AndroidManifest.xml | 1 | ||||
-rw-r--r-- | fastadapter-viewbinding/src/main/kotlin/ca/allanwang/fastadapter/viewbinding/BindingItem.kt | 156 | ||||
-rw-r--r-- | fastadapter-viewbinding/src/main/res/values/ids.xml | 5 |
7 files changed, 205 insertions, 0 deletions
diff --git a/fastadapter-viewbinding/.gitignore b/fastadapter-viewbinding/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/fastadapter-viewbinding/.gitignore @@ -0,0 +1 @@ +/build diff --git a/fastadapter-viewbinding/build.gradle b/fastadapter-viewbinding/build.gradle new file mode 100644 index 0000000..a786edb --- /dev/null +++ b/fastadapter-viewbinding/build.gradle @@ -0,0 +1,21 @@ +import kau.Dependencies +import kau.Versions + +ext.kauSubModuleMinSdk = Versions.coreMinSdk + +apply from: '../android-lib.gradle' + +android { + viewBinding { + enabled = true + } +} + +dependencies { + implementation project(':core') + + api Dependencies.fastAdapter + api Dependencies.fastAdapter("utils") +} + +apply from: '../artifacts.gradle' diff --git a/fastadapter-viewbinding/consumer-rules.pro b/fastadapter-viewbinding/consumer-rules.pro new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/fastadapter-viewbinding/consumer-rules.pro diff --git a/fastadapter-viewbinding/proguard-rules.pro b/fastadapter-viewbinding/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/fastadapter-viewbinding/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/fastadapter-viewbinding/src/main/AndroidManifest.xml b/fastadapter-viewbinding/src/main/AndroidManifest.xml new file mode 100644 index 0000000..3c1cd7f --- /dev/null +++ b/fastadapter-viewbinding/src/main/AndroidManifest.xml @@ -0,0 +1 @@ +<manifest package="ca.allanwang.kau.fastadapter.viewbinding" /> diff --git a/fastadapter-viewbinding/src/main/kotlin/ca/allanwang/fastadapter/viewbinding/BindingItem.kt b/fastadapter-viewbinding/src/main/kotlin/ca/allanwang/fastadapter/viewbinding/BindingItem.kt new file mode 100644 index 0000000..543a9ef --- /dev/null +++ b/fastadapter-viewbinding/src/main/kotlin/ca/allanwang/fastadapter/viewbinding/BindingItem.kt @@ -0,0 +1,156 @@ +/* + * Copyright 2019 Allan Wang + * + * 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 ca.allanwang.fastadapter.viewbinding + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import androidx.viewbinding.ViewBinding +import ca.allanwang.kau.fastadapter.viewbinding.R +import ca.allanwang.kau.logging.KL +import com.mikepenz.fastadapter.FastAdapter +import com.mikepenz.fastadapter.GenericItem +import com.mikepenz.fastadapter.items.AbstractItem +import com.mikepenz.fastadapter.listeners.ClickEventHook + +interface VhModel { + fun vh(): GenericItem +} + +/** + * Layout container. Should be implemented in a [BindingItem] companion. + */ +interface BindingLayout<Binding : ViewBinding> { + val layoutRes: Int +} + +abstract class BindingItem<Binding : ViewBinding>(open val data: Any?) : + AbstractItem<BindingItem.ViewHolder>(), + BindingLayout<Binding> { + + override val type: Int + get() = layoutRes + + abstract fun createBinding(layoutInflater: LayoutInflater, parent: ViewGroup?): Binding + + override fun createView(ctx: Context, parent: ViewGroup?): View { + val binding = createBinding(LayoutInflater.from(ctx), parent) + setBinding(binding.root, binding) + return binding.root + } + + final override fun bindView(holder: ViewHolder, payloads: MutableList<Any>) { + super.bindView(holder, payloads) + val binding = holder.getBinding<Binding>() + binding.bindView(holder, payloads) + } + + abstract fun Binding.bindView(holder: ViewHolder, payloads: MutableList<Any>) + + protected fun unbind(vararg textViews: TextView) { + textViews.forEach { it.text = null } + } + + protected fun unbind(vararg imageViews: ImageView) { + imageViews.forEach { it.setImageDrawable(null) } + } + + final override fun unbindView(holder: ViewHolder) { + super.unbindView(holder) + val binding = holder.getBinding<Binding>() + binding.unbindView(holder) + } + + open fun Binding.unbindView(holder: ViewHolder) {} + + final override fun getViewHolder(v: View): ViewHolder = + ViewHolder(v, layoutRes) + + override fun failedToRecycle(holder: ViewHolder): Boolean { + KL.e { "Failed to recycle" } + return super.failedToRecycle(holder) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is BindingItem<*>) return false + return identifier == other.identifier && data == other.data + } + + override fun hashCode(): Int = data.hashCode() + + class ViewHolder(itemView: View, internal val layoutRes: Int) : + RecyclerView.ViewHolder(itemView) { + + /** + * Retrieves a binding. + * + * It is assumed that the binding is set prior to this call, + * and that its type matches the supplied generic. + */ + fun <T> getBinding(): T = getBinding(itemView) + } + + companion object { + fun setBinding(view: View, binding: Any) { + view.setTag(R.id.kau_view_binding_model, binding) + } + + @Suppress("UNCHECKED_CAST") + fun <T> getBinding(view: View): T = view.getTag(R.id.kau_view_binding_model) as T + } +} + +abstract class BindingClickEventHook<Binding : ViewBinding, Item : BindingItem<Binding>>(val identifier: BindingLayout<Binding>) : + ClickEventHook<Item>() { + + private fun RecyclerView.ViewHolder.binding(): Binding? { + val holder = this as? BindingItem.ViewHolder ?: return null + if (holder.layoutRes != identifier.layoutRes) { + return null + } + return getBinding() + } + + final override fun onBind(viewHolder: RecyclerView.ViewHolder): View? { + val binding = viewHolder.binding() ?: return super.onBind(viewHolder) + val view = binding.onBind(viewHolder) ?: return super.onBind(viewHolder) + BindingItem.setBinding(view, binding) + return view + } + + open fun Binding.onBind(viewHolder: RecyclerView.ViewHolder): View? = super.onBind(viewHolder) + + final override fun onBindMany(viewHolder: RecyclerView.ViewHolder): List<View>? { + val binding = viewHolder.binding() ?: return super.onBindMany(viewHolder) + val views = binding.onBindMany(viewHolder) ?: return super.onBindMany(viewHolder) + views.forEach { BindingItem.setBinding(it, binding) } + return views + } + + open fun Binding.onBindMany(viewHolder: RecyclerView.ViewHolder): List<View>? = + super.onBindMany(viewHolder) + + final override fun onClick(v: View, position: Int, fastAdapter: FastAdapter<Item>, item: Item) { + BindingItem.getBinding<Binding>(v).onClick(v, position, fastAdapter, item) + } + + abstract fun Binding.onClick(v: View, position: Int, fastAdapter: FastAdapter<Item>, item: Item) +}
\ No newline at end of file diff --git a/fastadapter-viewbinding/src/main/res/values/ids.xml b/fastadapter-viewbinding/src/main/res/values/ids.xml new file mode 100644 index 0000000..550ae02 --- /dev/null +++ b/fastadapter-viewbinding/src/main/res/values/ids.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <item name="kau_view_binding_model" type="id" /> + <item name="kau_view_binding_root" type="id" /> +</resources>
\ No newline at end of file |