From 2c30a38232e56ba2620fe4ade2fc55faaf61dc44 Mon Sep 17 00:00:00 2001 From: drake Date: Fri, 5 Jun 2020 01:38:39 +0800 Subject: [PATCH] =?UTF-8?q?+=20=E5=BC=BA=E5=A4=A7=E7=9A=84=E5=88=86?= =?UTF-8?q?=E5=89=B2=E7=BA=BF=E5=8A=9F=E8=83=BD=20+=20=E5=88=86=E7=BB=84?= =?UTF-8?q?=E5=B1=95=E5=BC=80=E6=97=B6=E9=9A=90=E8=97=8F=E5=88=86=E5=89=B2?= =?UTF-8?q?=E7=BA=BF=20+=20ItemBind=E6=94=AF=E6=8C=81=E5=88=86=E7=A6=BB?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=E9=80=BB=E8=BE=91=20+=20=E5=90=84=E7=A7=8DIt?= =?UTF-8?q?em=E6=8E=A5=E5=8F=A3=E6=89=A9=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 +- .../main/java/com/drake/brv/BindingAdapter.kt | 56 +- .../java/com/drake/brv/DefaultDecoration.kt | 667 +++++++++++++++--- .../com/drake/brv/annotaion/AnimationType.kt | 25 +- .../com/drake/brv/annotaion/Orientation.kt | 5 + .../main/java/com/drake/brv/item/ItemBind.kt | 18 + .../java/com/drake/brv/item/ItemChecked.kt | 12 - .../brv/listener/OnItemOffsetsListener.kt | 17 - .../java/com/drake/brv/utils/RecyclerUtils.kt | 150 ++-- build.gradle | 4 +- gradle/wrapper/gradle-wrapper.properties | 4 +- .../com/drake/brv/sample/mod/GroupModel.kt | 14 - .../drake/brv/sample/mod/NestedGroupModel.kt | 12 - .../brv/sample/{mod => model}/CheckModel.kt | 2 +- .../sample/{mod => model}/DoubleItemModel.kt | 2 +- .../brv/sample/{mod => model}/FlexTagModel.kt | 2 +- .../com/drake/brv/sample/model/GroupModel.kt | 25 + .../sample/{mod => model}/HoverHeaderModel.kt | 2 +- .../drake/brv/sample/{mod => model}/Model.kt | 2 +- .../brv/sample/model/NestedGroupModel.kt | 18 + .../sample/{mod => model}/OneMoreTypeModel.kt | 2 +- .../drake/brv/sample/model/StaggeredModel.kt | 5 + .../sample/{mod => model}/SwipeDragModel.kt | 2 +- .../brv/sample/ui/activity/MainActivity.kt | 2 +- .../sample/ui/fragment/CheckModeFragment.kt | 2 +- .../brv/sample/ui/fragment/DividerFragment.kt | 79 +++ .../brv/sample/ui/fragment/FlexBoxFragment.kt | 2 +- .../brv/sample/ui/fragment/GroupFragment.kt | 21 +- .../ui/fragment/HeaderFooterFragment.kt | 6 +- .../sample/ui/fragment/HoverHeaderFragment.kt | 4 +- .../sample/ui/fragment/MultiTypeFragment.kt | 4 +- .../sample/ui/fragment/OneMoreTypeFragment.kt | 2 +- .../brv/sample/ui/fragment/RefreshFragment.kt | 7 +- .../sample/ui/fragment/StateLayoutFragment.kt | 8 +- .../sample/ui/fragment/SwipeDragFragment.kt | 2 +- .../brv/sample/vm/RenderBindComponnent.kt | 10 + .../main/res/drawable/divider_horizontal.xml | 14 +- .../res/drawable/divider_horizontal_dash.xml | 18 + .../main/res/drawable/divider_vertical.xml | 5 + .../src/main/res/layout/fragment_divider.xml | 20 + .../src/main/res/layout/item_check_mode.xml | 2 +- .../main/res/layout/item_expand_loading.xml | 12 + smaple/src/main/res/layout/item_flex_tag.xml | 2 +- smaple/src/main/res/layout/item_grid.xml | 20 + .../src/main/res/layout/item_group_title.xml | 4 +- .../res/layout/item_nested_group_title.xml | 4 +- smaple/src/main/res/layout/item_staggered.xml | 35 + .../main/res/layout/item_swipe_or_drag.xml | 2 +- smaple/src/main/res/menu/menu_divider.xml | 8 + smaple/src/main/res/menu/menu_main.xml | 8 +- smaple/src/main/res/navigation/nav_main.xml | 13 +- smaple/src/main/res/values/colors.xml | 1 + 52 files changed, 1043 insertions(+), 343 deletions(-) create mode 100644 brv/src/main/java/com/drake/brv/annotaion/Orientation.kt create mode 100644 brv/src/main/java/com/drake/brv/item/ItemBind.kt delete mode 100644 brv/src/main/java/com/drake/brv/item/ItemChecked.kt delete mode 100755 brv/src/main/java/com/drake/brv/listener/OnItemOffsetsListener.kt delete mode 100644 smaple/src/main/java/com/drake/brv/sample/mod/GroupModel.kt delete mode 100644 smaple/src/main/java/com/drake/brv/sample/mod/NestedGroupModel.kt rename smaple/src/main/java/com/drake/brv/sample/{mod => model}/CheckModel.kt (89%) rename smaple/src/main/java/com/drake/brv/sample/{mod => model}/DoubleItemModel.kt (81%) rename smaple/src/main/java/com/drake/brv/sample/{mod => model}/FlexTagModel.kt (51%) create mode 100644 smaple/src/main/java/com/drake/brv/sample/model/GroupModel.kt rename smaple/src/main/java/com/drake/brv/sample/{mod => model}/HoverHeaderModel.kt (88%) rename smaple/src/main/java/com/drake/brv/sample/{mod => model}/Model.kt (80%) create mode 100644 smaple/src/main/java/com/drake/brv/sample/model/NestedGroupModel.kt rename smaple/src/main/java/com/drake/brv/sample/{mod => model}/OneMoreTypeModel.kt (83%) create mode 100644 smaple/src/main/java/com/drake/brv/sample/model/StaggeredModel.kt rename smaple/src/main/java/com/drake/brv/sample/{mod => model}/SwipeDragModel.kt (95%) create mode 100644 smaple/src/main/java/com/drake/brv/sample/ui/fragment/DividerFragment.kt create mode 100644 smaple/src/main/java/com/drake/brv/sample/vm/RenderBindComponnent.kt create mode 100644 smaple/src/main/res/drawable/divider_horizontal_dash.xml create mode 100644 smaple/src/main/res/drawable/divider_vertical.xml create mode 100644 smaple/src/main/res/layout/fragment_divider.xml create mode 100644 smaple/src/main/res/layout/item_expand_loading.xml create mode 100644 smaple/src/main/res/layout/item_grid.xml create mode 100644 smaple/src/main/res/layout/item_staggered.xml create mode 100644 smaple/src/main/res/menu/menu_divider.xml diff --git a/README.md b/README.md index ba8fc89f8..370e6d134 100755 --- a/README.md +++ b/README.md @@ -5,11 +5,10 @@ ### 特性 -- 使用Databinding构建MVVM -- 完美拥有Kotlin的特性 -- 通用适配器 -- 方便实现常见需求 -- 代码量最少, 逻辑更清晰 +- 全网最少的代码 +- Kotlin的特性 +- 通用适配器, 无需继承 +- 快速实现常见需求 - 刷新还是添加数据都无闪屏 @@ -28,6 +27,13 @@ - 过滤重复点击 +- 分组 + + - 展开折叠 + - 顶部附着 + +- 支持所有的`LayoutManager`的分割线/均布间隔 + - 切换模式 - 选择模式 @@ -39,7 +45,7 @@ - 侧滑删除 -- 下拉刷新 | 上拉加载 (PageRefreshLayout|SmartRefreshLayout) +- 下拉刷新 | 上拉加载 (PageRefreshLayout) - 多状态缺省页 (PageRefreshLayout) @@ -57,9 +63,6 @@ 未来将支持: - 无限滚动 -- 分组 - - 展开折叠 - - 顶部附着 ## 安装 @@ -79,7 +82,7 @@ allprojects { module 的 build.gradle ```groovy -implementation 'com.github.liangjingkanji:BRV:1.2.11' +implementation 'com.github.liangjingkanji:BRV:1.2.13' ``` diff --git a/brv/src/main/java/com/drake/brv/BindingAdapter.kt b/brv/src/main/java/com/drake/brv/BindingAdapter.kt index 69c76de3a..99daea2da 100755 --- a/brv/src/main/java/com/drake/brv/BindingAdapter.kt +++ b/brv/src/main/java/com/drake/brv/BindingAdapter.kt @@ -22,6 +22,7 @@ import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView import com.drake.brv.animation.* import com.drake.brv.annotaion.AnimationType +import com.drake.brv.item.ItemBind import com.drake.brv.item.ItemExpand import com.drake.brv.item.ItemHover import com.drake.brv.item.ItemPosition @@ -45,9 +46,6 @@ import com.drake.brv.listener.throttleClick * 强大的选择状态 [setChecked] (切换模式/多选/单选/全选/取消全选/反选/选中数据集/选中数量/单选和多选模式切换) * 遵守高内聚低耦合原则, 支持功能配合使用, 代码简洁函数分组 * - * TODO - * [] 无限划动 - * [] 拖动多选 */ @Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate") @@ -103,7 +101,7 @@ class BindingAdapter : RecyclerView.Adapter() override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingViewHolder { val viewDataBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), viewType, parent, false) - ?: return BindingViewHolder(parent.getView(viewType)) + ?: return BindingViewHolder(parent.getView(viewType)) return BindingViewHolder(viewDataBinding) } @@ -130,7 +128,7 @@ class BindingAdapter : RecyclerView.Adapter() val model = getModel(position) val modelClass: Class<*> = model.javaClass return (typePool[modelClass]?.invoke(model, position) - ?: throw NoSuchPropertyException("Please add item model type : ${model.javaClass.simpleName}")) + ?: throw NoSuchPropertyException("Please add item model type : ${model.javaClass.simpleName}")) } override fun getItemCount() = headerCount + modelCount + footerCount @@ -268,7 +266,7 @@ class BindingAdapter : RecyclerView.Adapter() /** * 设置当前库自带的条目的动画样式 */ - fun setAnimation(@AnimationType animationType: Int) { + fun setAnimation(animationType: AnimationType) { this.animationEnabled = true when (animationType) { AnimationType.ALPHA -> this.itemAnimation = AlphaItemAnimation() @@ -336,7 +334,7 @@ class BindingAdapter : RecyclerView.Adapter() fun isHeader(@IntRange(from = 0) position: Int): Boolean = - (headerCount > 0 && position < headerCount) + (headerCount > 0 && position < headerCount) // @@ -426,7 +424,7 @@ class BindingAdapter : RecyclerView.Adapter() fun isFooter(@IntRange(from = 0) position: Int): Boolean = - (footerCount > 0 && position >= headerCount + modelCount && position < itemCount) + (footerCount > 0 && position >= headerCount + modelCount && position < itemCount) // @@ -484,7 +482,8 @@ class BindingAdapter : RecyclerView.Adapter() return result } - fun isModel(@IntRange(from = 0) position: Int): Boolean = !(isHeader(position) || isFooter(position)) + fun isModel(@IntRange(from = 0) position: Int): Boolean = + !(isHeader(position) || isFooter(position)) /** * 根据索引返回数据模型, 如果不存在该模型则返回Null @@ -719,9 +718,15 @@ class BindingAdapter : RecyclerView.Adapter() // + private var onExpand: (BindingViewHolder.(Boolean) -> Unit)? = null + // 分组展开和折叠是否启用动画 var expandAnimationEnabled: Boolean = true + fun onExpand(block: BindingViewHolder.(Boolean) -> Unit) { + this.onExpand = block + } + /** * 展开 * @param position 指定position的条目折叠 @@ -765,7 +770,7 @@ class BindingAdapter : RecyclerView.Adapter() lateinit var data: Any val adapter: BindingAdapter = this@BindingAdapter - val modelPosition get() = adapterPosition - headerCount + val modelPosition get() = layoutPosition - headerCount constructor(itemView: View) : super(itemView) @@ -797,15 +802,20 @@ class BindingAdapter : RecyclerView.Adapter() internal fun bind(model: Any) { this.data = model + if (model is ItemPosition) { + model.itemPosition = layoutPosition + } + + if (model is ItemBind) { + model.onBind(this) + return + } + onBind?.apply { val isReturn = onBind!!.invoke(this@BindingViewHolder) if (isReturn) return } - if (model is ItemPosition) { - model.itemPosition = layoutPosition - } - viewDataBinding?.setVariable(modelId, model) viewDataBinding?.executePendingBindings() } @@ -837,19 +847,21 @@ class BindingAdapter : RecyclerView.Adapter() fun expand(scrollTop: Boolean = true, @IntRange(from = -1) depth: Int = 0): Int { val itemExpand = getModelOrNull() + onExpand?.invoke(this, true) + return if (itemExpand != null && !itemExpand.itemExpand) { val sublist = itemExpand.itemSublist itemExpand.itemExpand = true if (sublist.isNullOrEmpty()) { - notifyItemChanged(adapterPosition) + notifyItemChanged(layoutPosition) 0 } else { val sublistFlat = flat(sublist, true, depth) ?: return 0 - this@BindingAdapter.data?.addAll(adapterPosition + 1, sublistFlat) + this@BindingAdapter.data?.addAll(layoutPosition + 1, sublistFlat) if (expandAnimationEnabled) { - notifyItemChanged(adapterPosition) - notifyItemRangeInserted(adapterPosition + 1, sublistFlat.size) + notifyItemChanged(layoutPosition) + notifyItemRangeInserted(layoutPosition + 1, sublistFlat.size) } else { notifyDataSetChanged() } @@ -871,19 +883,21 @@ class BindingAdapter : RecyclerView.Adapter() fun collapse(@IntRange(from = -1) depth: Int = 0): Int { val itemExpand = getModelOrNull() + onExpand?.invoke(this, false) + return if (itemExpand != null && itemExpand.itemExpand) { val sublist = itemExpand.itemSublist itemExpand.itemExpand = false if (sublist.isNullOrEmpty()) { - notifyItemChanged(adapterPosition, itemExpand) + notifyItemChanged(layoutPosition, itemExpand) 0 } else { val sublistFlat = flat(sublist, false, depth) ?: return 0 this@BindingAdapter.data?.removeAll(sublistFlat) if (expandAnimationEnabled) { - notifyItemChanged(adapterPosition, itemExpand) - notifyItemRangeRemoved(adapterPosition + 1, sublistFlat.size) + notifyItemChanged(layoutPosition, itemExpand) + notifyItemRangeRemoved(layoutPosition + 1, sublistFlat.size) } else { notifyDataSetChanged() } diff --git a/brv/src/main/java/com/drake/brv/DefaultDecoration.kt b/brv/src/main/java/com/drake/brv/DefaultDecoration.kt index 7eb50dd22..3eba1b0fe 100755 --- a/brv/src/main/java/com/drake/brv/DefaultDecoration.kt +++ b/brv/src/main/java/com/drake/brv/DefaultDecoration.kt @@ -9,196 +9,637 @@ package com.drake.brv import android.content.Context import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint import android.graphics.Rect +import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable import android.util.Log import android.view.View -import android.widget.LinearLayout +import androidx.annotation.ColorInt +import androidx.annotation.ColorRes import androidx.annotation.DrawableRes +import androidx.annotation.LayoutRes +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.StaggeredGridLayoutManager +import com.drake.brv.annotaion.Orientation +import com.drake.brv.item.ItemExpand +import kotlin.math.ceil +import kotlin.math.roundToInt /** - * 用于创建分隔物的帮助类 - * - 自定义图片分隔物 - * - 自定义颜色分隔物 - */ -class DefaultDecoration -/** - * Creates a divider [RecyclerView.ItemDecoration] that can be used with a - * [LinearLayoutManager]. + * 最强大的分割线工具 * - * @param context Current context, it will be used to access resources. - * @param orientation Divider orientation. Should be [.HORIZONTAL] or [.VERTICAL]. + * 完全功能需要配合[BindingAdapter]使用 + * 1. 分隔图片 + * 2. 分隔颜色 + * 3. 分隔间距 + * 4. 回调函数判断间隔 + * 5. 首尾是否显示分隔线, 可以展示表格效果 + * 6. 类型池来指定是否显示分割线 + * 7. 支持全部的LayoutManager, 竖向/横向/网格分割线 + * 8. 优于其他框架, 完美支持均布网格分隔物 + * 9. 支持分组条目的分割线 */ -constructor(private val context: Context, @RecyclerView.Orientation orientation: Int = RecyclerView.VERTICAL) : - RecyclerView.ItemDecoration() { - private val mBounds = Rect() - var divider: Drawable? = null - private set +class DefaultDecoration constructor(private val context: Context) : RecyclerView.ItemDecoration() { + /** - * Current orientation. Either [.HORIZONTAL] or [.VERTICAL]. + * 第一个条目之前是否显示分割线, 当处于[Orientation.GRID] 时水平方向顶端和末端是否显示分割线 */ - private var mOrientation: Int = 0 - var onItemOffsets: ((Rect, View, RecyclerView, RecyclerView.State) -> Boolean)? = null + var startVisible = false - init { - val a = context.obtainStyledAttributes(ATTRS) - divider = a.getDrawable(0) - if (divider == null) { - Log.w( - TAG, - "@android:attr/listDivider was not set in the theme used for this " + "DividerItemDecoration. Please set that attribute all call setDrawable()" - ) - } - a.recycle() - setOrientation(orientation) + /** + * 最后一个条目是否显示分割线, 当处于[Orientation.GRID] 时垂直方向顶端和末端是否显示分割线 + */ + var endVisible = false + + /** + * 展开分组条目后该条目是否显示分割线 + */ + var expandVisible = false + + /** + * 当使用[LinearLayoutManager]或[StaggeredGridLayoutManager]时该属性无需设置 + * [LinearLayoutManager]仅根据[LinearLayoutManager.getOrientation]来自动指定分割线方向 + * [StaggeredGridLayoutManager]仅可使用网格[Orientation.GRID]分割线 + */ + var orientation = Orientation.HORIZONTAL + + private var size = 1 + private var marginStart = 0 + private var marginEnd = 0 + private var divider: Drawable? = null + + // + + /** + * 集合内包含的类型才显示分割线 + */ + var typePool: MutableList? = null + + private var onEnabled: (BindingAdapter.BindingViewHolder.() -> Boolean)? = null + + /** + * 根据[BindingAdapter.BindingViewHolder]来判断是否启用分割线 + */ + fun onEnabled(enabled: BindingAdapter.BindingViewHolder.() -> Boolean) { + this.onEnabled = enabled } /** - * Sets the orientation for this divider. This should be called if - * [RecyclerView.LayoutManager] changes orientation. - * - * @param orientation [.HORIZONTAL] or [.VERTICAL] + * 添加类型后只允许该类型的条目显示分割线 + * 从未添加类型则默认为允许全部条目显示分割线 */ - fun setOrientation(orientation: Int) { - if (orientation != HORIZONTAL && orientation != VERTICAL) { - throw IllegalArgumentException( - "Invalid orientation. It should be either HORIZONTAL or VERTICAL" - ) + fun addType(@LayoutRes vararg typeArray: Int) { + if (typePool == null) { + typePool = mutableListOf() + onEnabled = { + typePool?.contains(itemViewType) ?: true + } } - mOrientation = orientation + typeArray.forEach { typePool?.add(it) } } + + // + + // /** - * Sets the [Drawable] for this divider. - * - * @param drawable Drawable that should be used as a divider. + * 设置图片 */ - fun setDrawable(drawable: Drawable?) { - drawable?.let { throw IllegalArgumentException("Drawable cannot be null.") } + fun setDrawable(drawable: Drawable) { divider = drawable } /** * 自定义分隔物 - * - * @param drawableRes 分隔物 */ fun setDrawable(@DrawableRes drawableRes: Int) { - val drawable = - context.resources.getDrawable(drawableRes) - ?: throw IllegalArgumentException("Drawable cannot be null.") + val drawable = ContextCompat.getDrawable(context, drawableRes) + ?: throw IllegalArgumentException("Drawable cannot be find") divider = drawable } + // + + // + /** + * 设置颜色 + */ + fun setColor(@ColorInt color: Int) { + divider = ColorDrawable(color) + } + + /** + * 设置十六进制的颜色值 + */ + fun setColor(color: String) { + val parseColor = Color.parseColor(color) + divider = ColorDrawable(parseColor) + } + + /** + * 设置颜色资源文件 + */ + fun setColorRes(@ColorRes color: Int) { + val colorRes = ContextCompat.getColor(context, color) + divider = ColorDrawable(colorRes) + } + + private var background = Color.TRANSPARENT + + /** + * 分割线背景色 + * 分割线有时候会存在间距或属于虚线, 可以设置背景色解决不统一的问题, 默认为透明[Color.TRANSPARENT] + */ + fun setBackground(@ColorInt color: Int) { + background = color + } - fun onItemOffsets(onItemOffsets: (Rect, View, RecyclerView, RecyclerView.State) -> Boolean) { - this.onItemOffsets = onItemOffsets + fun setBackground(colorString: String) { + try { + background = Color.parseColor(colorString) + } catch (e: Exception) { + throw IllegalArgumentException("Unknown color: $colorString") + } } - override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { - if (parent.layoutManager == null || divider == null) { - return + fun setBackgroundRes(@ColorRes color: Int) { + background = ContextCompat.getColor(context, color) + } + + // + + // + + /** + * 设置分割线宽度 + * 如果使用[setDrawable]则无效 + */ + fun setWith(height: Int = 1, pixel: Boolean = false) { + if (pixel) { + this.size = height + } else { + val density = context.resources.displayMetrics.density + this.size = (density * height).roundToInt() } - if (mOrientation == VERTICAL) { - drawVertical(c, parent) + } + + /** + * 设置分隔左右或上下间距, 依据分割线为垂直或者水平决定具体方向间距 + * 未设置分割线颜色[setColor]或者图片[setDrawable]同样有效 + */ + fun setMargin(start: Int = 0, end: Int = 0, pixel: Boolean = false) { + if (pixel) { + this.marginStart = start + this.marginEnd = end } else { - drawHorizontal(c, parent) + val density = context.resources.displayMetrics.density + this.marginStart = (start * density).roundToInt() + this.marginEnd = (end * density).roundToInt() } } + // + + + override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { + + val layoutManager = parent.layoutManager ?: return + + onEnabled?.let { + val vh = parent.findContainingViewHolder(view) as BindingAdapter.BindingViewHolder + val modelOrNull = vh.getModelOrNull() + if (!expandVisible && modelOrNull != null && modelOrNull is ItemExpand && modelOrNull.itemExpand) return + if (!it.invoke(vh)) return + } + + val position = parent.getChildAdapterPosition(view) + + val height = when { + divider == null -> size + divider?.intrinsicHeight != -1 -> divider!!.intrinsicHeight + divider?.intrinsicWidth != -1 -> divider!!.intrinsicWidth + else -> size + } + + val width = when { + divider == null -> size + divider?.intrinsicWidth != -1 -> divider!!.intrinsicWidth + divider?.intrinsicHeight != -1 -> divider!!.intrinsicHeight + else -> size + } + + val edge = computeEdge(position, layoutManager) + adjustOrientation(layoutManager) + + when (orientation) { + Orientation.HORIZONTAL -> { + val top = if (startVisible && edge.top) height else 0 + val bottom = if ((endVisible && edge.bottom) || !edge.bottom) height else 0 + outRect.set(0, top, 0, bottom) + } + Orientation.VERTICAL -> { + val left = if (startVisible && edge.left) width else 0 + val right = if ((endVisible && edge.right) || !edge.right) width else 0 + outRect.set(left, 0, right, 0) + } + Orientation.GRID -> { + + val spanCount = when (layoutManager) { + is GridLayoutManager -> layoutManager.spanCount + is StaggeredGridLayoutManager -> layoutManager.spanCount + else -> 1 + } + + val spanGroupCount = when (layoutManager) { + is GridLayoutManager -> layoutManager.spanSizeLookup.getSpanGroupIndex(state.itemCount - 1, spanCount) + 1 + is StaggeredGridLayoutManager -> ceil(state.itemCount / spanCount.toFloat()).toInt() + else -> 1 + } + + val spanIndex = when (layoutManager) { + is GridLayoutManager -> layoutManager.spanSizeLookup.getSpanIndex(position, spanCount) + is StaggeredGridLayoutManager -> (layoutManager.findViewByPosition(position)!!.layoutParams as StaggeredGridLayoutManager.LayoutParams).spanIndex + else -> 0 + } - override fun getItemOffsets( - outRect: Rect, - view: View, - parent: RecyclerView, - state: RecyclerView.State - ) { - onItemOffsets?.let { - val isReturn = onItemOffsets!!.invoke(outRect, view, parent, state) - if (isReturn) { - return + val spanGroupIndex = when (layoutManager) { + is GridLayoutManager -> layoutManager.spanSizeLookup.getSpanGroupIndex(position, spanCount) + is StaggeredGridLayoutManager -> ceil((position + 1) / spanCount.toFloat()).toInt() - 1 + else -> 0 + } + + val spanSize = when (layoutManager) { + is GridLayoutManager -> layoutManager.spanSizeLookup.getSpanSize(position) + else -> 1 + } + + val orientation = when (layoutManager) { + is GridLayoutManager -> layoutManager.orientation + is StaggeredGridLayoutManager -> layoutManager.orientation + else -> RecyclerView.VERTICAL + } + + val left = when { + endVisible && orientation == RecyclerView.VERTICAL -> width - spanIndex * width / spanCount + startVisible && orientation == RecyclerView.HORIZONTAL -> width - spanIndex * width / spanCount + else -> spanIndex * width / spanCount + } + + val right = when { + endVisible && orientation == RecyclerView.VERTICAL -> (spanIndex + spanSize) * width / spanCount + startVisible && orientation == RecyclerView.HORIZONTAL -> (spanIndex + spanSize) * width / spanCount + else -> width - (spanIndex + spanSize) * width / spanCount + } + + val top = when { + startVisible && orientation == RecyclerView.VERTICAL -> height - spanGroupIndex * height / spanGroupCount + endVisible && orientation == RecyclerView.HORIZONTAL -> height - spanGroupIndex * height / spanGroupCount + else -> spanGroupIndex * height / spanGroupCount + } + + val bottom = when { + startVisible && orientation == RecyclerView.VERTICAL -> (spanGroupIndex + 1) * height / spanGroupCount + endVisible && orientation == RecyclerView.HORIZONTAL -> (spanGroupIndex + 1) * height / spanGroupCount + else -> height - (spanGroupIndex + 1) * height / spanGroupCount + } + + if (orientation == RecyclerView.VERTICAL) { + outRect.set(left, top, right, bottom) + } else outRect.set(top, left, bottom, right) } } + } + + override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) { + val layoutManager = parent.layoutManager + if (layoutManager == null || divider == null) return + + adjustOrientation(layoutManager) - if (divider == null || parent.getChildLayoutPosition(view) == state.itemCount - 1) { - return + when (orientation) { + Orientation.HORIZONTAL -> drawHorizontal(canvas, parent) + Orientation.VERTICAL -> drawVertical(canvas, parent) + Orientation.GRID -> drawGrid(canvas, parent) } + } - if (mOrientation == VERTICAL) { - outRect.set(0, 0, 0, divider!!.intrinsicHeight) - } else { - outRect.set(0, 0, divider!!.intrinsicWidth, 0) + /** + * 自动调整不同布局管理器应该对应的[orientation] + */ + private fun adjustOrientation(layoutManager: RecyclerView.LayoutManager) { + if (layoutManager !is GridLayoutManager && layoutManager is LinearLayoutManager) { + orientation = if ((layoutManager as? LinearLayoutManager)?.orientation == RecyclerView.VERTICAL) Orientation.HORIZONTAL else Orientation.VERTICAL + } else if (layoutManager is StaggeredGridLayoutManager) { + orientation = Orientation.GRID } } - private fun drawVertical(canvas: Canvas, parent: RecyclerView) { + /** + * 绘制水平分割线 + */ + private fun drawHorizontal(canvas: Canvas, parent: RecyclerView) { canvas.save() val left: Int val right: Int if (parent.clipToPadding) { - left = parent.paddingLeft - right = parent.width - parent.paddingRight - canvas.clipRect( - left, - parent.paddingTop, - right, - parent.height - parent.paddingBottom - ) + left = parent.paddingLeft + this.marginStart + right = parent.width - parent.paddingRight - marginEnd } else { - left = 0 - right = parent.width + left = 0 + this.marginStart + right = parent.width - marginEnd } - val childCount = parent.childCount - for (i in 0 until childCount) { + loop@ for (i in 0 until parent.childCount) { val child = parent.getChildAt(i) - parent.getDecoratedBoundsWithMargins(child, mBounds) - val bottom = mBounds.bottom + Math.round(child.translationY) - val top = bottom - divider!!.intrinsicHeight - divider!!.setBounds(left, top, right, bottom) - divider!!.draw(canvas) + + if (onEnabled != null) { + val vh = parent.getChildViewHolder(child) as BindingAdapter.BindingViewHolder + val modelOrNull = vh.getModelOrNull() + if (!expandVisible && modelOrNull != null && modelOrNull is ItemExpand && modelOrNull.itemExpand) continue@loop + val enabled = onEnabled?.invoke(vh) ?: true + if (!enabled) continue@loop + } + + Log.d("日志", "(DefaultDecoration.kt:372) ") + + val position = parent.getChildAdapterPosition(child) + val layoutManager = parent.layoutManager ?: return + val edge = computeEdge(position, layoutManager) + + if (orientation != Orientation.GRID && !endVisible && edge.bottom) { + continue@loop + } + + divider?.apply { + val decoratedBounds = Rect() + parent.getDecoratedBoundsWithMargins(child, decoratedBounds) + + val firstBottom = if (intrinsicHeight == -1) decoratedBounds.top + size else decoratedBounds.top + intrinsicHeight + val firstTop = decoratedBounds.top + + val bottom = decoratedBounds.bottom + val top = if (intrinsicHeight == -1) bottom - size else bottom - intrinsicHeight + + if (background != Color.TRANSPARENT) { + val paint = Paint() + paint.color = background + paint.style = Paint.Style.FILL + + if (startVisible && edge.top) { + val firstRect = Rect(parent.paddingLeft, firstTop, parent.width - parent.paddingRight, firstBottom) + canvas.drawRect(firstRect, paint) + } + + val rect = Rect(parent.paddingLeft, top, parent.width - parent.paddingRight, bottom) + canvas.drawRect(rect, paint) + } + + if (startVisible && edge.top) { + setBounds(left, firstTop, right, firstBottom) + draw(canvas) + } + + setBounds(left, top, right, bottom) + draw(canvas) + } } canvas.restore() } - private fun drawHorizontal(canvas: Canvas, parent: RecyclerView) { + /** + * 绘制垂直分割线 + */ + private fun drawVertical(canvas: Canvas, parent: RecyclerView) { canvas.save() val top: Int val bottom: Int if (parent.clipToPadding) { - top = parent.paddingTop - bottom = parent.height - parent.paddingBottom - canvas.clipRect( - parent.paddingLeft, - top, - parent.width - parent.paddingRight, - bottom - ) + top = parent.paddingTop + marginStart + bottom = parent.height - parent.paddingBottom - marginEnd } else { - top = 0 - bottom = parent.height + top = 0 + marginStart + bottom = parent.height - marginEnd } val childCount = parent.childCount - for (i in 0 until childCount) { + + loop@ for (i in 0 until childCount) { val child = parent.getChildAt(i) - parent.layoutManager!!.getDecoratedBoundsWithMargins(child, mBounds) - val right = mBounds.right + Math.round(child.translationX) - val left = right - divider!!.intrinsicWidth - divider!!.setBounds(left, top, right, bottom) - divider!!.draw(canvas) + + if (onEnabled != null) { + val vh = parent.getChildViewHolder(child) as BindingAdapter.BindingViewHolder + val modelOrNull = vh.getModelOrNull() + if (!expandVisible && modelOrNull != null && modelOrNull is ItemExpand && modelOrNull.itemExpand) continue@loop + val enabled = onEnabled?.invoke(vh) ?: true + if (!enabled) continue@loop + } + + val position = parent.getChildAdapterPosition(child) + val layoutManager = parent.layoutManager ?: return + + val edge = computeEdge(position, layoutManager) + + if (orientation != Orientation.GRID && !endVisible && edge.right) { + continue@loop + } + + divider?.apply { + val decoratedBounds = Rect() + parent.getDecoratedBoundsWithMargins(child, decoratedBounds) + + val firstRight = if (intrinsicWidth == -1) decoratedBounds.left + size else decoratedBounds.left + intrinsicWidth + val firstLeft = decoratedBounds.left + + val right = (decoratedBounds.right + child.translationX).roundToInt() + val left = if (intrinsicWidth == -1) right - size else right - intrinsicWidth + + if (background != Color.TRANSPARENT) { + val paint = Paint() + paint.color = background + paint.style = Paint.Style.FILL + + if (startVisible && edge.left) { + val firstRect = Rect(firstLeft, parent.paddingTop, firstRight, parent.height - parent.paddingBottom) + canvas.drawRect(firstRect, paint) + } + + val rect = Rect(left, parent.paddingTop, right, parent.height - parent.paddingBottom) + canvas.drawRect(rect, paint) + } + + if (startVisible && edge.left) { + setBounds(firstLeft, top, firstRight, bottom) + draw(canvas) + } + + setBounds(left, top, right, bottom) + draw(canvas) + } } + canvas.restore() } + /** + * 绘制网格分割线 + */ + private fun drawGrid(canvas: Canvas, parent: RecyclerView) { + canvas.save() + + val childCount = parent.childCount + + loop@ for (i in 0 until childCount) { + val child = parent.getChildAt(i) + + if (onEnabled != null) { + val vh = parent.getChildViewHolder(child) as BindingAdapter.BindingViewHolder + val modelOrNull = vh.getModelOrNull() + if (!expandVisible && modelOrNull != null && modelOrNull is ItemExpand && modelOrNull.itemExpand) continue@loop + val enabled = onEnabled?.invoke(vh) ?: true + if (!enabled) continue@loop + } + + val position = parent.getChildAdapterPosition(child) + val layoutManager = parent.layoutManager ?: return + val edge = computeEdge(position, layoutManager) + + val height = when { + divider == null -> size + divider?.intrinsicHeight != -1 -> divider!!.intrinsicHeight + divider?.intrinsicWidth != -1 -> divider!!.intrinsicWidth + else -> size + } + + val width = when { + divider == null -> size + divider?.intrinsicWidth != -1 -> divider!!.intrinsicWidth + divider?.intrinsicHeight != -1 -> divider!!.intrinsicHeight + else -> size + } + + divider?.apply { + val layoutParams = child.layoutParams as RecyclerView.LayoutParams + val bounds = Rect(child.left + layoutParams.leftMargin, child.top + layoutParams.topMargin, child.right + layoutParams.rightMargin, child.bottom + layoutParams.bottomMargin) + + + // top + if (!endVisible && edge.right) { + setBounds(bounds.left - width, bounds.top - height, bounds.right, bounds.top) + draw(canvas) + } else if (!endVisible && edge.left) { + setBounds(bounds.left, bounds.top - height, bounds.right + width, bounds.top) + draw(canvas) + } else if (!edge.top || (startVisible && edge.top)) { + setBounds(bounds.left - width, bounds.top - height, bounds.right + width, bounds.top) + draw(canvas) + } + + // bottom + if (!endVisible && edge.right) { + setBounds(bounds.left - width, bounds.bottom, bounds.right, bounds.bottom + height) + draw(canvas) + } else if (!endVisible && edge.left) { + setBounds(bounds.left, bounds.bottom, bounds.right + width, bounds.bottom + height) + draw(canvas) + } else if (!edge.bottom || (startVisible && edge.bottom)) { + setBounds(bounds.left - width, bounds.bottom, bounds.right + width, bounds.bottom + height) + draw(canvas) + } + + // left + if (!edge.left || (endVisible && edge.left)) { + setBounds(bounds.left - width, bounds.top, bounds.left, bounds.bottom) + draw(canvas) + } + + // right + if (!edge.right || (endVisible && edge.right)) { + setBounds(bounds.right, bounds.top, bounds.right + width, bounds.bottom) + draw(canvas) + } + } + } + + canvas.restore() + } + + /** + * 列表条目是否靠近边缘的结算结果 + */ + data class Edge( + var left: Boolean = false, + var top: Boolean = false, + var right: Boolean = false, + var bottom: Boolean = false + ) + companion object { - const val HORIZONTAL = LinearLayout.HORIZONTAL - const val VERTICAL = LinearLayout.VERTICAL + /** + * 计算指定条目的边缘位置 + */ + fun computeEdge(position: Int, layoutManager: RecyclerView.LayoutManager): Edge { + + val index = position + 1 + val itemCount = layoutManager.itemCount - private const val TAG = "DividerItem" - private val ATTRS = intArrayOf(android.R.attr.listDivider) + return Edge().apply { + when (layoutManager) { + is StaggeredGridLayoutManager -> { + val spanCount = layoutManager.spanCount + val spanIndex = (layoutManager.findViewByPosition(position)!!.layoutParams as StaggeredGridLayoutManager.LayoutParams).spanIndex + 1 + + if (layoutManager.orientation == RecyclerView.VERTICAL) { + left = spanIndex == 1 + right = spanIndex == spanCount + top = index <= spanCount + bottom = index > itemCount - spanCount + } else { + left = index <= spanCount + right = index > itemCount - spanCount + top = spanIndex == 1 + bottom = spanIndex == spanCount + } + } + is GridLayoutManager -> { + val spanSizeLookup = layoutManager.spanSizeLookup + val spanCount = layoutManager.spanCount + val spanGroupIndex = spanSizeLookup.getSpanGroupIndex(position, spanCount) + val spanIndex = spanSizeLookup.getSpanIndex(position, spanCount) + 1 + val spanSize = spanSizeLookup.getSpanSize(position) + + if (layoutManager.orientation == RecyclerView.VERTICAL) { + left = spanIndex == 1 + right = spanIndex + spanSize - 1 == spanCount || index == itemCount + top = index <= spanCount && spanGroupIndex == spanSizeLookup.getSpanGroupIndex(position - 1, spanCount) + bottom = index > itemCount - spanCount + } else { + left = spanGroupIndex == 0 + right = index > itemCount - spanCount + top = spanIndex == 1 + bottom = spanIndex + spanSize - 1 == spanCount + } + } + is LinearLayoutManager -> { + if (layoutManager.orientation == RecyclerView.VERTICAL) { + left = true + right = true + top = index == 1 + bottom = index == itemCount + } else { + left = index == 1 + right = index == itemCount + top = true + bottom = true + } + } + } + } + } } } diff --git a/brv/src/main/java/com/drake/brv/annotaion/AnimationType.kt b/brv/src/main/java/com/drake/brv/annotaion/AnimationType.kt index b5232cf05..3cb02ee30 100755 --- a/brv/src/main/java/com/drake/brv/annotaion/AnimationType.kt +++ b/brv/src/main/java/com/drake/brv/annotaion/AnimationType.kt @@ -7,27 +7,6 @@ package com.drake.brv.annotaion -import androidx.annotation.IntDef -import com.drake.brv.annotaion.AnimationType.Companion.ALPHA -import com.drake.brv.annotaion.AnimationType.Companion.SCALE -import com.drake.brv.annotaion.AnimationType.Companion.SLIDE_BOTTOM -import com.drake.brv.annotaion.AnimationType.Companion.SLIDE_LEFT -import com.drake.brv.annotaion.AnimationType.Companion.SLIDE_RIGHT - - -@IntDef(ALPHA, SCALE, SLIDE_BOTTOM, SLIDE_LEFT, SLIDE_RIGHT) -@Retention(AnnotationRetention.SOURCE) -annotation class AnimationType { - companion object { - - const val ALPHA = 0x00000001 - - const val SCALE = 0x00000002 - - const val SLIDE_BOTTOM = 0x00000003 - - const val SLIDE_LEFT = 0x00000004 - - const val SLIDE_RIGHT = 0x00000005 - } +enum class AnimationType { + ALPHA, SCALE, SLIDE_BOTTOM, SLIDE_LEFT, SLIDE_RIGHT } diff --git a/brv/src/main/java/com/drake/brv/annotaion/Orientation.kt b/brv/src/main/java/com/drake/brv/annotaion/Orientation.kt new file mode 100644 index 000000000..812676c7d --- /dev/null +++ b/brv/src/main/java/com/drake/brv/annotaion/Orientation.kt @@ -0,0 +1,5 @@ +package com.drake.brv.annotaion + +enum class Orientation { + VERTICAL, HORIZONTAL, GRID +} \ No newline at end of file diff --git a/brv/src/main/java/com/drake/brv/item/ItemBind.kt b/brv/src/main/java/com/drake/brv/item/ItemBind.kt new file mode 100644 index 000000000..4ce9308fd --- /dev/null +++ b/brv/src/main/java/com/drake/brv/item/ItemBind.kt @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2018, Umbrella CompanyLimited All rights reserved. + * Project:BRV + * Author:Drake + * Date:5/9/20 1:07 AM + */ + +package com.drake.brv.item + +import com.drake.brv.BindingAdapter + +/** + * 推荐使用DataBinding来进行数据绑定[com.drake.brv.BindingAdapter.modelId], 或者函数[com.drake.brv.BindingAdapter.onBind] + * 该接口进行UI操作不符合MVVM架构, 因为Model中不允许出现View引用 + */ +interface ItemBind { + fun onBind(vh: BindingAdapter.BindingViewHolder) +} \ No newline at end of file diff --git a/brv/src/main/java/com/drake/brv/item/ItemChecked.kt b/brv/src/main/java/com/drake/brv/item/ItemChecked.kt deleted file mode 100644 index 1e63800fa..000000000 --- a/brv/src/main/java/com/drake/brv/item/ItemChecked.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (C) 2018, Umbrella CompanyLimited All rights reserved. - * Project:BRV - * Author:Drake - * Date:5/5/20 9:12 PM - */ - -package com.drake.brv.item - -interface ItemChecked { - var itemChecked: Boolean -} \ No newline at end of file diff --git a/brv/src/main/java/com/drake/brv/listener/OnItemOffsetsListener.kt b/brv/src/main/java/com/drake/brv/listener/OnItemOffsetsListener.kt deleted file mode 100755 index 835f991cc..000000000 --- a/brv/src/main/java/com/drake/brv/listener/OnItemOffsetsListener.kt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2018, Umbrella CompanyLimited All rights reserved. - * Project:BRV - * Author:Drake - * Date:5/5/20 9:12 PM - */ - -package com.drake.brv.listener - -import android.graphics.Rect -import android.view.View -import androidx.recyclerview.widget.RecyclerView - -interface OnItemOffsetsListener { - - fun onItemOffset(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State): Boolean -} diff --git a/brv/src/main/java/com/drake/brv/utils/RecyclerUtils.kt b/brv/src/main/java/com/drake/brv/utils/RecyclerUtils.kt index da42d7a3f..332d407a0 100755 --- a/brv/src/main/java/com/drake/brv/utils/RecyclerUtils.kt +++ b/brv/src/main/java/com/drake/brv/utils/RecyclerUtils.kt @@ -8,13 +8,10 @@ package com.drake.brv.utils import android.app.Dialog -import android.graphics.Rect -import android.util.NoSuchPropertyException -import android.view.View -import android.view.View.NO_ID import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import androidx.annotation.ColorInt +import androidx.annotation.ColorRes import androidx.annotation.DrawableRes -import androidx.annotation.LayoutRes import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.VERTICAL @@ -25,10 +22,19 @@ import com.drake.brv.layoutmanager.HoverLinearLayoutManager import com.drake.brv.layoutmanager.HoverStaggeredGridLayoutManager +val RecyclerView.bindingAdapter + get() = adapter as BindingAdapter + +var RecyclerView.models + get() = bindingAdapter.models + set(value) { + bindingAdapter.models = value + } + + +// /** - * 详细设置适配器 - * @receiver RecyclerView - * @param block bindingAdapter.() -> Unit + * 设置适配器 */ fun RecyclerView.setup(block: BindingAdapter.(RecyclerView) -> Unit): BindingAdapter { val adapter = BindingAdapter() @@ -36,86 +42,113 @@ fun RecyclerView.setup(block: BindingAdapter.(RecyclerView) -> Unit): BindingAda this.adapter = adapter return adapter } +// -/** - * 快速创建多类型 - * itemLayout和block二者选一, 分别对应 单一类型/一对多数据类型, - * 普通多类型配置请使用 {@link RecyclerView.bindingAdapter(block: bindingAdapter.() -> Unit): bindingAdapter} - * - * @receiver RecyclerView - * @param itemLayout Int - * @param block (M.(Int) -> Int)? - * @return bindingAdapter - */ -inline fun RecyclerView.setup( - @LayoutRes itemLayout: Int = NO_ID, - noinline block: (M.(Int) -> Int)? = null -): BindingAdapter { - val adapter = BindingAdapter() - when { - itemLayout != NO_ID -> adapter.addType(itemLayout) - block != null -> adapter.addType(block) - else -> throw NoSuchPropertyException("Please add item model type") - } - this.adapter = adapter - return adapter -} - -val RecyclerView.bindingAdapter - get() = adapter as BindingAdapter - -var RecyclerView.models - get() = bindingAdapter.models - set(value) { - bindingAdapter.models = value - } +// fun RecyclerView.linear( - @RecyclerView.Orientation orientation: Int = VERTICAL, - reverseLayout: Boolean = false + @RecyclerView.Orientation orientation: Int = VERTICAL, + reverseLayout: Boolean = false ): RecyclerView { layoutManager = HoverLinearLayoutManager(context, orientation, reverseLayout) return this } fun RecyclerView.grid( - spanCount: Int, - @RecyclerView.Orientation orientation: Int = VERTICAL, - reverseLayout: Boolean = false + spanCount: Int = 1, + @RecyclerView.Orientation orientation: Int = VERTICAL, + reverseLayout: Boolean = false ): RecyclerView { layoutManager = HoverGridLayoutManager(context, spanCount, orientation, reverseLayout) return this } fun RecyclerView.staggered( - spanCount: Int, - @RecyclerView.Orientation orientation: Int = VERTICAL + spanCount: Int, + @RecyclerView.Orientation orientation: Int = VERTICAL ): RecyclerView { layoutManager = HoverStaggeredGridLayoutManager(spanCount, orientation) return this } +// + +// +/** + * 函数配置分割线 + */ fun RecyclerView.divider( - @DrawableRes drawable: Int, - @RecyclerView.Orientation orientation: Int = RecyclerView.VERTICAL, - block: ((Rect, View, RecyclerView, RecyclerView.State) -> Boolean)? = null + block: DefaultDecoration.() -> Unit ): RecyclerView { - val decoration = DefaultDecoration(context).apply { + val itemDecoration = DefaultDecoration(context).apply(block) + addItemDecoration(itemDecoration) + return this +} + +/** + * 指定Drawable资源为分割线, 分割线的间距和宽度应在资源文件中配置 + */ +fun RecyclerView.divider( + @DrawableRes drawable: Int +): RecyclerView { + return divider { setDrawable(drawable) } - block?.let { - decoration.onItemOffsets(block) +} + +/** + * 指定颜色为分割线 + * @param color 颜色 + * @param marginStart 左或上间距 + * @param marginEnd 右或下间距 + * @param width 分割线宽度 + */ +fun RecyclerView.dividerColor( + @ColorInt color: Int, + marginStart: Int = 0, + marginEnd: Int = 0, + width: Int = 1 +): RecyclerView { + return divider { + setColor(color) + setMargin(marginStart, marginEnd) + setWith(width) + } +} + +fun RecyclerView.dividerColor( + color: String, + marginStart: Int = 0, + marginEnd: Int = 0, + width: Int = 1 +): RecyclerView { + return divider { + setColor(color) + setMargin(marginStart, marginEnd) + setWith(width) + } +} + +fun RecyclerView.dividerColorRes( + @ColorRes color: Int, + marginStart: Int = 0, + marginEnd: Int = 0, + width: Int = 1 +): RecyclerView { + return divider { + setColorRes(color) + setMargin(marginStart, marginEnd) + setWith(width) } - addItemDecoration(decoration) - return this } +// +// /** - * 对话框设置列表 - * + * 对话框设置一个列表组件 */ -fun Dialog.setAdapter(block: BindingAdapter.(RecyclerView) -> Unit): Dialog { +fun Dialog.brv(block: BindingAdapter.(RecyclerView) -> Unit): Dialog { val context = context val recyclerView = RecyclerView(context) recyclerView.setup(block) @@ -124,6 +157,7 @@ fun Dialog.setAdapter(block: BindingAdapter.(RecyclerView) -> Unit): Dialog { setContentView(recyclerView) return this } +// diff --git a/build.gradle b/build.gradle index 7920bdf87..c2f8209b5 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { ext { - kotlin_version = '1.3.61' + kotlin_version = '1.3.72' rv_version = '1.1.0' } repositories { @@ -18,7 +18,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.6.3' + classpath 'com.android.tools.build:gradle:4.0.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e1574ae0c..6d8b9982f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun May 03 16:38:04 CST 2020 +#Fri May 29 15:14:59 CST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip diff --git a/smaple/src/main/java/com/drake/brv/sample/mod/GroupModel.kt b/smaple/src/main/java/com/drake/brv/sample/mod/GroupModel.kt deleted file mode 100644 index 09295692e..000000000 --- a/smaple/src/main/java/com/drake/brv/sample/mod/GroupModel.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.drake.brv.sample.mod - -import com.drake.brv.item.ItemExpand -import com.drake.brv.item.ItemHover - -class GroupModel : ItemExpand, ItemHover { - - override var itemGroupPosition: Int = 0 - override var itemExpand: Boolean = false - override var itemSublist: List? = listOf(Model(), Model(), Model(), Model()) - override var itemHover: Boolean = true - val title get() = "分组 [ $itemGroupPosition ]" - -} \ No newline at end of file diff --git a/smaple/src/main/java/com/drake/brv/sample/mod/NestedGroupModel.kt b/smaple/src/main/java/com/drake/brv/sample/mod/NestedGroupModel.kt deleted file mode 100644 index 45ef04a40..000000000 --- a/smaple/src/main/java/com/drake/brv/sample/mod/NestedGroupModel.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.drake.brv.sample.mod - -import com.drake.brv.item.ItemExpand - -class NestedGroupModel : ItemExpand { - - override var itemGroupPosition: Int = 0 - override var itemExpand: Boolean = false - override var itemSublist: List? = listOf(Model(), Model(), Model(), Model()) - val title get() = "嵌套分组 [ $itemGroupPosition ]" - -} \ No newline at end of file diff --git a/smaple/src/main/java/com/drake/brv/sample/mod/CheckModel.kt b/smaple/src/main/java/com/drake/brv/sample/model/CheckModel.kt similarity index 89% rename from smaple/src/main/java/com/drake/brv/sample/mod/CheckModel.kt rename to smaple/src/main/java/com/drake/brv/sample/model/CheckModel.kt index 0fba296ab..2621200a2 100644 --- a/smaple/src/main/java/com/drake/brv/sample/mod/CheckModel.kt +++ b/smaple/src/main/java/com/drake/brv/sample/model/CheckModel.kt @@ -5,7 +5,7 @@ * Date:9/11/19 6:49 PM */ -package com.drake.brv.sample.mod +package com.drake.brv.sample.model import androidx.databinding.BaseObservable diff --git a/smaple/src/main/java/com/drake/brv/sample/mod/DoubleItemModel.kt b/smaple/src/main/java/com/drake/brv/sample/model/DoubleItemModel.kt similarity index 81% rename from smaple/src/main/java/com/drake/brv/sample/mod/DoubleItemModel.kt rename to smaple/src/main/java/com/drake/brv/sample/model/DoubleItemModel.kt index e6d437ce3..c0b969897 100644 --- a/smaple/src/main/java/com/drake/brv/sample/mod/DoubleItemModel.kt +++ b/smaple/src/main/java/com/drake/brv/sample/model/DoubleItemModel.kt @@ -5,6 +5,6 @@ * Date:9/11/19 6:49 PM */ -package com.drake.brv.sample.mod +package com.drake.brv.sample.model class DoubleItemModel \ No newline at end of file diff --git a/smaple/src/main/java/com/drake/brv/sample/mod/FlexTagModel.kt b/smaple/src/main/java/com/drake/brv/sample/model/FlexTagModel.kt similarity index 51% rename from smaple/src/main/java/com/drake/brv/sample/mod/FlexTagModel.kt rename to smaple/src/main/java/com/drake/brv/sample/model/FlexTagModel.kt index 34194c841..f9a0b08a6 100644 --- a/smaple/src/main/java/com/drake/brv/sample/mod/FlexTagModel.kt +++ b/smaple/src/main/java/com/drake/brv/sample/model/FlexTagModel.kt @@ -1,3 +1,3 @@ -package com.drake.brv.sample.mod +package com.drake.brv.sample.model class FlexTagModel(var name: String) \ No newline at end of file diff --git a/smaple/src/main/java/com/drake/brv/sample/model/GroupModel.kt b/smaple/src/main/java/com/drake/brv/sample/model/GroupModel.kt new file mode 100644 index 000000000..3784c7e61 --- /dev/null +++ b/smaple/src/main/java/com/drake/brv/sample/model/GroupModel.kt @@ -0,0 +1,25 @@ +package com.drake.brv.sample.model + +import androidx.databinding.BaseObservable +import com.drake.brv.item.ItemExpand +import com.drake.brv.item.ItemHover +import com.drake.brv.item.ItemPosition +import com.drake.brv.sample.R + +class GroupModel : ItemExpand, ItemHover, ItemPosition, BaseObservable() { + + override var itemGroupPosition: Int = 0 + override var itemExpand: Boolean = false + set(value) { + field = value + notifyChange() + } + override var itemSublist: List? = listOf(Model(), Model(), Model(), Model()) + override var itemHover: Boolean = true + override var itemPosition: Int = 0 + + val title get() = "分组 [ $itemGroupPosition ]" + + val expandIcon get() = if (itemExpand) R.drawable.ic_arrow_expand else R.drawable.ic_arrow_collapse + +} \ No newline at end of file diff --git a/smaple/src/main/java/com/drake/brv/sample/mod/HoverHeaderModel.kt b/smaple/src/main/java/com/drake/brv/sample/model/HoverHeaderModel.kt similarity index 88% rename from smaple/src/main/java/com/drake/brv/sample/mod/HoverHeaderModel.kt rename to smaple/src/main/java/com/drake/brv/sample/model/HoverHeaderModel.kt index 0a09eccec..f58e1171a 100644 --- a/smaple/src/main/java/com/drake/brv/sample/mod/HoverHeaderModel.kt +++ b/smaple/src/main/java/com/drake/brv/sample/model/HoverHeaderModel.kt @@ -5,7 +5,7 @@ * Date:9/11/19 6:49 PM */ -package com.drake.brv.sample.mod +package com.drake.brv.sample.model import com.drake.brv.item.ItemHover diff --git a/smaple/src/main/java/com/drake/brv/sample/mod/Model.kt b/smaple/src/main/java/com/drake/brv/sample/model/Model.kt similarity index 80% rename from smaple/src/main/java/com/drake/brv/sample/mod/Model.kt rename to smaple/src/main/java/com/drake/brv/sample/model/Model.kt index 450af31b3..855078fc9 100644 --- a/smaple/src/main/java/com/drake/brv/sample/mod/Model.kt +++ b/smaple/src/main/java/com/drake/brv/sample/model/Model.kt @@ -5,6 +5,6 @@ * Date:9/11/19 6:49 PM */ -package com.drake.brv.sample.mod +package com.drake.brv.sample.model class Model \ No newline at end of file diff --git a/smaple/src/main/java/com/drake/brv/sample/model/NestedGroupModel.kt b/smaple/src/main/java/com/drake/brv/sample/model/NestedGroupModel.kt new file mode 100644 index 000000000..b291fbd23 --- /dev/null +++ b/smaple/src/main/java/com/drake/brv/sample/model/NestedGroupModel.kt @@ -0,0 +1,18 @@ +package com.drake.brv.sample.model + +import androidx.databinding.BaseObservable +import com.drake.brv.item.ItemExpand +import com.drake.brv.sample.R + +class NestedGroupModel : ItemExpand, BaseObservable() { + + override var itemGroupPosition: Int = 0 + override var itemExpand: Boolean = false + set(value) { + field = value + notifyChange() + } + override var itemSublist: List? = listOf(Model(), Model(), Model(), Model()) + val title get() = "嵌套分组 [ $itemGroupPosition ]" + val expandIcon get() = if (itemExpand) R.drawable.ic_arrow_nested_expand else R.drawable.ic_arrow_nested_collapse +} \ No newline at end of file diff --git a/smaple/src/main/java/com/drake/brv/sample/mod/OneMoreTypeModel.kt b/smaple/src/main/java/com/drake/brv/sample/model/OneMoreTypeModel.kt similarity index 83% rename from smaple/src/main/java/com/drake/brv/sample/mod/OneMoreTypeModel.kt rename to smaple/src/main/java/com/drake/brv/sample/model/OneMoreTypeModel.kt index 5991e9d3d..da81cc2ce 100644 --- a/smaple/src/main/java/com/drake/brv/sample/mod/OneMoreTypeModel.kt +++ b/smaple/src/main/java/com/drake/brv/sample/model/OneMoreTypeModel.kt @@ -5,6 +5,6 @@ * Date:9/11/19 6:49 PM */ -package com.drake.brv.sample.mod +package com.drake.brv.sample.model data class OneMoreTypeModel(var type: Int) \ No newline at end of file diff --git a/smaple/src/main/java/com/drake/brv/sample/model/StaggeredModel.kt b/smaple/src/main/java/com/drake/brv/sample/model/StaggeredModel.kt new file mode 100644 index 000000000..6332b7f1c --- /dev/null +++ b/smaple/src/main/java/com/drake/brv/sample/model/StaggeredModel.kt @@ -0,0 +1,5 @@ +package com.drake.brv.sample.model + +import com.drake.brv.item.ItemPosition + +data class StaggeredModel(var width: Int = 400, var height: Int = 600, override var itemPosition: Int = 0) : ItemPosition \ No newline at end of file diff --git a/smaple/src/main/java/com/drake/brv/sample/mod/SwipeDragModel.kt b/smaple/src/main/java/com/drake/brv/sample/model/SwipeDragModel.kt similarity index 95% rename from smaple/src/main/java/com/drake/brv/sample/mod/SwipeDragModel.kt rename to smaple/src/main/java/com/drake/brv/sample/model/SwipeDragModel.kt index 1f7e65dfe..d604f0837 100644 --- a/smaple/src/main/java/com/drake/brv/sample/mod/SwipeDragModel.kt +++ b/smaple/src/main/java/com/drake/brv/sample/model/SwipeDragModel.kt @@ -1,4 +1,4 @@ -package com.drake.brv.sample.mod +package com.drake.brv.sample.model import com.drake.brv.annotaion.DragType import com.drake.brv.annotaion.SwipeType diff --git a/smaple/src/main/java/com/drake/brv/sample/ui/activity/MainActivity.kt b/smaple/src/main/java/com/drake/brv/sample/ui/activity/MainActivity.kt index 5eac0f3d1..0b4595fa8 100644 --- a/smaple/src/main/java/com/drake/brv/sample/ui/activity/MainActivity.kt +++ b/smaple/src/main/java/com/drake/brv/sample/ui/activity/MainActivity.kt @@ -2,7 +2,7 @@ * Copyright (C) 2018, Umbrella CompanyLimited All rights reserved. * Project:BRV * Author:Drake - * Date:9/11/19 6:49 PM + * Date:9/11/19 6:49 PM */ package com.drake.brv.sample.ui.activity diff --git a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/CheckModeFragment.kt b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/CheckModeFragment.kt index 7cf70aab9..c07deb7cb 100644 --- a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/CheckModeFragment.kt +++ b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/CheckModeFragment.kt @@ -13,7 +13,7 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import com.drake.brv.sample.R -import com.drake.brv.sample.mod.CheckModel +import com.drake.brv.sample.model.CheckModel import com.drake.brv.utils.bindingAdapter import com.drake.brv.utils.linear import com.drake.brv.utils.setup diff --git a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/DividerFragment.kt b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/DividerFragment.kt new file mode 100644 index 000000000..cbf706e03 --- /dev/null +++ b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/DividerFragment.kt @@ -0,0 +1,79 @@ +package com.drake.brv.sample.ui.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.drake.brv.annotaion.Orientation +import com.drake.brv.layoutmanager.HoverGridLayoutManager +import com.drake.brv.sample.R +import com.drake.brv.sample.model.StaggeredModel +import com.drake.brv.utils.divider +import com.drake.brv.utils.setup +import kotlinx.android.synthetic.main.fragment_divider.* + + +class DividerFragment : Fragment() { + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + + return inflater.inflate(R.layout.fragment_divider, container, false) + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + + // 动态跨度同样支持均分分割线 + rv_grid.layoutManager = HoverGridLayoutManager(context, 3, RecyclerView.VERTICAL, false).apply { + spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() { + override fun getSpanSize(position: Int): Int { + return if (position == 3) 2 else 1 + } + } + } + + rv_grid.divider { + orientation = Orientation.GRID + setColorRes(R.color.dividerDecoration) + setWith(30, true) + startVisible = true // 网格布局中水平方向首尾显示分割线 + endVisible = true // 网格布局中垂直方向首尾显示分割线 + }.setup { + addType(R.layout.item_staggered) + + // 模拟瀑布流动态宽高, 根据数据动态改变宽高, 瀑布流不建议宽高同时都可变 + // onBind { + // val model = getModel() + // itemView.layoutParams.apply { + // // width = model.width + // height = model.height + // itemView.layoutParams = this + // } + // false + // } + + }.models = getData() + } + + + private fun getData(): List { + val data = mutableListOf() + // 模拟瀑布流动态宽高 + for (i in 0..9) { + when (i) { + 2 -> data.add(StaggeredModel(height = 400, width = 200)) + 3 -> data.add(StaggeredModel(height = 400, width = 150)) + 5 -> data.add(StaggeredModel(height = 800)) + 4 -> data.add(StaggeredModel(height = 1000)) + 8 -> data.add(StaggeredModel(height = 500)) + 11 -> data.add(StaggeredModel(height = 700)) + else -> data.add(StaggeredModel()) + } + } + return data + } + +} diff --git a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/FlexBoxFragment.kt b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/FlexBoxFragment.kt index b2eb81c1c..3bd74d955 100644 --- a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/FlexBoxFragment.kt +++ b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/FlexBoxFragment.kt @@ -13,7 +13,7 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import com.drake.brv.sample.R -import com.drake.brv.sample.mod.FlexTagModel +import com.drake.brv.sample.model.FlexTagModel import com.drake.brv.utils.setup import com.google.android.flexbox.FlexboxLayoutManager import kotlinx.android.synthetic.main.fragment_flex_box.* diff --git a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/GroupFragment.kt b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/GroupFragment.kt index 2efdc0cff..aa89fb42a 100644 --- a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/GroupFragment.kt +++ b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/GroupFragment.kt @@ -7,10 +7,9 @@ import android.view.ViewGroup import androidx.fragment.app.Fragment import com.drake.brv.item.ItemExpand import com.drake.brv.sample.R -import com.drake.brv.sample.mod.GroupModel -import com.drake.brv.sample.mod.Model -import com.drake.brv.sample.mod.NestedGroupModel -import com.drake.brv.utils.divider +import com.drake.brv.sample.model.GroupModel +import com.drake.brv.sample.model.Model +import com.drake.brv.sample.model.NestedGroupModel import com.drake.brv.utils.linear import com.drake.brv.utils.setup import com.drake.tooltip.toast @@ -27,13 +26,15 @@ class GroupFragment : Fragment() { override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - rv_group.linear().divider(R.drawable.divider_horizontal).setup { + rv_group.linear().setup { + // 任何条目都需要添加类型到BindingAdapter中 addType(R.layout.item_group_title) addType(R.layout.item_nested_group_title) addType(R.layout.item_multi_type_simple) + addFastClickable(R.id.item) - onClick(R.id.item) { + onClick { when (itemViewType) { R.layout.item_nested_group_title, R.layout.item_group_title -> { val changeCount = if (getModel().itemExpand) "折叠 ${expandOrCollapse()} 条" else "展开 ${expandOrCollapse()} 条" @@ -41,14 +42,8 @@ class GroupFragment : Fragment() { } } } - }.models = getData() - // dev { - // function { - // // (rv_group.layoutManager as LinearLayoutManager).scrollToPosition(3) - // rv_group.smoothScrollToPosition(3) - // } - // } + }.models = getData() } diff --git a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/HeaderFooterFragment.kt b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/HeaderFooterFragment.kt index 3dd12a594..9947bc731 100644 --- a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/HeaderFooterFragment.kt +++ b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/HeaderFooterFragment.kt @@ -14,7 +14,7 @@ import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.fragment.app.Fragment import com.drake.brv.sample.R -import com.drake.brv.sample.mod.Model +import com.drake.brv.sample.model.Model import com.drake.brv.utils.bindingAdapter import com.drake.brv.utils.linear import com.drake.brv.utils.setup @@ -24,8 +24,6 @@ import kotlinx.android.synthetic.main.fragment_header_footer.* class HeaderFooterFragment : Fragment() { - lateinit var toolbar: Toolbar - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -67,7 +65,7 @@ class HeaderFooterFragment : Fragment() { val adapter = rv_header_footer.bindingAdapter - toolbar = activity!!.findViewById(R.id.toolbar) + val toolbar: Toolbar = requireActivity().findViewById(R.id.toolbar) toolbar.inflateMenu(R.menu.menu_header_footer) toolbar.setOnMenuItemClickListener { when (it.itemId) { diff --git a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/HoverHeaderFragment.kt b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/HoverHeaderFragment.kt index 17af092b5..1d1d87875 100644 --- a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/HoverHeaderFragment.kt +++ b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/HoverHeaderFragment.kt @@ -8,8 +8,8 @@ import androidx.core.view.ViewCompat import androidx.fragment.app.Fragment import com.drake.brv.listener.OnHoverAttachListener import com.drake.brv.sample.R -import com.drake.brv.sample.mod.HoverHeaderModel -import com.drake.brv.sample.mod.Model +import com.drake.brv.sample.model.HoverHeaderModel +import com.drake.brv.sample.model.Model import com.drake.brv.utils.bindingAdapter import com.drake.brv.utils.linear import com.drake.brv.utils.setup diff --git a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/MultiTypeFragment.kt b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/MultiTypeFragment.kt index 30b6bb415..d1fead16b 100644 --- a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/MultiTypeFragment.kt +++ b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/MultiTypeFragment.kt @@ -13,8 +13,8 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import com.drake.brv.sample.R -import com.drake.brv.sample.mod.DoubleItemModel -import com.drake.brv.sample.mod.Model +import com.drake.brv.sample.model.DoubleItemModel +import com.drake.brv.sample.model.Model import com.drake.brv.utils.bindingAdapter import com.drake.brv.utils.linear import com.drake.brv.utils.setup diff --git a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/OneMoreTypeFragment.kt b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/OneMoreTypeFragment.kt index e28d11424..3b439a620 100644 --- a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/OneMoreTypeFragment.kt +++ b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/OneMoreTypeFragment.kt @@ -13,7 +13,7 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import com.drake.brv.sample.R -import com.drake.brv.sample.mod.OneMoreTypeModel +import com.drake.brv.sample.model.OneMoreTypeModel import com.drake.brv.utils.linear import com.drake.brv.utils.setup import kotlinx.android.synthetic.main.fragment_one_more_type.* diff --git a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/RefreshFragment.kt b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/RefreshFragment.kt index 0dab3450a..8fc41da7a 100644 --- a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/RefreshFragment.kt +++ b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/RefreshFragment.kt @@ -15,8 +15,8 @@ import androidx.appcompat.widget.Toolbar import androidx.fragment.app.Fragment import com.drake.brv.PageRefreshLayout import com.drake.brv.sample.R -import com.drake.brv.sample.mod.DoubleItemModel -import com.drake.brv.sample.mod.Model +import com.drake.brv.sample.model.DoubleItemModel +import com.drake.brv.sample.model.Model import com.drake.brv.utils.linear import com.drake.brv.utils.setup import com.drake.tooltip.toast @@ -25,7 +25,6 @@ import kotlinx.android.synthetic.main.fragment_refresh.* class RefreshFragment : Fragment() { - lateinit var toolbar: Toolbar private val total = 2 override fun onCreateView( @@ -86,7 +85,7 @@ class RefreshFragment : Fragment() { private fun initToolbar(page: PageRefreshLayout) { - toolbar = activity!!.findViewById(R.id.toolbar) + val toolbar: Toolbar = requireActivity().findViewById(R.id.toolbar) toolbar.inflateMenu(R.menu.menu_refresh) toolbar.setOnMenuItemClickListener { when (it.itemId) { diff --git a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/StateLayoutFragment.kt b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/StateLayoutFragment.kt index b2040d4d6..bfd88ae3d 100644 --- a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/StateLayoutFragment.kt +++ b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/StateLayoutFragment.kt @@ -14,8 +14,8 @@ import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.fragment.app.Fragment import com.drake.brv.sample.R -import com.drake.brv.sample.mod.DoubleItemModel -import com.drake.brv.sample.mod.Model +import com.drake.brv.sample.model.DoubleItemModel +import com.drake.brv.sample.model.Model import com.drake.brv.utils.linear import com.drake.brv.utils.setup import com.drake.statelayout.StateLayout @@ -25,8 +25,6 @@ import kotlinx.android.synthetic.main.fragment_state_layout.* class StateLayoutFragment : Fragment() { - lateinit var toolbar: Toolbar - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -69,7 +67,7 @@ class StateLayoutFragment : Fragment() { private fun initToolbar(state: StateLayout) { - toolbar = activity!!.findViewById(R.id.toolbar) + val toolbar: Toolbar = requireActivity().findViewById(R.id.toolbar) toolbar.inflateMenu(R.menu.menu_state) toolbar.setOnMenuItemClickListener { when (it.itemId) { diff --git a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/SwipeDragFragment.kt b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/SwipeDragFragment.kt index a18faa246..4e4052e44 100644 --- a/smaple/src/main/java/com/drake/brv/sample/ui/fragment/SwipeDragFragment.kt +++ b/smaple/src/main/java/com/drake/brv/sample/ui/fragment/SwipeDragFragment.kt @@ -15,7 +15,7 @@ import androidx.fragment.app.Fragment import com.drake.brv.annotaion.DragType import com.drake.brv.annotaion.SwipeType import com.drake.brv.sample.R -import com.drake.brv.sample.mod.SwipeDragModel +import com.drake.brv.sample.model.SwipeDragModel import com.drake.brv.utils.linear import com.drake.brv.utils.setup import kotlinx.android.synthetic.main.fragment_swipe_drag.* diff --git a/smaple/src/main/java/com/drake/brv/sample/vm/RenderBindComponnent.kt b/smaple/src/main/java/com/drake/brv/sample/vm/RenderBindComponnent.kt new file mode 100644 index 000000000..2d4bde7c1 --- /dev/null +++ b/smaple/src/main/java/com/drake/brv/sample/vm/RenderBindComponnent.kt @@ -0,0 +1,10 @@ +package com.drake.brv.sample.vm + +import android.widget.ImageView +import androidx.annotation.DrawableRes +import androidx.databinding.BindingAdapter + +@BindingAdapter("android:src") +fun ImageView.bindImageRes(@DrawableRes drawable: Int) { + setImageResource(drawable) +} \ No newline at end of file diff --git a/smaple/src/main/res/drawable/divider_horizontal.xml b/smaple/src/main/res/drawable/divider_horizontal.xml index 9ab42cb13..a4efe41a3 100644 --- a/smaple/src/main/res/drawable/divider_horizontal.xml +++ b/smaple/src/main/res/drawable/divider_horizontal.xml @@ -1,5 +1,11 @@ - - - - \ No newline at end of file + + + + + + + + \ No newline at end of file diff --git a/smaple/src/main/res/drawable/divider_horizontal_dash.xml b/smaple/src/main/res/drawable/divider_horizontal_dash.xml new file mode 100644 index 000000000..78ebd9ce1 --- /dev/null +++ b/smaple/src/main/res/drawable/divider_horizontal_dash.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/smaple/src/main/res/drawable/divider_vertical.xml b/smaple/src/main/res/drawable/divider_vertical.xml new file mode 100644 index 000000000..26982befe --- /dev/null +++ b/smaple/src/main/res/drawable/divider_vertical.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/smaple/src/main/res/layout/fragment_divider.xml b/smaple/src/main/res/layout/fragment_divider.xml new file mode 100644 index 000000000..5a70fe217 --- /dev/null +++ b/smaple/src/main/res/layout/fragment_divider.xml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/smaple/src/main/res/layout/item_check_mode.xml b/smaple/src/main/res/layout/item_check_mode.xml index 7027133fa..7382864d2 100644 --- a/smaple/src/main/res/layout/item_check_mode.xml +++ b/smaple/src/main/res/layout/item_check_mode.xml @@ -14,7 +14,7 @@ + type="com.drake.brv.sample.model.CheckModel" /> diff --git a/smaple/src/main/res/layout/item_expand_loading.xml b/smaple/src/main/res/layout/item_expand_loading.xml new file mode 100644 index 000000000..d65355878 --- /dev/null +++ b/smaple/src/main/res/layout/item_expand_loading.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/smaple/src/main/res/layout/item_flex_tag.xml b/smaple/src/main/res/layout/item_flex_tag.xml index a9b0d9825..5342d1c36 100644 --- a/smaple/src/main/res/layout/item_flex_tag.xml +++ b/smaple/src/main/res/layout/item_flex_tag.xml @@ -6,7 +6,7 @@ + type="com.drake.brv.sample.model.FlexTagModel" /> diff --git a/smaple/src/main/res/layout/item_grid.xml b/smaple/src/main/res/layout/item_grid.xml new file mode 100644 index 000000000..ceb5be7c6 --- /dev/null +++ b/smaple/src/main/res/layout/item_grid.xml @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/smaple/src/main/res/layout/item_group_title.xml b/smaple/src/main/res/layout/item_group_title.xml index bbde71e30..e552d45fa 100644 --- a/smaple/src/main/res/layout/item_group_title.xml +++ b/smaple/src/main/res/layout/item_group_title.xml @@ -7,7 +7,7 @@ + type="com.drake.brv.sample.model.GroupModel" /> + android:src="@{m.expandIcon}" /> + type="com.drake.brv.sample.model.NestedGroupModel" /> + android:src="@{m.expandIcon}" /> + + + + + + + + + + + + + + + + + + diff --git a/smaple/src/main/res/layout/item_swipe_or_drag.xml b/smaple/src/main/res/layout/item_swipe_or_drag.xml index 8f2b70128..bdce5eaf8 100644 --- a/smaple/src/main/res/layout/item_swipe_or_drag.xml +++ b/smaple/src/main/res/layout/item_swipe_or_drag.xml @@ -8,7 +8,7 @@ + type="com.drake.brv.sample.model.SwipeDragModel" /> + + + + + + + \ No newline at end of file diff --git a/smaple/src/main/res/menu/menu_main.xml b/smaple/src/main/res/menu/menu_main.xml index 8d0a9d28a..b20ab24f7 100644 --- a/smaple/src/main/res/menu/menu_main.xml +++ b/smaple/src/main/res/menu/menu_main.xml @@ -14,10 +14,14 @@ android:id="@+id/hover" android:icon="@drawable/ic_hover_header" android:title="悬停" /> + + + + + android:title="分割线" /> + + + + + + android:id="@+id/grid_divider" + android:name="com.drake.brv.sample.ui.fragment.DividerFragment" + android:label="分割线" + tools:layout="@layout/fragment_divider" /> \ No newline at end of file diff --git a/smaple/src/main/res/values/colors.xml b/smaple/src/main/res/values/colors.xml index a4df1c867..e84b71168 100644 --- a/smaple/src/main/res/values/colors.xml +++ b/smaple/src/main/res/values/colors.xml @@ -13,6 +13,7 @@ #339e9e9e + #FF9800 #f5f5f5 #737373