├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── zyyoona7
│ │ └── demo
│ │ ├── DataServer.kt
│ │ ├── Extentions.kt
│ │ ├── MainActivity.kt
│ │ ├── SectionData.kt
│ │ ├── activity
│ │ ├── BaseActivity.kt
│ │ ├── HorizontalGridActivity.kt
│ │ ├── HorizontalLinearActivity.kt
│ │ ├── HorizontalSectionGridActivity.kt
│ │ ├── HorizontalSectionLinearActivity.kt
│ │ ├── HorizontalStaggeredGridActivity.kt
│ │ ├── VerticalGridActivity.kt
│ │ ├── VerticalLinearActivity.kt
│ │ ├── VerticalSectionGridActivity.kt
│ │ ├── VerticalSectionLinearActivity.kt
│ │ └── VerticalStaggeredGridActivity.kt
│ │ └── adapter
│ │ ├── DataAdapter.kt
│ │ ├── HorizontalDataAdapter.kt
│ │ ├── HorizontalSectionAdapter.kt
│ │ ├── MainAdapter.kt
│ │ └── SectionAdapter.kt
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ └── ic_launcher_background.xml
│ ├── layout
│ ├── activity_base.xml
│ ├── activity_main.xml
│ ├── item_data.xml
│ ├── item_hor_footer.xml
│ ├── item_hor_header.xml
│ ├── item_hor_section_header.xml
│ ├── item_horizontal_data.xml
│ ├── item_main.xml
│ ├── item_section_header.xml
│ ├── item_ver_footer.xml
│ └── item_ver_header.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── itemdecoration
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── zyyoona7
│ │ └── itemdecoration
│ │ ├── RecyclerViewDivider.kt
│ │ ├── ext
│ │ └── Extentions.kt
│ │ └── provider
│ │ ├── GridItemDecoration.kt
│ │ ├── LinearItemDecoration.kt
│ │ └── StaggeredGridItemDecoration.kt
│ └── res
│ └── values
│ └── strings.xml
├── preview
├── grid.gif
├── linear.gif
└── staggered_grid.gif
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | /build
7 | /captures
8 | .externalNativeBuild
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RecyclerViewItemDecoration
2 | itemDecoration for LinearLayoutManager,GridLayoutManager,StaggeredGridLayoutManager.
3 |
4 | ### 效果图(Preview)
5 |
6 | 
7 | 
8 | 
9 |
10 | ### 依赖(dependencies)
11 |
12 | ```groovy
13 | implementation 'com.github.zyyoona7:RecyclerViewItemDecoration:1.0.3'
14 | ```
15 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | android {
6 | compileSdkVersion 28
7 | defaultConfig {
8 | applicationId "com.zyyoona7.demo"
9 | minSdkVersion 16
10 | targetSdkVersion 28
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | implementation fileTree(include: ['*.jar'], dir: 'libs')
24 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
25 | implementation 'androidx.appcompat:appcompat:1.0.0'
26 | implementation 'androidx.recyclerview:recyclerview:1.0.0'
27 | implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.46'
28 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
29 | implementation project(':itemdecoration')
30 | // implementation 'com.github.zyyoona7:RecyclerViewItemDecoration:1.0.2'
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/DataServer.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo
2 |
3 | /**
4 | * @author zyyoona7
5 | * @version v1.0
6 | * @since 2018/12/13.
7 | */
8 | class DataServer {
9 |
10 | companion object {
11 |
12 | @JvmStatic
13 | fun createLinearData(size: Int = 30) = createData("这是 LinearLayoutManager ItemDecoration 展示。", size)
14 |
15 | @JvmStatic
16 | fun createGridData(size: Int = 30) = createData("这是 GridLayoutManager ItemDecoration 展示。", size)
17 |
18 | @JvmStatic
19 | fun createStaggeredGridData(size: Int = 30) =
20 | createData("这是 StaggeredGridLayoutManager ItemDecoration 展示。", size)
21 |
22 | private fun createData(text: String, size: Int): List {
23 | val list = arrayListOf()
24 | for (i in 0 until size) {
25 | list.add(text)
26 | }
27 | return list
28 | }
29 |
30 | @JvmStatic
31 | fun createSectionLinearData(size: Int = 30) = createSectionData(
32 | "Section Header",
33 | "这是 LinearLayoutManager ItemDecoration 展示。", size
34 | )
35 |
36 | @JvmStatic
37 | fun createSectionGridData(size: Int = 30) = createSectionData(
38 | "Section Header",
39 | "这是 GridLayoutManager ItemDecoration 展示。", size
40 | )
41 |
42 | @JvmStatic
43 | fun createSectionStaggerGridData(size: Int = 30) = createSectionData(
44 | "Section Header",
45 | "这是 StaggeredGridLayoutManager ItemDecoration 展示。", size
46 | )
47 |
48 | private fun createSectionData(header: String, text: String, size: Int): List {
49 | val list = arrayListOf()
50 | for (i in 0 until size) {
51 | if (i % 5 == 0) {
52 | list.add(SectionData(true, header, text))
53 | } else {
54 | list.add(SectionData(false, header, text))
55 | }
56 | }
57 | return list
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/Extentions.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo
2 |
3 | import android.content.res.Resources
4 | import android.util.TypedValue
5 |
6 | /**
7 | * @author zyyoona7
8 | * @version v1.0
9 | * @since 2018/12/13.
10 | */
11 |
12 | fun dpToPx(dp:Float)=TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,Resources.getSystem().displayMetrics).toInt()
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo
2 |
3 | import android.content.Intent
4 | import android.os.Bundle
5 | import androidx.appcompat.app.AppCompatActivity
6 | import androidx.recyclerview.widget.RecyclerView
7 | import androidx.recyclerview.widget.StaggeredGridLayoutManager
8 | import com.zyyoona7.demo.activity.*
9 | import com.zyyoona7.demo.adapter.MainAdapter
10 | import com.zyyoona7.itemdecoration.RecyclerViewDivider
11 |
12 | class MainActivity : AppCompatActivity() {
13 |
14 | override fun onCreate(savedInstanceState: Bundle?) {
15 | super.onCreate(savedInstanceState)
16 | setContentView(R.layout.activity_main)
17 |
18 | val mainRv = findViewById(R.id.rv_main)
19 |
20 | mainRv.layoutManager =
21 | androidx.recyclerview.widget.StaggeredGridLayoutManager(
22 | 2,
23 | androidx.recyclerview.widget.StaggeredGridLayoutManager.VERTICAL
24 | )
25 | val adapter = MainAdapter()
26 | mainRv.adapter = adapter
27 |
28 | RecyclerViewDivider.staggeredGrid()
29 | .includeEdge()
30 | .includeStartEdge()
31 | .spacingSize(dpToPx(10f))
32 | .build()
33 | .addTo(mainRv)
34 |
35 | adapter.setNewData(createData())
36 |
37 | adapter.setOnItemClickListener { adapter, view, position ->
38 | run {
39 | when (position) {
40 | 0 -> start(VerticalLinearActivity::class.java)
41 | 1 -> start(VerticalSectionLinearActivity::class.java)
42 | 2 -> start(HorizontalLinearActivity::class.java)
43 | 3 -> start(HorizontalSectionLinearActivity::class.java)
44 | 4 -> start(VerticalGridActivity::class.java)
45 | 5 -> start(VerticalSectionGridActivity::class.java)
46 | 6 -> start(HorizontalGridActivity::class.java)
47 | 7 -> start(HorizontalSectionGridActivity::class.java)
48 | 8 -> start(VerticalStaggeredGridActivity::class.java)
49 | 9 -> start(HorizontalStaggeredGridActivity::class.java)
50 | else -> {
51 | start(VerticalLinearActivity::class.java)
52 | }
53 | }
54 | }
55 | }
56 | }
57 |
58 | private fun start(actyClass: Class) {
59 | startActivity(Intent(this, actyClass))
60 | }
61 |
62 | private fun createData(): List {
63 | val list = arrayListOf()
64 | list.add("Vertical Linear")
65 | list.add("Vertical Linear with section")
66 | list.add("Horizontal Linear")
67 | list.add("Horizontal Linear with section")
68 | list.add("Vertical Grid")
69 | list.add("Vertical Grid with section")
70 | list.add("Horizontal Grid")
71 | list.add("Horizontal Grid with section")
72 | list.add("Vertical Staggered Grid")
73 | list.add("Horizontal Staggered Grid")
74 | return list
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/SectionData.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo
2 |
3 | import com.chad.library.adapter.base.entity.SectionEntity
4 |
5 | /**
6 | * @author zyyoona7
7 | * @version v1.0
8 | * @since 2018/12/17.
9 | */
10 | class SectionData : SectionEntity {
11 |
12 | var text: String? = null
13 |
14 | constructor(isHeader: Boolean, header: String) : super(isHeader, header) {}
15 |
16 | constructor(isHeader: Boolean, header: String, text: String) : super(isHeader, header) {
17 | this.text = text
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/activity/BaseActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.activity
2 |
3 | import android.os.Bundle
4 | import androidx.annotation.LayoutRes
5 | import androidx.appcompat.app.AppCompatActivity
6 | import androidx.recyclerview.widget.RecyclerView
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import com.chad.library.adapter.base.BaseViewHolder
10 | import com.zyyoona7.demo.R
11 |
12 | /**
13 | * @author zyyoona7
14 | * @version v1.0
15 | * @since 2018/12/27.
16 | */
17 | abstract class BaseActivity : AppCompatActivity() {
18 |
19 | override fun onCreate(savedInstanceState: Bundle?) {
20 | super.onCreate(savedInstanceState)
21 | setContentView(R.layout.activity_base)
22 |
23 | val recyclerView = findViewById(R.id.rv_base)
24 | recyclerView.layoutManager = createLayoutManager()
25 |
26 | val adapter = createAdapter()
27 | recyclerView.adapter = adapter
28 | addHeaderFooter(adapter)
29 |
30 | initItemDecoration(recyclerView,adapter)
31 |
32 | initData(adapter)
33 | }
34 |
35 | abstract fun createLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager
36 |
37 | abstract fun createAdapter(): androidx.recyclerview.widget.RecyclerView.Adapter
38 |
39 | abstract fun addHeaderFooter(adapter: androidx.recyclerview.widget.RecyclerView.Adapter)
40 |
41 | abstract fun initItemDecoration(recyclerView: androidx.recyclerview.widget.RecyclerView, adapter: androidx.recyclerview.widget.RecyclerView.Adapter)
42 |
43 | abstract fun initData(adapter: androidx.recyclerview.widget.RecyclerView.Adapter)
44 |
45 | fun getView(@LayoutRes layoutRes:Int):View{
46 | return LayoutInflater.from(this).inflate(layoutRes,null)
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/activity/HorizontalGridActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.activity
2 |
3 | import android.graphics.Color
4 | import androidx.recyclerview.widget.GridLayoutManager
5 | import androidx.recyclerview.widget.RecyclerView
6 | import android.widget.LinearLayout
7 | import com.chad.library.adapter.base.BaseQuickAdapter
8 | import com.chad.library.adapter.base.BaseViewHolder
9 | import com.zyyoona7.demo.DataServer
10 | import com.zyyoona7.demo.R
11 | import com.zyyoona7.demo.adapter.HorizontalDataAdapter
12 | import com.zyyoona7.demo.dpToPx
13 | import com.zyyoona7.itemdecoration.RecyclerViewDivider
14 |
15 | class HorizontalGridActivity : BaseActivity() {
16 |
17 | override fun createLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager {
18 | return androidx.recyclerview.widget.GridLayoutManager(
19 | this,
20 | 3,
21 | androidx.recyclerview.widget.GridLayoutManager.HORIZONTAL,
22 | false
23 | )
24 | }
25 |
26 | override fun createAdapter(): androidx.recyclerview.widget.RecyclerView.Adapter {
27 | return HorizontalDataAdapter()
28 | }
29 |
30 | override fun addHeaderFooter(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
31 | val quickAdapter = adapter as HorizontalDataAdapter
32 | quickAdapter.addHeaderView(getView(R.layout.item_hor_header),-1,LinearLayout.HORIZONTAL)
33 | // quickAdapter.addFooterView(getView(R.layout.item_hor_footer))
34 | }
35 |
36 | override fun initItemDecoration(recyclerView: androidx.recyclerview.widget.RecyclerView, adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
37 | RecyclerViewDivider.grid()
38 | .color(Color.BLUE)
39 | // .includeEdge()
40 | .dividerSize(dpToPx(10f))
41 | // .hideLastDivider()
42 | .hideDividerForItemType(BaseQuickAdapter.HEADER_VIEW, BaseQuickAdapter.FOOTER_VIEW)
43 | .build()
44 | .addTo(recyclerView)
45 | }
46 |
47 | override fun initData(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
48 | val quickAdapter = adapter as HorizontalDataAdapter
49 | quickAdapter.setNewData(DataServer.createGridData(20))
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/activity/HorizontalLinearActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.activity
2 |
3 | import android.graphics.Color
4 | import androidx.recyclerview.widget.LinearLayoutManager
5 | import androidx.recyclerview.widget.RecyclerView
6 | import com.chad.library.adapter.base.BaseQuickAdapter
7 | import com.chad.library.adapter.base.BaseViewHolder
8 | import com.zyyoona7.demo.DataServer
9 | import com.zyyoona7.demo.R
10 | import com.zyyoona7.demo.adapter.HorizontalDataAdapter
11 | import com.zyyoona7.demo.dpToPx
12 | import com.zyyoona7.itemdecoration.RecyclerViewDivider
13 |
14 | class HorizontalLinearActivity : BaseActivity() {
15 |
16 | override fun createLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager {
17 | return androidx.recyclerview.widget.LinearLayoutManager(
18 | this,
19 | androidx.recyclerview.widget.LinearLayoutManager.HORIZONTAL,
20 | false
21 | )
22 | }
23 |
24 | override fun createAdapter(): androidx.recyclerview.widget.RecyclerView.Adapter {
25 | return HorizontalDataAdapter()
26 | }
27 |
28 | override fun addHeaderFooter(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
29 | val quickAdapter = adapter as HorizontalDataAdapter
30 | quickAdapter.addHeaderView(getView(R.layout.item_hor_header))
31 | quickAdapter.addFooterView(getView(R.layout.item_hor_footer))
32 | }
33 |
34 | override fun initItemDecoration(recyclerView: androidx.recyclerview.widget.RecyclerView, adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
35 | RecyclerViewDivider.linear()
36 | .color(Color.RED)
37 | .dividerSize(dpToPx(1f))
38 | .marginStart(dpToPx(20f))
39 | .hideDividerForItemType(BaseQuickAdapter.HEADER_VIEW)
40 | .hideAroundDividerForItemType(BaseQuickAdapter.FOOTER_VIEW)
41 | .build()
42 | .addTo(recyclerView)
43 | }
44 |
45 | override fun initData(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
46 | val quickAdapter = adapter as HorizontalDataAdapter
47 | quickAdapter.setNewData(DataServer.createLinearData(20))
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/activity/HorizontalSectionGridActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.activity
2 |
3 | import androidx.recyclerview.widget.GridLayoutManager
4 | import androidx.recyclerview.widget.RecyclerView
5 | import com.chad.library.adapter.base.BaseQuickAdapter
6 | import com.chad.library.adapter.base.BaseViewHolder
7 | import com.zyyoona7.demo.DataServer
8 | import com.zyyoona7.demo.R
9 | import com.zyyoona7.demo.adapter.HorizontalSectionAdapter
10 | import com.zyyoona7.demo.dpToPx
11 | import com.zyyoona7.itemdecoration.RecyclerViewDivider
12 |
13 | class HorizontalSectionGridActivity : BaseActivity() {
14 |
15 | override fun createLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager {
16 | return androidx.recyclerview.widget.GridLayoutManager(
17 | this,
18 | 2,
19 | androidx.recyclerview.widget.GridLayoutManager.HORIZONTAL,
20 | false
21 | )
22 | }
23 |
24 | override fun createAdapter(): androidx.recyclerview.widget.RecyclerView.Adapter {
25 | return HorizontalSectionAdapter()
26 | }
27 |
28 | override fun addHeaderFooter(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
29 | val sectionAdapter = adapter as HorizontalSectionAdapter
30 | sectionAdapter.addHeaderView(getView(R.layout.item_hor_header))
31 | sectionAdapter.addFooterView(getView(R.layout.item_hor_footer))
32 | }
33 |
34 | override fun initItemDecoration(recyclerView: androidx.recyclerview.widget.RecyclerView, adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
35 | RecyclerViewDivider.grid()
36 | .asSpace()
37 | .dividerSize(dpToPx(10f))
38 | .hideDividerForItemType(BaseQuickAdapter.HEADER_VIEW, BaseQuickAdapter.FOOTER_VIEW)
39 | .build()
40 | .addTo(recyclerView)
41 | }
42 |
43 | override fun initData(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
44 | val sectionAdapter = adapter as HorizontalSectionAdapter
45 | sectionAdapter.setNewData(DataServer.createSectionGridData(30))
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/activity/HorizontalSectionLinearActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.activity
2 |
3 | import android.graphics.Color
4 | import androidx.recyclerview.widget.LinearLayoutManager
5 | import androidx.recyclerview.widget.RecyclerView
6 | import com.chad.library.adapter.base.BaseQuickAdapter
7 | import com.chad.library.adapter.base.BaseViewHolder
8 | import com.zyyoona7.demo.DataServer
9 | import com.zyyoona7.demo.R
10 | import com.zyyoona7.demo.adapter.HorizontalSectionAdapter
11 | import com.zyyoona7.demo.dpToPx
12 | import com.zyyoona7.itemdecoration.RecyclerViewDivider
13 |
14 | class HorizontalSectionLinearActivity : BaseActivity() {
15 |
16 | override fun createLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager {
17 | return androidx.recyclerview.widget.LinearLayoutManager(
18 | this,
19 | androidx.recyclerview.widget.LinearLayoutManager.HORIZONTAL,
20 | false
21 | )
22 | }
23 |
24 | override fun createAdapter(): androidx.recyclerview.widget.RecyclerView.Adapter {
25 | return HorizontalSectionAdapter()
26 | }
27 |
28 | override fun addHeaderFooter(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
29 | val sectionAdapter = adapter as HorizontalSectionAdapter
30 | sectionAdapter.addHeaderView(getView(R.layout.item_hor_header))
31 | sectionAdapter.addFooterView(getView(R.layout.item_hor_footer))
32 | }
33 |
34 | override fun initItemDecoration(recyclerView: androidx.recyclerview.widget.RecyclerView, adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
35 | val sectionAdapter = adapter as HorizontalSectionAdapter
36 | RecyclerViewDivider.linear()
37 | .color(Color.RED)
38 | .dividerSize(dpToPx(1f))
39 | .marginStart(dpToPx(20f))
40 | .hideDividerForItemType(BaseQuickAdapter.HEADER_VIEW)
41 | .hideAroundDividerForItemType(sectionAdapter.sectionItemType(), BaseQuickAdapter.FOOTER_VIEW)
42 | .build()
43 | .addTo(recyclerView)
44 | }
45 |
46 | override fun initData(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
47 | val sectionAdapter = adapter as HorizontalSectionAdapter
48 | sectionAdapter.setNewData(DataServer.createSectionLinearData(30))
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/activity/HorizontalStaggeredGridActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.activity
2 |
3 | import androidx.recyclerview.widget.RecyclerView
4 | import androidx.recyclerview.widget.StaggeredGridLayoutManager
5 | import com.chad.library.adapter.base.BaseViewHolder
6 | import com.zyyoona7.demo.R
7 | import com.zyyoona7.demo.adapter.HorizontalDataAdapter
8 | import com.zyyoona7.demo.dpToPx
9 | import com.zyyoona7.itemdecoration.RecyclerViewDivider
10 |
11 | class HorizontalStaggeredGridActivity : BaseActivity() {
12 |
13 | override fun createLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager {
14 | return androidx.recyclerview.widget.StaggeredGridLayoutManager(
15 | 2,
16 | androidx.recyclerview.widget.StaggeredGridLayoutManager.HORIZONTAL
17 | )
18 | }
19 |
20 | override fun createAdapter(): androidx.recyclerview.widget.RecyclerView.Adapter {
21 | return HorizontalDataAdapter()
22 | }
23 |
24 | override fun addHeaderFooter(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
25 | val quickAdapter = adapter as HorizontalDataAdapter
26 | quickAdapter.addHeaderView(getView(R.layout.item_ver_header))
27 | quickAdapter.addFooterView(getView(R.layout.item_ver_footer))
28 | }
29 |
30 | override fun initItemDecoration(recyclerView: androidx.recyclerview.widget.RecyclerView, adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
31 | RecyclerViewDivider.staggeredGrid()
32 | .spacingSize(dpToPx(10f))
33 | .includeEdge()
34 | .build()
35 | .addTo(recyclerView)
36 | }
37 |
38 | override fun initData(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
39 | val quickAdapter = adapter as HorizontalDataAdapter
40 | val list = arrayListOf()
41 | for (i in 0 until 5) {
42 | list.add("vertical")
43 | list.add("vertical staggered grid")
44 | list.add("vertical staggered")
45 | list.add("vertical staggered grid layout manager show. woo~~~")
46 | list.add("vertical staggered grid layout manager")
47 | list.add("vertical staggered grid layout manager show.")
48 | }
49 | quickAdapter.setNewData(list)
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/activity/VerticalGridActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.activity
2 |
3 | import android.graphics.Color
4 | import androidx.recyclerview.widget.GridLayoutManager
5 | import androidx.recyclerview.widget.RecyclerView
6 | import com.chad.library.adapter.base.BaseQuickAdapter
7 | import com.chad.library.adapter.base.BaseViewHolder
8 | import com.zyyoona7.demo.DataServer
9 | import com.zyyoona7.demo.R
10 | import com.zyyoona7.demo.adapter.DataAdapter
11 | import com.zyyoona7.demo.dpToPx
12 | import com.zyyoona7.itemdecoration.RecyclerViewDivider
13 |
14 | class VerticalGridActivity : BaseActivity() {
15 |
16 | override fun createLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager {
17 | return androidx.recyclerview.widget.GridLayoutManager(this, 4)
18 | }
19 |
20 | override fun createAdapter(): androidx.recyclerview.widget.RecyclerView.Adapter {
21 | return DataAdapter()
22 | }
23 |
24 | override fun addHeaderFooter(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
25 | val quickAdapter = adapter as DataAdapter
26 | quickAdapter.addHeaderView(getView(R.layout.item_ver_header))
27 | // quickAdapter.addFooterView(getView(R.layout.item_ver_footer))
28 | }
29 |
30 | override fun initItemDecoration(recyclerView: androidx.recyclerview.widget.RecyclerView, adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
31 | RecyclerViewDivider.grid()
32 | .color(Color.BLUE)
33 | .dividerSize(dpToPx(10f))
34 | // .includeEdge()
35 | // .hideLastDivider()
36 | .hideDividerForItemType(BaseQuickAdapter.HEADER_VIEW, BaseQuickAdapter.FOOTER_VIEW)
37 | .build()
38 | .addTo(recyclerView)
39 | }
40 |
41 | override fun initData(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
42 | val quickAdapter = adapter as DataAdapter
43 | // quickAdapter.setSpanSizeLookup { gridLayoutManager, position ->
44 | // 2 }
45 | quickAdapter.setNewData(DataServer.createGridData(21))
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/activity/VerticalLinearActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.activity
2 |
3 | import android.graphics.Color
4 | import androidx.recyclerview.widget.LinearLayoutManager
5 | import androidx.recyclerview.widget.RecyclerView
6 | import com.chad.library.adapter.base.BaseQuickAdapter
7 | import com.chad.library.adapter.base.BaseViewHolder
8 | import com.zyyoona7.demo.DataServer
9 | import com.zyyoona7.demo.R
10 | import com.zyyoona7.demo.adapter.DataAdapter
11 | import com.zyyoona7.demo.dpToPx
12 | import com.zyyoona7.itemdecoration.RecyclerViewDivider
13 |
14 | class VerticalLinearActivity : BaseActivity() {
15 |
16 | override fun createLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager {
17 | return androidx.recyclerview.widget.LinearLayoutManager(this)
18 | }
19 |
20 | override fun createAdapter(): androidx.recyclerview.widget.RecyclerView.Adapter {
21 | return DataAdapter()
22 | }
23 |
24 | override fun addHeaderFooter(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
25 | val quickAdapter = adapter as DataAdapter
26 | quickAdapter.addHeaderView(getView(R.layout.item_ver_header))
27 | quickAdapter.addFooterView(getView(R.layout.item_ver_footer))
28 | }
29 |
30 | override fun initItemDecoration(recyclerView: androidx.recyclerview.widget.RecyclerView, adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
31 | RecyclerViewDivider.linear()
32 | .color(Color.RED)
33 | .dividerSize(dpToPx(1f))
34 | .marginStart(dpToPx(20f))
35 | .hideDividerForItemType(BaseQuickAdapter.HEADER_VIEW)
36 | .hideAroundDividerForItemType(BaseQuickAdapter.FOOTER_VIEW)
37 | .build()
38 | .addTo(recyclerView)
39 | }
40 |
41 | override fun initData(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
42 | val quickAdapter = adapter as DataAdapter
43 | quickAdapter.setNewData(DataServer.createLinearData(20))
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/activity/VerticalSectionGridActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.activity
2 |
3 | import androidx.recyclerview.widget.GridLayoutManager
4 | import androidx.recyclerview.widget.RecyclerView
5 | import com.chad.library.adapter.base.BaseQuickAdapter
6 | import com.chad.library.adapter.base.BaseViewHolder
7 | import com.zyyoona7.demo.DataServer
8 | import com.zyyoona7.demo.R
9 | import com.zyyoona7.demo.adapter.SectionAdapter
10 | import com.zyyoona7.demo.dpToPx
11 | import com.zyyoona7.itemdecoration.RecyclerViewDivider
12 |
13 | class VerticalSectionGridActivity : BaseActivity() {
14 |
15 | override fun createLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager {
16 | return androidx.recyclerview.widget.GridLayoutManager(this, 2)
17 | }
18 |
19 | override fun createAdapter(): androidx.recyclerview.widget.RecyclerView.Adapter {
20 | return SectionAdapter()
21 | }
22 |
23 | override fun addHeaderFooter(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
24 | val sectionAdapter=adapter as SectionAdapter
25 | sectionAdapter.addHeaderView(getView(R.layout.item_ver_header))
26 | sectionAdapter.addFooterView(getView(R.layout.item_ver_footer))
27 | }
28 |
29 | override fun initItemDecoration(recyclerView: androidx.recyclerview.widget.RecyclerView, adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
30 | RecyclerViewDivider.grid()
31 | .asSpace()
32 | .dividerSize(dpToPx(10f))
33 | .hideDividerForItemType(BaseQuickAdapter.HEADER_VIEW,BaseQuickAdapter.FOOTER_VIEW)
34 | .build()
35 | .addTo(recyclerView)
36 | }
37 |
38 | override fun initData(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
39 | val sectionAdapter=adapter as SectionAdapter
40 | sectionAdapter.setNewData(DataServer.createSectionGridData(30))
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/activity/VerticalSectionLinearActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.activity
2 |
3 | import android.graphics.Color
4 | import androidx.recyclerview.widget.LinearLayoutManager
5 | import androidx.recyclerview.widget.RecyclerView
6 | import com.chad.library.adapter.base.BaseQuickAdapter
7 | import com.chad.library.adapter.base.BaseViewHolder
8 | import com.zyyoona7.demo.DataServer
9 | import com.zyyoona7.demo.R
10 | import com.zyyoona7.demo.adapter.SectionAdapter
11 | import com.zyyoona7.demo.dpToPx
12 | import com.zyyoona7.itemdecoration.RecyclerViewDivider
13 |
14 | class VerticalSectionLinearActivity : BaseActivity() {
15 |
16 | override fun createLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager {
17 | return androidx.recyclerview.widget.LinearLayoutManager(this)
18 | }
19 |
20 | override fun createAdapter(): androidx.recyclerview.widget.RecyclerView.Adapter {
21 | return SectionAdapter()
22 | }
23 |
24 | override fun addHeaderFooter(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
25 | val sectionAdapter = adapter as SectionAdapter
26 | sectionAdapter.addHeaderView(getView(R.layout.item_ver_header))
27 | sectionAdapter.addFooterView(getView(R.layout.item_ver_footer))
28 | }
29 |
30 | override fun initItemDecoration(recyclerView: androidx.recyclerview.widget.RecyclerView, adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
31 | val sectionAdapter = adapter as SectionAdapter
32 | RecyclerViewDivider.linear()
33 | .color(Color.RED)
34 | .dividerSize(dpToPx(1f))
35 | .marginStart(dpToPx(20f))
36 | .hideDividerForItemType(BaseQuickAdapter.HEADER_VIEW)
37 | .hideAroundDividerForItemType(sectionAdapter.sectionItemType(),BaseQuickAdapter.FOOTER_VIEW)
38 | .build()
39 | .addTo(recyclerView)
40 | }
41 |
42 | override fun initData(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
43 | val sectionAdapter = adapter as SectionAdapter
44 | sectionAdapter.setNewData(DataServer.createSectionLinearData(30))
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/activity/VerticalStaggeredGridActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.activity
2 |
3 | import androidx.recyclerview.widget.RecyclerView
4 | import androidx.recyclerview.widget.StaggeredGridLayoutManager
5 | import com.chad.library.adapter.base.BaseViewHolder
6 | import com.zyyoona7.demo.R
7 | import com.zyyoona7.demo.adapter.DataAdapter
8 | import com.zyyoona7.demo.dpToPx
9 | import com.zyyoona7.itemdecoration.RecyclerViewDivider
10 |
11 | class VerticalStaggeredGridActivity : BaseActivity() {
12 |
13 | override fun createLayoutManager(): androidx.recyclerview.widget.RecyclerView.LayoutManager {
14 | return androidx.recyclerview.widget.StaggeredGridLayoutManager(
15 | 2,
16 | androidx.recyclerview.widget.StaggeredGridLayoutManager.VERTICAL
17 | )
18 | }
19 |
20 | override fun createAdapter(): androidx.recyclerview.widget.RecyclerView.Adapter {
21 | return DataAdapter()
22 | }
23 |
24 | override fun addHeaderFooter(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
25 | val quickAdapter = adapter as DataAdapter
26 | quickAdapter.addHeaderView(getView(R.layout.item_ver_header))
27 | quickAdapter.addFooterView(getView(R.layout.item_ver_footer))
28 | }
29 |
30 | override fun initItemDecoration(recyclerView: androidx.recyclerview.widget.RecyclerView, adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
31 | RecyclerViewDivider.staggeredGrid()
32 | .spacingSize(dpToPx(10f))
33 | .includeEdge()
34 | .build()
35 | .addTo(recyclerView)
36 | }
37 |
38 | override fun initData(adapter: androidx.recyclerview.widget.RecyclerView.Adapter) {
39 | val quickAdapter = adapter as DataAdapter
40 | val list= arrayListOf()
41 | for (i in 0 until 5){
42 | list.add("vertical")
43 | list.add("vertical staggered grid")
44 | list.add("vertical staggered")
45 | list.add("vertical staggered grid layout manager show. woo~~~")
46 | list.add("vertical staggered grid layout manager")
47 | list.add("vertical staggered grid layout manager show.")
48 | }
49 | quickAdapter.setNewData(list)
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/adapter/DataAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.adapter
2 |
3 | import com.chad.library.adapter.base.BaseQuickAdapter
4 | import com.chad.library.adapter.base.BaseViewHolder
5 | import com.zyyoona7.demo.R
6 |
7 | /**
8 | * @author zyyoona7
9 | * @version v1.0
10 | * @since 2018/12/13.
11 | */
12 | class DataAdapter :BaseQuickAdapter(R.layout.item_data,null) {
13 |
14 | override fun convert(helper: BaseViewHolder?, item: String?) {
15 | helper?.setText(R.id.tv_item_data,"${helper.adapterPosition}. $item")
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/adapter/HorizontalDataAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.adapter
2 |
3 | import com.chad.library.adapter.base.BaseQuickAdapter
4 | import com.chad.library.adapter.base.BaseViewHolder
5 | import com.zyyoona7.demo.R
6 |
7 | /**
8 | * @author zyyoona7
9 | * @version v1.0
10 | * @since 2018/12/13.
11 | */
12 | class HorizontalDataAdapter() :BaseQuickAdapter(R.layout.item_horizontal_data,null) {
13 |
14 | override fun convert(helper: BaseViewHolder?, item: String?) {
15 | helper?.setText(R.id.tv_item_data,item)
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/adapter/HorizontalSectionAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.adapter
2 |
3 | import com.chad.library.adapter.base.BaseSectionQuickAdapter
4 | import com.chad.library.adapter.base.BaseViewHolder
5 | import com.zyyoona7.demo.R
6 | import com.zyyoona7.demo.SectionData
7 |
8 | /**
9 | * @author zyyoona7
10 | * @version v1.0
11 | * @since 2018/12/17.
12 | */
13 | class HorizontalSectionAdapter :
14 | BaseSectionQuickAdapter(
15 | R.layout.item_horizontal_data,
16 | R.layout.item_hor_section_header, null) {
17 |
18 | override fun convertHead(helper: BaseViewHolder, item: SectionData) {
19 | helper.setText(R.id.tv_item_header_text, "S\ne\nc\nt\ni\no\nn\nH\ne\na\nd\ne\nr")
20 | }
21 |
22 | override fun convert(helper: BaseViewHolder, item: SectionData) {
23 | helper.setText(R.id.tv_item_data, item.text)
24 | }
25 |
26 | fun sectionItemType():Int{
27 | return SECTION_HEADER_VIEW
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/adapter/MainAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.adapter
2 |
3 | import com.chad.library.adapter.base.BaseQuickAdapter
4 | import com.chad.library.adapter.base.BaseViewHolder
5 | import com.zyyoona7.demo.R
6 |
7 | /**
8 | * @author zyyoona7
9 | * @version v1.0
10 | * @since 2018/12/27.
11 | */
12 | class MainAdapter:BaseQuickAdapter(R.layout.item_main,null){
13 |
14 |
15 | override fun convert(helper: BaseViewHolder?, item: String?) {
16 | helper?.setText(R.id.tv_item_data,"${helper.adapterPosition}. $item")
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/zyyoona7/demo/adapter/SectionAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.demo.adapter
2 |
3 | import com.chad.library.adapter.base.BaseSectionQuickAdapter
4 | import com.chad.library.adapter.base.BaseViewHolder
5 | import com.zyyoona7.demo.R
6 | import com.zyyoona7.demo.SectionData
7 |
8 | /**
9 | * @author zyyoona7
10 | * @version v1.0
11 | * @since 2018/12/17.
12 | */
13 | class SectionAdapter :
14 | BaseSectionQuickAdapter(
15 | R.layout.item_data,
16 | R.layout.item_section_header, null) {
17 |
18 | override fun convertHead(helper: BaseViewHolder, item: SectionData) {
19 | helper.setText(R.id.tv_item_header_text, item.header)
20 | }
21 |
22 | override fun convert(helper: BaseViewHolder, item: SectionData) {
23 | helper.setText(R.id.tv_item_data, item.text)
24 | }
25 |
26 | fun sectionItemType():Int{
27 | return SECTION_HEADER_VIEW
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
12 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_base.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_data.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_hor_footer.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_hor_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_hor_section_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_horizontal_data.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_section_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_ver_footer.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_ver_header.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | RecyclerViewItemDecoration
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.72'
5 | repositories {
6 | mavenCentral()
7 | google()
8 | maven { url "https://jitpack.io" }
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.6.4'
12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | mavenCentral()
21 | google()
22 | maven { url "https://jitpack.io" }
23 | }
24 | }
25 |
26 | task clean(type: Delete) {
27 | delete rootProject.buildDir
28 | }
29 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # Kotlin code style for this project: "official" or "obsolete":
15 | kotlin.code.style=official
16 | android.useAndroidX=true
17 | android.enableJetifier=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Jun 11 12:55:23 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/itemdecoration/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/itemdecoration/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 | apply plugin: 'maven-publish'
5 |
6 | android {
7 | compileSdkVersion 28
8 |
9 | defaultConfig {
10 | minSdkVersion 16
11 | targetSdkVersion 28
12 | versionCode 4
13 | versionName "1.0.3"
14 | }
15 |
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 |
23 | }
24 |
25 | dependencies {
26 | compileOnly fileTree(dir: 'libs', include: ['*.jar'])
27 | compileOnly 'androidx.appcompat:appcompat:1.0.0'
28 | compileOnly 'androidx.recyclerview:recyclerview:1.0.0'
29 | compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
30 | }
31 | repositories {
32 | mavenCentral()
33 | }
34 |
35 | afterEvaluate {
36 | publishing {
37 | publications {
38 | // Creates a Maven publication called "release".
39 | release(MavenPublication) {
40 | // Applies the component for the release build variant.
41 | from components.release
42 |
43 | // You can then customize attributes of the publication as shown below.
44 | groupId = 'com.github.zyyoona7'
45 | artifactId = 'recyclerviewdivider'
46 | version = '1.0.3'
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/itemdecoration/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/itemdecoration/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/itemdecoration/src/main/java/com/zyyoona7/itemdecoration/RecyclerViewDivider.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.itemdecoration
2 |
3 | import androidx.recyclerview.widget.RecyclerView
4 | import com.zyyoona7.itemdecoration.provider.GridItemDecoration
5 | import com.zyyoona7.itemdecoration.provider.LinearItemDecoration
6 | import com.zyyoona7.itemdecoration.provider.StaggeredGridItemDecoration
7 |
8 | /**
9 | * @author zyyoona7
10 | * @version v1.0
11 | * @since 2018/12/12.
12 | */
13 | class RecyclerViewDivider : RecyclerView.ItemDecoration() {
14 |
15 | companion object {
16 |
17 | @JvmStatic
18 | fun linear() = LinearItemDecoration.Builder()
19 |
20 | @JvmStatic
21 | fun grid() = GridItemDecoration.Builder()
22 |
23 | @JvmStatic
24 | fun staggeredGrid() = StaggeredGridItemDecoration.Builder()
25 | }
26 | }
--------------------------------------------------------------------------------
/itemdecoration/src/main/java/com/zyyoona7/itemdecoration/ext/Extentions.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.itemdecoration.ext
2 |
3 | import androidx.recyclerview.widget.GridLayoutManager
4 | import androidx.recyclerview.widget.RecyclerView
5 |
6 | /**
7 | * @author zyyoona7
8 | * @version v1.0
9 | * @since 2018/12/13.
10 | */
11 | internal fun androidx.recyclerview.widget.RecyclerView.itemCount(): Int {
12 | return this.adapter?.itemCount ?: 0
13 | }
14 |
15 | internal fun androidx.recyclerview.widget.RecyclerView.itemType(itemPosition: Int): Int {
16 | return this.adapter?.getItemViewType(itemPosition) ?: -1
17 | }
18 |
19 | internal fun androidx.recyclerview.widget.GridLayoutManager.spanSize(itemPosition: Int): Int {
20 | return this.spanSizeLookup.getSpanSize(itemPosition)
21 | }
22 |
23 | internal fun androidx.recyclerview.widget.GridLayoutManager.spanIndex(itemPosition: Int): Int {
24 | return this.spanSizeLookup.getSpanIndex(itemPosition, spanCount)
25 | }
--------------------------------------------------------------------------------
/itemdecoration/src/main/java/com/zyyoona7/itemdecoration/provider/GridItemDecoration.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.itemdecoration.provider
2 |
3 | import android.graphics.Canvas
4 | import android.graphics.Color
5 | import android.graphics.Rect
6 | import android.graphics.drawable.ColorDrawable
7 | import android.graphics.drawable.Drawable
8 | import androidx.annotation.ColorInt
9 | import androidx.annotation.Px
10 | import androidx.collection.ArraySet
11 | import androidx.recyclerview.widget.GridLayoutManager
12 | import androidx.recyclerview.widget.RecyclerView
13 | import android.view.View
14 | import com.zyyoona7.itemdecoration.ext.itemCount
15 | import com.zyyoona7.itemdecoration.ext.itemType
16 | import com.zyyoona7.itemdecoration.ext.spanIndex
17 | import com.zyyoona7.itemdecoration.ext.spanSize
18 |
19 | /**
20 | * @author zyyoona7
21 | * @version v1.0
22 | * @since 2018/12/13.
23 | */
24 | class GridItemDecoration internal constructor(builder: Builder) : RecyclerView.ItemDecoration() {
25 |
26 | private val isSpace: Boolean = builder.isSpace
27 | private val divider: Drawable = builder.divider
28 | private val dividerSize: Int = builder.dividerSize
29 | //有无边界
30 | private val isIncludeEdge: Boolean = builder.isIncludeEdge
31 | //hide divider only work spanSize==spanCount itemType
32 | private val hideDividerItemTypeSet = builder.hideDividerItemTypeSet
33 |
34 | /**
35 | * add item decoration to [recyclerView]
36 | */
37 | fun addTo(recyclerView: RecyclerView) {
38 | removeFrom(recyclerView)
39 | recyclerView.addItemDecoration(this)
40 | }
41 |
42 | /**
43 | * remove item decoration from [recyclerView]
44 | */
45 | fun removeFrom(recyclerView: RecyclerView) {
46 | recyclerView.removeItemDecoration(this)
47 | }
48 |
49 | /**
50 | * 计算空隙
51 | */
52 | override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView,
53 | state: RecyclerView.State) {
54 |
55 | super.getItemOffsets(outRect, view, parent, state)
56 |
57 | val itemCount = parent.itemCount()
58 | if (itemCount == 0) {
59 | return
60 | }
61 |
62 | val itemPosition = parent.getChildAdapterPosition(view)
63 | if (itemPosition == RecyclerView.NO_POSITION) {
64 | return
65 | }
66 |
67 | val layoutManager = parent.layoutManager as? GridLayoutManager
68 | ?: return
69 |
70 | val spanCount = layoutManager.spanCount
71 | val spanIndex = layoutManager.spanIndex(itemPosition)
72 | val spanSize = layoutManager.spanSize(itemPosition)
73 |
74 | val verticalSize = calculateVerticalDividerSize()
75 | val horizontalSize = calculateHorizontalDividerSize()
76 |
77 | if (layoutManager.orientation == RecyclerView.VERTICAL) {
78 | //如果出现小数的话,可能会出现微小的偏差
79 | val realHorizontalSize =
80 | if (horizontalSize % spanCount == 0) horizontalSize else horizontalSize / spanCount * spanCount
81 | val eachItemHorDividerSize =
82 | if (spanSize == spanCount) (if (isIncludeEdge) 2 * realHorizontalSize else 0)
83 | else ((spanCount + if (isIncludeEdge) 1 else -1) * realHorizontalSize / spanCount)
84 | if (isIncludeEdge) {
85 | outRect.left =
86 | (spanIndex + 1) * realHorizontalSize - spanIndex * eachItemHorDividerSize
87 | outRect.right = eachItemHorDividerSize - outRect.left
88 | outRect.top = if (spanIndex == itemPosition) verticalSize else 0
89 | if (spanSize == spanCount && isHideItemType(itemPosition, parent)) {
90 | outRect.bottom = 0
91 | } else {
92 | outRect.bottom = verticalSize
93 | }
94 | } else {
95 | outRect.left = spanIndex * (realHorizontalSize - eachItemHorDividerSize)
96 | outRect.right = eachItemHorDividerSize - outRect.left
97 | outRect.top = 0
98 | if (spanSize == spanCount && isHideItemType(itemPosition, parent)) {
99 | outRect.bottom = 0
100 | } else {
101 | outRect.bottom =
102 | if (isInLastRowOrColumn(itemPosition, itemCount, spanCount, layoutManager))
103 | 0 else verticalSize
104 | }
105 | }
106 |
107 | } else {
108 | //如果出现小数的话,可能会出现微小的偏差
109 | val realVerticalSize =
110 | if (verticalSize % spanCount == 0) verticalSize else verticalSize / spanCount * spanCount
111 | val eachItemHorDividerSize =
112 | if (spanSize == spanCount) (if (isIncludeEdge) 2 * realVerticalSize else 0)
113 | else ((spanCount + if (isIncludeEdge) 1 else -1) * realVerticalSize / spanCount)
114 | if (isIncludeEdge) {
115 | outRect.top =
116 | (spanIndex + 1) * realVerticalSize - spanIndex * eachItemHorDividerSize
117 | outRect.bottom = eachItemHorDividerSize - outRect.top
118 | outRect.left = if (spanIndex == itemPosition) horizontalSize else 0
119 | if (spanSize == spanCount && isHideItemType(itemPosition, parent)) {
120 | outRect.right = 0
121 | } else {
122 | outRect.right = horizontalSize
123 | }
124 | } else {
125 | outRect.top = spanIndex * (realVerticalSize - eachItemHorDividerSize)
126 | outRect.bottom = eachItemHorDividerSize - outRect.top
127 | outRect.left = 0
128 | if (spanSize == spanCount && isHideItemType(itemPosition, parent)) {
129 | outRect.right = 0
130 | } else {
131 | outRect.right =
132 | if (isInLastRowOrColumn(itemPosition, itemCount, spanCount, layoutManager))
133 | 0 else horizontalSize
134 | }
135 | }
136 | }
137 | }
138 |
139 | /**
140 | * 绘制,根据 item 绘制
141 | */
142 | override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
143 | super.onDraw(c, parent, state)
144 |
145 | val itemCount = parent.itemCount()
146 | if (isSpace || itemCount == 0) {
147 | return
148 | }
149 |
150 | val layoutManager = parent.layoutManager as? GridLayoutManager
151 | ?: return
152 |
153 | val spanCount = layoutManager.spanCount
154 | val verticalSize = calculateVerticalDividerSize()
155 | val horizontalSize = calculateHorizontalDividerSize()
156 | val isVertical=layoutManager.orientation== GridLayoutManager.VERTICAL
157 |
158 | val realHorizontalSize = if (isVertical)
159 | (if (horizontalSize % spanCount == 0) horizontalSize else horizontalSize / spanCount * spanCount)
160 | else horizontalSize
161 | val realVerticalSize = if (!isVertical)
162 | (if (verticalSize % spanCount == 0) verticalSize else verticalSize / spanCount * spanCount)
163 | else verticalSize
164 |
165 | val childCount = parent.childCount
166 | for (i in 0 until childCount) {
167 | val childView = parent.getChildAt(i)
168 | val itemPosition = parent.getChildAdapterPosition(childView)
169 | if (itemPosition == RecyclerView.NO_POSITION) {
170 | return
171 | }
172 | val spanIndex = layoutManager.spanIndex(itemPosition)
173 | val spanSize = layoutManager.spanSize(itemPosition)
174 |
175 | val params = childView.layoutParams as RecyclerView.LayoutParams
176 |
177 | val bLeft: Int = childView.left - params.leftMargin -
178 | (if (isIncludeEdge && spanIndex == 0 && isVertical) realHorizontalSize else 0)
179 | //bottom divider 补齐空缺位置,如果不加 item 对角间会有空隙
180 | //垂直方向时,底部 divider 的补位宽度
181 | val verticalBRight=if (!isIncludeEdge&&spanIndex+spanSize==spanCount) 0 else realHorizontalSize
182 | //水平方向时,底部 divider 的补位宽度
183 | val horizontalBRight=if (!isIncludeEdge&&isInLastRowOrColumn(itemPosition, itemCount, spanCount, layoutManager))
184 | 0 else realHorizontalSize
185 | val bRight = childView.right + params.rightMargin +(if (isVertical) verticalBRight else horizontalBRight)
186 | val rTop = childView.top - params.topMargin -
187 | (if (isIncludeEdge && spanIndex == 0 && !isVertical) realVerticalSize else 0)
188 | val rBottom = childView.bottom + params.bottomMargin
189 |
190 | val bTop: Int = childView.bottom + params.bottomMargin
191 | val bBottom: Int = bTop + realVerticalSize
192 | val rLeft: Int = childView.right + params.rightMargin
193 | val rRight: Int = rLeft + realHorizontalSize
194 |
195 | val isNotDrawEnd=spanIndex+spanSize==spanCount && !isIncludeEdge
196 | val isNotDrawLastItem=isInLastRowOrColumn(itemPosition, itemCount, spanCount, layoutManager)
197 | && !isIncludeEdge
198 | val isNotDrawHideItem = spanSize == spanCount && isHideItemType(itemPosition, parent)
199 | //draw bottom divider
200 | if (!(isNotDrawHideItem && isVertical)
201 | && !(isNotDrawEnd && !isVertical)
202 | && !(isNotDrawLastItem && isVertical)) {
203 | divider.setBounds(bLeft, bTop, bRight, bBottom)
204 | divider.draw(c)
205 | }
206 |
207 | //draw right divider
208 | if (!(isNotDrawHideItem && !isVertical)
209 | && !(isNotDrawEnd && isVertical)
210 | && !(isNotDrawLastItem && !isVertical)) {
211 | divider.setBounds(rLeft, rTop, rRight, rBottom)
212 | divider.draw(c)
213 | }
214 |
215 | if (isVertical) {
216 | if (isIncludeEdge && spanIndex == 0) {
217 | val lLeft = childView.left - params.leftMargin - realHorizontalSize
218 | val lRight = childView.left - params.leftMargin
219 | val lTop = childView.top - params.topMargin
220 | val lBottom = childView.bottom + params.bottomMargin
221 | divider.setBounds(lLeft, lTop, lRight, lBottom)
222 | divider.draw(c)
223 | }
224 | if (isIncludeEdge && spanIndex == itemPosition) {
225 | val tLeft = childView.left - params.leftMargin -
226 | (if (spanIndex == 0) realHorizontalSize else 0)
227 | val tRight = childView.right + params.rightMargin + realHorizontalSize
228 | val tTop = childView.top - params.topMargin - realVerticalSize
229 | val tBottom = childView.top - params.topMargin
230 | divider.setBounds(tLeft, tTop, tRight, tBottom)
231 | divider.draw(c)
232 | }
233 | } else {
234 | if (isIncludeEdge && spanIndex == 0) {
235 | val tLeft = childView.left - params.leftMargin - realHorizontalSize
236 | val tRight = childView.right + params.rightMargin + realHorizontalSize
237 | val tTop = childView.top - params.topMargin - realVerticalSize
238 | val tBottom = tTop + realVerticalSize
239 | divider.setBounds(tLeft, tTop, tRight, tBottom)
240 | divider.draw(c)
241 | }
242 |
243 | if (isIncludeEdge && spanIndex == itemPosition) {
244 | val lLeft = childView.left - params.leftMargin - realHorizontalSize
245 | val lRight = childView.left - params.leftMargin
246 | val lTop = childView.top - params.topMargin
247 | val lBottom = childView.bottom + params.bottomMargin+realVerticalSize
248 |
249 | divider.setBounds(lLeft, lTop, lRight, lBottom)
250 | divider.draw(c)
251 | }
252 | }
253 |
254 | }
255 | }
256 |
257 | /**
258 | * [divider] type calculate vertical size
259 | */
260 | private fun calculateVerticalDividerSize(): Int {
261 | return if (divider is ColorDrawable) dividerSize else divider.intrinsicHeight
262 | }
263 |
264 | /**
265 | * [divider] type calculate horizontal size
266 | */
267 | private fun calculateHorizontalDividerSize(): Int {
268 | return if (divider is ColorDrawable) dividerSize else divider.intrinsicWidth
269 | }
270 |
271 | /**
272 | * [itemPosition] is the hide end divider itemType
273 | */
274 | private fun isHideItemType(itemPosition: Int, parent: RecyclerView): Boolean {
275 | val itemType = parent.itemType(itemPosition)
276 | return hideDividerItemTypeSet.contains(itemType)
277 | }
278 |
279 | /**
280 | * [itemPosition] is in last row for Vertical or last column for Horizontal
281 | */
282 | private fun isInLastRowOrColumn(itemPosition: Int, itemCount: Int, spanCount: Int,
283 | layoutManager: GridLayoutManager
284 | ): Boolean {
285 | val lastPosition = itemCount - 1
286 | if (itemPosition == lastPosition) {
287 | //最后一个 item 肯定在最后一行(列)
288 | return true
289 | }
290 | if (lastPosition - itemPosition < spanCount) {
291 | //有可能是最后一行的下标,候选
292 | //上一行(列)的最后一个 position
293 | var beforeLastItemPosition: Int = -1
294 | for (i in lastPosition - 1 downTo lastPosition - spanCount) {
295 | //从倒数第二个开始到候选 item 的最后一个,
296 | // 如果这中间有上一行(列)的最后一个,则这个 item 包括它之前的 item 都不在最后一行
297 | val spanIndex = layoutManager.spanIndex(i)
298 | val spanSize = layoutManager.spanSize(i)
299 | if (spanIndex + spanSize == spanCount) {
300 | beforeLastItemPosition = i
301 | break
302 | }
303 | }
304 | return itemPosition > beforeLastItemPosition
305 | }
306 | return false
307 | }
308 |
309 | class Builder {
310 |
311 | internal var isSpace: Boolean = false
312 | internal var divider: Drawable = ColorDrawable(Color.TRANSPARENT)
313 | internal var dividerSize: Int = 0
314 | internal var isIncludeEdge: Boolean = false
315 | internal val hideDividerItemTypeSet: ArraySet = ArraySet(1)
316 |
317 | fun asSpace() = apply { isSpace = true }
318 |
319 | fun includeEdge() = apply { isIncludeEdge = true }
320 |
321 | fun color(@ColorInt color: Int) = apply { divider = ColorDrawable(color) }
322 |
323 | fun drawable(drawable: Drawable) = apply { divider = drawable }
324 |
325 | fun dividerSize(@Px size: Int) = apply { dividerSize = size }
326 |
327 | /**
328 | * hide end divider of [itemTypes]
329 | */
330 | fun hideDividerForItemType(vararg itemTypes: Int) = apply {
331 | if (itemTypes.isNotEmpty()) {
332 | itemTypes.forEach { hideDividerItemTypeSet.add(it) }
333 | }
334 | }
335 |
336 | fun build() = GridItemDecoration(this)
337 | }
338 | }
--------------------------------------------------------------------------------
/itemdecoration/src/main/java/com/zyyoona7/itemdecoration/provider/LinearItemDecoration.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.itemdecoration.provider
2 |
3 | import android.graphics.Canvas
4 | import android.graphics.Color
5 | import android.graphics.Rect
6 | import android.graphics.drawable.ColorDrawable
7 | import android.graphics.drawable.Drawable
8 | import android.view.View
9 | import androidx.annotation.ColorInt
10 | import androidx.annotation.Px
11 | import androidx.collection.ArraySet
12 | import androidx.recyclerview.widget.LinearLayoutManager
13 | import androidx.recyclerview.widget.RecyclerView
14 | import com.zyyoona7.itemdecoration.ext.itemCount
15 | import com.zyyoona7.itemdecoration.ext.itemType
16 |
17 | /**
18 | * @author zyyoona7
19 | * @version v1.0
20 | * @since 2018/12/13.
21 | */
22 | class LinearItemDecoration internal constructor(builder: Builder) :RecyclerView.ItemDecoration() {
23 |
24 | private val isSpace: Boolean = builder.isSpace
25 | private val isHideLastDivider: Boolean = builder.isHideLastDivider
26 | private val divider: Drawable = builder.divider
27 | private val dividerSize: Int = builder.dividerSize
28 | private val marginStart: Int = builder.marginStart
29 | private val marginEnd: Int = builder.marginEnd
30 | private val hideDividerItemTypeSet: ArraySet = builder.hideDividerItemTypeSet
31 | private val hideAroundDividerItemTypeSet: ArraySet = builder.hideAroundDividerItemTypeSet
32 |
33 | /**
34 | * add item decoration to [recyclerView]
35 | */
36 | fun addTo(recyclerView:RecyclerView) {
37 | removeFrom(recyclerView)
38 | recyclerView.addItemDecoration(this)
39 | }
40 |
41 | /**
42 | * remove item decoration from [recyclerView]
43 | */
44 | fun removeFrom(recyclerView:RecyclerView) {
45 | recyclerView.removeItemDecoration(this)
46 | }
47 |
48 | override fun getItemOffsets(outRect: Rect, view: View, parent:RecyclerView, state:RecyclerView.State) {
49 | super.getItemOffsets(outRect, view, parent, state)
50 | val itemCount = parent.itemCount()
51 | if (itemCount == 0) {
52 | return
53 | }
54 |
55 | val itemPosition = parent.getChildAdapterPosition(view)
56 | if (itemPosition == RecyclerView.NO_POSITION) {
57 | return
58 | }
59 |
60 | val layoutManager = parent.layoutManager as? LinearLayoutManager
61 | ?: return
62 |
63 | val size = calculateDividerSize(layoutManager)
64 |
65 | if (layoutManager.orientation == RecyclerView.VERTICAL) {
66 | //LinearLayoutManager vertical
67 | if ((isHideLastDivider && isLastItem(itemPosition, itemCount))
68 | || nextIsHideItemType(itemPosition, itemCount, parent) || isHideItemType(itemPosition, parent)
69 | ) {
70 | outRect.setEmpty()
71 | } else {
72 | outRect.set(0, 0, 0, size)
73 | }
74 | } else {
75 | //LinearLayoutManager horizontal
76 | if ((isHideLastDivider && isLastItem(itemPosition, itemCount))
77 | || nextIsHideItemType(itemPosition, itemCount, parent) || isHideItemType(itemPosition, parent)
78 | ) {
79 | outRect.setEmpty()
80 | } else {
81 | outRect.set(0, 0, size, 0)
82 | }
83 | }
84 | }
85 |
86 | override fun onDraw(c: Canvas, parent:RecyclerView, state:RecyclerView.State) {
87 | super.onDraw(c, parent, state)
88 |
89 | val itemCount = parent.itemCount()
90 | if (isSpace || itemCount == 0) {
91 | return
92 | }
93 |
94 | val layoutManager = parent.layoutManager as?LinearLayoutManager
95 | ?: return
96 |
97 | if (layoutManager.orientation ==RecyclerView.VERTICAL) {
98 | //LinearLayoutManager vertical
99 | drawVertical(c, parent, layoutManager, itemCount)
100 | } else {
101 | drawHorizontal(c, parent, layoutManager, itemCount)
102 | }
103 | }
104 |
105 | private fun drawVertical(canvas: Canvas, parent:RecyclerView, layoutManager:LinearLayoutManager, itemCount: Int) {
106 |
107 | val left = parent.paddingLeft + marginStart
108 | val right = parent.width - parent.paddingRight - marginEnd
109 | val size = calculateDividerSize(layoutManager)
110 |
111 | val childCount = parent.childCount
112 | for (i in 0 until childCount) {
113 | val childView = parent.getChildAt(i)
114 | val itemPosition = parent.getChildAdapterPosition(childView)
115 | if (itemPosition ==RecyclerView.NO_POSITION) {
116 | return
117 | }
118 |
119 | if ((isHideLastDivider && isLastItem(itemPosition, itemCount))
120 | || nextIsHideItemType(itemPosition, itemCount, parent) || isHideItemType(itemPosition, parent)
121 | ) {
122 | continue
123 | }
124 |
125 | val params = childView.layoutParams as RecyclerView.LayoutParams
126 | val top = childView.bottom + params.bottomMargin
127 | val bottom = top + size
128 |
129 | divider.setBounds(left, top, right, bottom)
130 | divider.draw(canvas)
131 | }
132 | }
133 |
134 | private fun drawHorizontal(canvas: Canvas, parent:RecyclerView, layoutManager:LinearLayoutManager, itemCount: Int) {
135 |
136 | val top = parent.paddingTop + marginStart
137 | val bottom = parent.height - parent.paddingBottom - marginEnd
138 | val size = calculateDividerSize(layoutManager)
139 |
140 | val childCount = parent.childCount
141 | for (i in 0 until childCount) {
142 | val childView = parent.getChildAt(i)
143 | val itemPosition = parent.getChildAdapterPosition(childView)
144 | if (itemPosition ==RecyclerView.NO_POSITION) {
145 | return
146 | }
147 |
148 | if ((isHideLastDivider && isLastItem(itemPosition, itemCount))
149 | || nextIsHideItemType(itemPosition, itemCount, parent) || isHideItemType(itemPosition, parent)
150 | ) {
151 | continue
152 | }
153 |
154 | val params = childView.layoutParams as RecyclerView.LayoutParams
155 | val left = childView.right + params.rightMargin
156 | val right = left + size
157 |
158 | divider.setBounds(left, top, right, bottom)
159 | divider.draw(canvas)
160 | }
161 | }
162 |
163 | /**
164 | * [itemPosition] is last item
165 | */
166 | private fun isLastItem(itemPosition: Int, itemCount: Int): Boolean {
167 | return itemCount > 0 && itemPosition == itemCount - 1
168 | }
169 |
170 | /**
171 | * [itemPosition]+1 is the hide divider itemType
172 | */
173 | private fun nextIsHideItemType(itemPosition: Int, itemCount: Int, parent:RecyclerView): Boolean {
174 | return if (itemPosition + 1 < itemCount) hideAroundDividerItemTypeSet.contains(parent.itemType(itemPosition + 1)) else false
175 | }
176 |
177 | /**
178 | * [itemPosition] is the hide divider itemType
179 | */
180 | private fun isHideItemType(itemPosition: Int, parent:RecyclerView): Boolean {
181 | val itemType = parent.itemType(itemPosition)
182 | return hideAroundDividerItemTypeSet.contains(itemType) || hideDividerItemTypeSet.contains(itemType)
183 | }
184 |
185 | /**
186 | * [divider] type calculate size
187 | */
188 | private fun calculateDividerSize(layoutManager:LinearLayoutManager): Int {
189 | return if (layoutManager.orientation ==RecyclerView.VERTICAL) {
190 | if (divider is ColorDrawable) dividerSize else divider.intrinsicHeight
191 | } else {
192 | if (divider is ColorDrawable) dividerSize else divider.intrinsicWidth
193 | }
194 | }
195 |
196 | class Builder {
197 |
198 | internal var isSpace: Boolean = false
199 | internal var isHideLastDivider: Boolean = false
200 | internal var divider: Drawable = ColorDrawable(Color.TRANSPARENT)
201 | internal var dividerSize: Int = 0
202 | internal var marginStart: Int = 0
203 | internal var marginEnd: Int = 0
204 | internal val hideDividerItemTypeSet: ArraySet = ArraySet(1)
205 | internal val hideAroundDividerItemTypeSet: ArraySet = ArraySet(1)
206 |
207 | fun asSpace() = apply { isSpace = true }
208 |
209 | fun hideLastDivider() = apply { isHideLastDivider = true }
210 |
211 | fun color(@ColorInt color: Int) = apply { divider = ColorDrawable(color) }
212 |
213 | fun drawable(drawable: Drawable) = apply { divider = drawable }
214 |
215 | fun dividerSize(@Px size: Int) = apply { dividerSize = size }
216 |
217 | fun marginStart(@Px marginStart: Int) = apply { this.marginStart = marginStart }
218 |
219 | fun marginEnd(@Px marginEnd: Int) = apply { this.marginEnd = marginEnd }
220 |
221 | /**
222 | * hide divider of [itemTypes]
223 | */
224 | fun hideDividerForItemType(vararg itemTypes: Int) = apply {
225 | if (itemTypes.isNotEmpty()) {
226 | itemTypes.forEach { hideDividerItemTypeSet.add(it) }
227 | }
228 | }
229 |
230 | /**
231 | * hide current position divider and hide position-1 divider of [itemTypes]
232 | */
233 | fun hideAroundDividerForItemType(vararg itemTypes: Int) = apply {
234 | if (itemTypes.isNotEmpty()) {
235 | itemTypes.forEach { hideAroundDividerItemTypeSet.add(it) }
236 | }
237 | }
238 |
239 | fun build() = LinearItemDecoration(this)
240 | }
241 | }
--------------------------------------------------------------------------------
/itemdecoration/src/main/java/com/zyyoona7/itemdecoration/provider/StaggeredGridItemDecoration.kt:
--------------------------------------------------------------------------------
1 | package com.zyyoona7.itemdecoration.provider
2 |
3 | import android.graphics.Rect
4 | import androidx.annotation.Px
5 | import androidx.recyclerview.widget.RecyclerView
6 | import androidx.recyclerview.widget.StaggeredGridLayoutManager
7 | import android.view.View
8 | import com.zyyoona7.itemdecoration.ext.itemCount
9 |
10 | /**
11 | * @author zyyoona7
12 | * @version v1.0
13 | * @since 2018/12/13.
14 | */
15 | class StaggeredGridItemDecoration(builder: Builder) : RecyclerView.ItemDecoration() {
16 |
17 | private val spacingSize: Int = builder.spacingSize
18 | //orientation is Vertical,edge left right. Horizontal,edge top bottom
19 | private val isIncludeEdge: Boolean = builder.isIncludeEdge
20 | //orientation is Vertical,first row top. Horizontal,first column left
21 | private val isIncludeStartEdge: Boolean = builder.isIncludeStartEdge
22 |
23 | /**
24 | * add item decoration to [recyclerView]
25 | */
26 | fun addTo(recyclerView: RecyclerView) {
27 | removeFrom(recyclerView)
28 | recyclerView.addItemDecoration(this)
29 | }
30 |
31 | /**
32 | * remove item decoration from [recyclerView]
33 | */
34 | fun removeFrom(recyclerView: RecyclerView) {
35 | recyclerView.removeItemDecoration(this)
36 | }
37 |
38 | override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
39 | super.getItemOffsets(outRect, view, parent, state)
40 |
41 | val itemCount = parent.itemCount()
42 | if (itemCount == 0) {
43 | return
44 | }
45 |
46 | val itemPosition = parent.getChildAdapterPosition(view)
47 | if (itemPosition == RecyclerView.NO_POSITION) {
48 | return
49 | }
50 |
51 | val layoutManager = parent.layoutManager as? StaggeredGridLayoutManager
52 | ?: return
53 | val params = view.layoutParams as? StaggeredGridLayoutManager.LayoutParams ?: return
54 |
55 |
56 | if (layoutManager.orientation == RecyclerView.VERTICAL) {
57 | //orientation vertical
58 | itemOffsetsVertical(outRect, itemPosition, layoutManager, params)
59 | } else {
60 | //orientation horizontal
61 | itemOffsetsHorizontal(outRect, itemPosition, layoutManager, params)
62 | }
63 | }
64 |
65 | private fun itemOffsetsVertical(
66 | outRect: Rect, itemPosition: Int, layoutManager: StaggeredGridLayoutManager,
67 | params: StaggeredGridLayoutManager.LayoutParams
68 | ) {
69 |
70 | val spanCount = layoutManager.spanCount
71 | val spanIndex = params.spanIndex
72 | val isFullSpan = params.isFullSpan
73 | if (isIncludeStartEdge) {
74 | if (spanIndex == itemPosition) {
75 | //first row top spacing
76 | outRect.top = spacingSize
77 | }
78 | }
79 |
80 | if (isIncludeEdge) {
81 | when {
82 | isFullSpan -> {
83 | outRect.left = spacingSize
84 | outRect.right = spacingSize
85 | }
86 | spanIndex == 0 -> {
87 | //first column
88 | outRect.left = spacingSize
89 | outRect.right = spacingSize / 2
90 | }
91 | (spanIndex + 1) % spanCount == 0 -> {
92 | //last column
93 | outRect.right = spacingSize
94 | outRect.left = spacingSize / 2
95 | }
96 | else -> {
97 | outRect.right = spacingSize / 2
98 | outRect.left = spacingSize / 2
99 | }
100 | }
101 | } else {
102 | when {
103 | isFullSpan -> {
104 | outRect.left = 0
105 | outRect.right = 0
106 | }
107 | spanIndex == 0 -> {
108 | //first column
109 | outRect.left = 0
110 | outRect.right = spacingSize / 2
111 | }
112 | (spanIndex + 1) % spanCount == 0 -> {
113 | //last column
114 | outRect.right = 0
115 | outRect.left = spacingSize / 2
116 | }
117 | else -> {
118 | outRect.right = spacingSize / 2
119 | outRect.left = spacingSize / 2
120 | }
121 | }
122 | }
123 |
124 | //无法确定最后一行
125 | outRect.bottom = spacingSize
126 | }
127 |
128 | private fun itemOffsetsHorizontal(
129 | outRect: Rect, itemPosition: Int,
130 | layoutManager: StaggeredGridLayoutManager, params: StaggeredGridLayoutManager.LayoutParams
131 | ) {
132 |
133 | val spanCount = layoutManager.spanCount
134 | val spanIndex = params.spanIndex
135 | val isFullSpan = params.isFullSpan
136 | if (isIncludeStartEdge) {
137 | if (spanIndex == itemPosition) {
138 | //first column left spacing
139 | outRect.left = spacingSize
140 | }
141 | }
142 |
143 | if (isIncludeEdge) {
144 | when {
145 | isFullSpan -> {
146 | outRect.top = spacingSize
147 | outRect.bottom = spacingSize
148 | }
149 | spanIndex == 0 -> {
150 | //first row
151 | outRect.top = spacingSize
152 | outRect.bottom = spacingSize / 2
153 | }
154 | (spanIndex + 1) % spanCount == 0 -> {
155 | //last row
156 | outRect.top = spacingSize / 2
157 | outRect.bottom = spacingSize
158 | }
159 | else -> {
160 | outRect.top = spacingSize / 2
161 | outRect.bottom = spacingSize / 2
162 | }
163 | }
164 | } else {
165 | when {
166 | isFullSpan -> {
167 | outRect.top = 0
168 | outRect.bottom = 0
169 | }
170 | spanIndex == 0 -> {
171 | //first row
172 | outRect.top = 0
173 | outRect.bottom = spacingSize / 2
174 | }
175 | (spanIndex + 1) % spanCount == 0 -> {
176 | //last row
177 | outRect.top = spacingSize / 2
178 | outRect.bottom = 0
179 | }
180 | else -> {
181 | outRect.top = spacingSize / 2
182 | outRect.bottom = spacingSize / 2
183 | }
184 | }
185 | }
186 |
187 | //无法确定最后一列
188 | outRect.right = spacingSize
189 | }
190 |
191 | class Builder {
192 | internal var spacingSize: Int = 0
193 | internal var isIncludeEdge: Boolean = false
194 | internal var isIncludeStartEdge: Boolean = false
195 |
196 | /**
197 | * orientation is Vertical,edge left right. Horizontal,edge top bottom
198 | */
199 | fun includeEdge() = apply { isIncludeEdge = true }
200 |
201 | /**
202 | * orientation is Vertical,first row top. Horizontal,first column left
203 | */
204 | fun includeStartEdge() = apply { isIncludeStartEdge = true }
205 |
206 | fun spacingSize(@Px size: Int) = apply { spacingSize = size }
207 |
208 | fun build() = StaggeredGridItemDecoration(this)
209 | }
210 | }
--------------------------------------------------------------------------------
/itemdecoration/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | RecyclerViewDivider
3 |
4 |
--------------------------------------------------------------------------------
/preview/grid.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/preview/grid.gif
--------------------------------------------------------------------------------
/preview/linear.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/preview/linear.gif
--------------------------------------------------------------------------------
/preview/staggered_grid.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zyyoona7/RecyclerViewItemDecoration/f5b32d0cc6f67ef42a4da2c17200c83864495c94/preview/staggered_grid.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':itemdecoration'
2 |
--------------------------------------------------------------------------------