RecyclerView中Decoration的使用场景不仅仅是做分隔线

继上一篇: RecyclerView中Decoration解读,就只能做分割占位了吗

最近看的知识点大致分为两个方向,一个是Kotlin,一个是自定义view,所以笔记写的就很杂,当然了主要还是一次性把一个东西学完学会,这里面消耗的心力和脑力是很大的。所以交叉着多次学习,Kotlin 学了到自定义view上可能又有使用的地方。所以,今天又来卡着一天的最后一两个小时写笔记了,这有一种刀尖舔血的魅力感。OK,那就开整

正文

上一篇blog,大致是对ItemDecoration 进行了简单的使用,比如说调用次数,层级划分等等。当然了还有额外的扩展空间,其实我有时候看到ItemDecoration的时候也会想这个玩意还能做啥。恰好,今天在翻阅启航大佬的《Android自定义控件高级进阶与精彩实例》这本书的时候,看到了大佬在该书的第7章里面提供了很多的思路,那么就尝试整一下,所以,这笔记里面很多东西都是在借鉴大佬这本书,嗯,大佬还写了一本书《Android自定义控件开发入门与实战》感觉也很细,都很适合填充一些自己的知识点盲区。

getItemOffsets中Rect对于整个recyclerView的影响

上一篇的demo 里面,当我们列表是上下滚动的,那么我们对于rect的设置是:

css 复制代码
// left top right bottom
outRect.set(0, 0, 0, 10))

我们只是对于bottom设置了10px。想要了解这个玩意的效果,最好还是理解一下Rect这个对象的在canvas使用上的含义。这里就需要偷一张图了:

又回到那个问题了,图看懂了,有啥关系吗? 那么我们就把每一个都设置10,然后分割线填充颜色。

bash 复制代码
outRect.set(10, 10, 10, 10)

那么来看效果图:

可以看到左右有10px的间距了,而且我们第一行的头上也有了10px,第2行和第1行之间的间距变成了20。单纯从效果上看,我们就可以知道,这个layoutManger计算item的绘制位置的时候,一定是获取了rect对象的参数的。在RecyclerView的measureChild的函数里面确实在获取这个调调,所以这个rect是可以影响整个的recycler的布局的,那么我们脑洞大一点,左右动态的呢?

kotlin 复制代码
override fun getItemOffsets(outRect: Rect, itemPosition: Int, parent: RecyclerView) {
    outRect.set(10*itemPosition, 10, 10*itemPosition, 5)
}

我们随着item的position的增加,左右也增加。

emmm? 果真要这样吗?既然如此大佬书中的效果就很容易理解了。下面几种效果不就是计算位置自定义view了吗?

绘制区域内容

我们再来回顾一下onDraw的入参。

less 复制代码
onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State)

recyclerview都拿到了,我们还拿不到什么?而且canvas是整个recyclerview 区域。我们再来回顾一下,之前绘制分割线的时候怎么确定分割线的位置的。

scss 复制代码
override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
    super.onDraw(canvas, parent, state)
    canvas.save()
    // 剩下的就是复制 DividerItemDecoration.drawVertical() 的代码,然后进行更改就行。
    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
        )
    } else {
        left = 0
        right = parent.width
    }

    val childCount = parent.childCount
    val startX = paddingHorizontal + left
    val stopX = right - paddingHorizontal
    LogUtils.e(stopX)
    for (i in 0 until childCount) {
        val child = parent.getChildAt(i)
        // 获取item的margins
        parent.getDecoratedBoundsWithMargins(child, mBounds)
        val bottom = mBounds.bottom + child.translationY
        val top = bottom - lineHeight+paddingVertical
        val rect=Rect(startX.toInt(),top.toInt(),stopX.toInt(),(bottom-paddingVertical).toInt())
        //paint.color=lineColor
        // 通过矩形绘制
        canvas.drawRect(rect,paint)
        // 通过线条绘制
        //paint.color=Color.RED
        //canvas.drawLine(startX,rect.centerY().toFloat(),stopX,rect.centerY().toFloat(),paint)
    }
    canvas.restore()
}

其中getDecoratedBoundsWithMargins很关键,它确定了我们需要绘制的分割线的位置。那么我们是不是也可以计算出这个item的y轴上的中间位置。为了确定这个的具体位置,直接实现onDrawOver:

kotlin 复制代码
override fun onDrawOver(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
    super.onDrawOver(canvas, parent, state)
    canvas.save()
    paint.color=Color.GREEN
    val child = parent.getChildAt(0)
    parent.getDecoratedBoundsWithMargins(child, mBounds)
    // 通过矩形绘制
    canvas.drawRect(mBounds,paint)
    canvas.restore()
}

可以看到,mbounds 所在空间其实是包含了我们所需要绘制分割线的空间的,所以,可以基于mBounds 去确定item的y轴的中间位置。

结束

因为是基于书上的内容,还是需要自己去看书,大致需要的逻辑,其实已经捋的比较细了,比如说确定位置,比如说如何让item不遮挡我们canvas所画的内容都又涉及到,demo 代码还是在上一篇中的分支里面。看完大佬的书,感觉真的限制我们的只有想象力,当然想象力完全依托于认知,所以提升认知还是任重道远的。

相关推荐
开发之奋斗人生12 分钟前
android关于pthread的使用过程
android·pthread
wu_android2 小时前
Android 视图系统入门指南
android
淡淡的香烟2 小时前
Android11 Launcher3实现去掉抽屉改为单层
android
火柴就是我2 小时前
每日见闻之THREE.PerspectiveCamera的含义
android
小书房3 小时前
Android的Dalvik和ART
android·aot·jit·art·dalvik
夏日玲子3 小时前
Monkey 测试的基本概念及常用命令(Android )
android
whysqwhw3 小时前
Transcoder代码学习-项目构建
android
夕泠爱吃糖3 小时前
Linux 文件内容的查询与统计
android·linux·c#
yzpyzp4 小时前
Kotlin的MutableList和ArrayList区别
android·kotlin
用户2018792831674 小时前
故事:《安卓公司的消息快递系统》
android