RecyclerView系列之二 ItemDecoration

一 添加分割线

less 复制代码
recyclerView.addItemDecoration(DividerItemDecoration(this@MainActivity,LinearLayout.VERTICAL))

二 什么是ItemDecoration

它是Item的装饰,在Item的四周,我们可以给它添加上自定义的装饰,我们也可以在Item的上下左右添加装饰,而且这些装饰是允许我们自定义的。如果我们想实现其它的装饰效果,就需要自定义了。

三 自定义ItemDecoration

3.1 getItemOffsets的意义

当我们要重写ItemDecoration时,主要涉及到三个函数

typescript 复制代码
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
    super.onDraw(c, parent, state);
}

@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
    super.onDrawOver(c, parent, state);
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    super.getItemOffsets(outRect, view, parent, state);
}

首先我们来看看getItemOffsets: 它的主要作用就是给item的四周加上边距,实现的效果类似margin,将item的四周撑开一些距离,在撑开这些距离后,我们将可以利用上面的onDraw函数,在这个距离上进行绘图。我们来看看这个方法

kotlin 复制代码
verride fun getItemOffsets(
    outRect: Rect,
    view: View,
    parent: RecyclerView,
    state: RecyclerView.State
) {
    super.getItemOffsets(outRect, view, parent, state)
}

outRect:Rect 就是表示在item的上下左右所撑开的距离。 view:View 是指当前Item的View对象 parent:RecyclerView 是指RecyclerView本身 state:Recycler.State 通过State可以获取当前RecyclerView的状态。

下面我们专门来看看Rect outRect这个参数,outRect的top,left,right,bottom四个点,是指Item上,左,右,下撑开的距离,这个值默认是0。

3.2 getItemOffsets示例 我们自定义一条红色分割线,首先我们给整个布局加上一个红色的背景色。

ini 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F60459"
    android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

然后再给每个Item添加上默认的背景色白色,这样有白色的地方就不会透出背景色的红色了,而没有白色的地方就会露出红色。

ini 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@color/white"
    android:padding="16dp">

    <TextView
        android:id="@+id/tvItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"/>

</LinearLayout>

然后就是自定义我们的CustomLinearLayoutDecoration,

kotlin 复制代码
class CustomLinearLayoutDecoration : RecyclerView.ItemDecoration() {
    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        super.getItemOffsets(outRect, view, parent, state)
        outRect.top = 1 //这里暂时先直接写死1px
    }

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)
    }

    override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDrawOver(c, parent, state)
    }
}

效果如图展示:

这里可以看到每个Item的上方都出现了一条红线,如果我们改为底部1px,左侧50px,右侧100px,

kotlin 复制代码
override fun getItemOffsets(
    outRect: Rect,
    view: View,
    parent: RecyclerView,
    state: RecyclerView.State
) {
    super.getItemOffsets(outRect, view, parent, state)
    //这里暂时先直接写死1px
    outRect.left=50;
    outRect.right=100;
    outRect.bottom=1;
}

3.3 onDraw的用法:

kotlin 复制代码
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
    super.onDraw(c, parent, state)
}

c:Canvas是指通过getItemOffsets撑开的空白区域所对应的画布,通过这个canvas可以在getItemOffsetes所撑出来的区域进行任意绘图。现在我们想在getItemOffsets的Item的左侧撑出来的200px的距离,然后在中间画一个圆形。

注意:getItemOffsets是针对每个Item走一次,也就是说每个Item的outRect都可以不同,但是onDraw所针对整个ItemDecoration只执行一次,并不是针对Item,所有我们需要在onDraw中绘图时,一次性将所有Item的ItemOration绘制完成。

下面我们来举例每个Item也是可以设置不同的outRect,这点特别适合对第一个item进行特殊处理的情况。

ini 复制代码
private val LEFT_OFFSETS = 200  //这里暂时先直接写死200px
private val RADIUS = 20f
var mPaint: Paint = Paint().apply {
    color = Color.GREEN
}
ini 复制代码
override fun getItemOffsets(
    outRect: Rect,
    view: View,
    parent: RecyclerView,
    state: RecyclerView.State
) {
    super.getItemOffsets(outRect, view, parent, state)
    //这里获取itemview位于整个RecyclerView列表的position
    val position = parent.getChildAdapterPosition(view)
    if (position == 0) {
        outRect.left = 400;
        outRect.bottom = 1;
    } else {
        outRect.left = LEFT_OFFSETS;
        outRect.bottom = 1;
    }
}
相关推荐
*拯34 分钟前
Uniapp Android/IOS 获取手机通讯录
android·ios·uni-app
天天打码3 小时前
Lynx-字节跳动跨平台框架多端兼容Android, iOS, Web 原生渲染
android·前端·javascript·ios
lilili啊啊啊5 小时前
iOS safari和android chrome开启网页调试与检查器的方法
android·ios·safari
Blue.ztl7 小时前
菜鸟之路day31一一MySQL之多表设计
android·数据库·mysql
练习本11 小时前
Android系统架构模式分析
android·java·架构·系统架构
每次的天空16 小时前
Kotlin 内联函数深度解析:从源码到实践优化
android·开发语言·kotlin
练习本16 小时前
Android MVC架构的现代化改造:构建清晰单向数据流
android·架构·mvc
早上好啊! 树哥16 小时前
android studio开发:设置屏幕朝向为竖屏,强制应用的包体始终以竖屏(纵向)展示
android·ide·android studio
YY_pdd17 小时前
使用go开发安卓程序
android·golang
Android 小码峰啊19 小时前
Android Compose 框架物理动画之捕捉动画深入剖析(29)
android·spring