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;
    }
}
相关推荐
Yang-Never3 小时前
Kotlin协程 -> Job.join() 完整流程图与核心源码分析
android·开发语言·kotlin·android studio
一笑的小酒馆8 小时前
Android性能优化之截屏时黑屏卡顿问题
android
懒人村杂货铺11 小时前
Android BLE 扫描完整实战
android
TeleostNaCl13 小时前
如何安装 Google 通用的驱动以便使用 ADB 和 Fastboot 调试(Bootloader)设备
android·经验分享·adb·android studio·android-studio·android runtime
fatiaozhang952714 小时前
中国移动浪潮云电脑CD1000-系统全分区备份包-可瑞芯微工具刷机-可救砖
android·网络·电脑·电视盒子·刷机固件·机顶盒刷机
2501_9159184115 小时前
iOS 开发全流程实战 基于 uni-app 的 iOS 应用开发、打包、测试与上架流程详解
android·ios·小程序·https·uni-app·iphone·webview
lichong95115 小时前
【混合开发】vue+Android、iPhone、鸿蒙、win、macOS、Linux之dist打包发布在Android工程asserts里
android·vue.js·iphone
Android出海15 小时前
Android 15重磅升级:16KB内存页机制详解与适配指南
android·人工智能·新媒体运营·产品运营·内容运营
一只修仙的猿15 小时前
毕业三年后,我离职了
android·面试
编程乐学16 小时前
安卓非原创--基于Android Studio 实现的新闻App
android·ide·android studio·移动端开发·安卓大作业·新闻app