├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── littlejerk
│ │ └── xrecyclerviewdivider
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── littlejerk
│ │ │ └── xrecyclerviewdivider
│ │ │ ├── GridActivity.java
│ │ │ ├── LinearActivity.java
│ │ │ ├── MainActivity.java
│ │ │ └── StaggeredGridActivity.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable-xxhdpi
│ │ └── icon_back_arrow_white.png
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ ├── activity_grid.xml
│ │ ├── activity_linear.xml
│ │ ├── activity_main.xml
│ │ ├── activity_staggered_grid.xml
│ │ ├── item_gird_horizontal_list.xml
│ │ ├── item_grid_vertical_list.xml
│ │ ├── item_linear_horizontal_list.xml
│ │ ├── item_linear_vertical_list.xml
│ │ ├── item_staggered_grid_horizontal_list.xml
│ │ └── item_staggered_grid_vertical_list.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-night
│ │ └── themes.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── themes.xml
│ └── test
│ └── java
│ └── com
│ └── littlejerk
│ └── xrecyclerviewdivider
│ └── ExampleUnitTest.java
├── art
├── app-debug.apk
├── grid_h_include_edge.jpg
├── grid_h_noinclude_edge.jpg
├── grid_v_include_edge.jpg
├── grid_v_noinclude_edge.jpg
├── linear_include_edge.jpg
├── linear_padding.jpg
├── staggeredgrid_h.jpg
└── staggeredgrid_v.jpg
├── baselib
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── littlejerk
│ │ └── rvdivider
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ └── java
│ │ └── com
│ │ └── littlejerk
│ │ └── rvdivider
│ │ ├── DividerHelper.java
│ │ ├── builder
│ │ ├── XDividerDecoration.java
│ │ ├── XGridBuilder.java
│ │ ├── XLinearBuilder.java
│ │ └── XStaggeredGridBuilder.java
│ │ └── decoration
│ │ ├── ILDecoration.java
│ │ └── LDecoration.java
│ └── test
│ └── java
│ └── com
│ └── littlejerk
│ └── rvdivider
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | .DS_Store # only needed under mac os
4 | /build
5 | /captures
6 | *.iml
7 | .idea
8 | *.apk #optional
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Android ReycyclerView强大的分割线-XRecyclerViewDivider
2 | [](https://jitpack.io/#HHotHeart/XRecyclerViewDivider)
3 |
4 | XRecyclerViewDivider是一个功能十分强大且全面的RecyclerView 分割线库,使用建造者模式初始化Decoration,链式调用即可绘制你所需要的分割线样式,间接减少重复性代码,主要有三个建造者:
5 | [XLinearBuilder](https://github.com/HHotHeart/XRecyclerViewDivider/blob/master/baselib/src/main/java/com/littlejerk/rvdivider/builder/XLinearBuilder.java)、[XGridBuilder](https://github.com/HHotHeart/XRecyclerViewDivider/blob/master/baselib/src/main/java/com/littlejerk/rvdivider/builder/XGridBuilder.java)、[XStaggeredGridBuilder](https://github.com/HHotHeart/XRecyclerViewDivider/blob/master/baselib/src/main/java/com/littlejerk/rvdivider/builder/XStaggeredGridBuilder.java)
6 | 它们分别为LinearLayoutManager、GridLayoutManager、StaggeredGridLayoutManager绘制不一样的分割线。
7 |
8 | ## 项目引入该库
9 |
10 | 在你的 Project build.gradle文件中添加:
11 |
12 | ```java
13 | allprojects {
14 | repositories {
15 | ...
16 | maven { url 'https://jitpack.io' }
17 | }
18 | }
19 | ```
20 | 在你的 Module build.gradle文件中添加:
21 |
22 | ```java
23 | dependencies {
24 | implementation 'com.github.huangxiaolianghh:XRecyclerViewDivider:1.0.2'
25 | }
26 | ```
27 |
28 |
29 | ## 效果图
30 |
31 |
32 |
33 |  |
34 |  |
35 |
36 |
37 |
38 |
39 |
40 |  |
41 |  |
42 |
43 |
44 |
45 |
46 |
47 |  |
48 |  |
49 |
50 |
51 |
52 |
53 |
54 |  |
55 |  |
56 |
57 |
58 |
59 |
60 | ## 功能特点
61 |
62 | ### 1.LinearLayoutManager
63 | * 支持水平竖直方向LayoutManager
64 | * 支持设置第一个item 上边距
65 | * 支持设置最后一个item的分割线
66 | * 支持space大小、分割线padding、分割线是否绘制到RecyclerView的padding
67 | * 支持设置分割线color、drawable
68 | * 支持设置不显示哪些item分割线
69 | * 支持定制某个item的分割线(包括padding、color、drawable、设置边界等)
70 |
71 | XLinearBuilder属性表格
72 |
73 | 属性| 意义
74 | -------- | -----
75 | mSpacing| 分割线间距,默认1dp;可直接设置dp或dp对应的res
76 | mShowLastLine| 是否绘制最后一个item的分割线,默认false
77 | mShowFirstTopLine| 是否绘制第一个item上边或左边分割线,默认false
78 | mIsIncludeParentLTPadding| 分割线是否绘制RecyclerView的左或上padding部分,默认false
79 | mIsIncludeParentRBPadding| 分割线是否绘制RecyclerView的右或下padding部分,默认false
80 | mLeftPadding | mTopPadding|分割线左边距或上边距
81 | mRightPadding | mBottomPadding|分割线右边距或下边距
82 | mColor| 分割线的颜色
83 | mDividerDrawable| 分割线的drawable
84 | mOnNoDividerPosition| position分割线不绘制的回调,返回position的数组,为null不处理
85 | mOnItemDivider| 定制某条分割线的回调,返回的是LDecoration,为null不处理
86 |
87 | LDecoration主要是设置某条分割线的属性,如果设置了setPadding方法,则会把mLeftPadding、mTopPadding、mRightPadding、mBottomPadding设置,设置了mDividerDrawable会覆盖mColor,具体可看源码。
88 |
89 |
90 | 基本使用:
91 | ```java
92 | new XLinearBuilder(this)
93 | //分割线间距,支持float dp 和DimenRes dp
94 | .setSpacing(4f)
95 | .setShowFirstTopLine(true)
96 | .setShowLastLine(true)
97 | .setColor(Color.BLACK)
98 | //设置哪几个position不绘制分割线,接受数组new int[]{0,1},返回null表示不处理
99 | .setOnItemNoDivider(() -> null)
100 | //定制某一item分割线样式,可改颜色和设置边沿分割线,返回null表示不处理
101 | .setOnItemDividerDecoration(new XLinearBuilder.OnItemDivider() {
102 | @Override
103 | public LDecoration getItemDividerDecoration(int position) {
104 | if (position == 1) {
105 | return new LDecoration(LinearActivity.this)
106 | .setColor(Color.RED);
107 |
108 | }
109 | return null;
110 | }
111 | })
112 | ;
113 | ```
114 | 如果想全部绘制边沿分割线,可这样设置:
115 |
116 | ```java
117 | new XLinearBuilder(this)
118 | //分割线间距,支持float dp 和DimenRes dp
119 | .setSpacing(4f)
120 | .setShowFirstTopLine(true)
121 | .setShowLastLine(true)
122 | .setColor(Color.BLACK)
123 | //设置哪几个position不绘制分割线,接受数组new int[]{0,1},返回null表示不处理
124 | .setOnItemNoDivider(() -> null)
125 | //定制某一item分割线样式,可改颜色和设置边沿分割线,返回null表示不处理
126 | .setOnItemDividerDecoration(new XLinearBuilder.OnItemDivider() {
127 | @Override
128 | public LDecoration getItemDividerDecoration(int position) {
129 | return new LDecoration(LinearActivity.this)
130 | .setAroundEdge(true, null, true, null)
131 | .setColor(Color.RED);
132 |
133 |
134 | }
135 | });
136 | ```
137 | 具体还有很多功能,可clone下来,自己去体验。
138 |
139 | ### 2.GridLayoutManager
140 |
141 | * 支持水平竖直方向GridLayoutManager
142 | * 支持设置是否显示边界
143 | * 可分别设置水平方向和竖直方向的space、color、drawable等
144 | * 支持SpanSizeLookup(不规则的Grid)
145 | * 支持设置横竖交叉处的归属(属于竖向或横向)
146 |
147 | XGridBuilder属性表格
148 |
149 | 属性| 意义
150 | -------- | -----
151 | mSpacing| 分割线间距,默认0dp;可直接设置dp或dp对应的res
152 | mVLineSpacing| 竖直线的间距,默认0dp,会覆盖mSpacing
153 | mHLineSpacing| 水平线的间距,默认0dp,会覆盖mSpacing
154 | mIsIncludeEdge| 是否绘制边界,默认false
155 | mVerticalIncludeEdge| 分割线交叉处是否属于竖直线的部分,默认false
156 | mVLineColor|竖直分割线颜色
157 | mHLineColor|水平分割线颜色
158 | mColor| 分割线的颜色,会被mVLineColor或mHLineColor覆盖
159 | mVLineDividerDrawable| 竖直分割线的drawable
160 | mHLineDividerDrawable| 水平分割线的drawable
161 | mDividerDrawable| 分割线的drawable,会被mVLineDividerDrawable或mHLineDividerDrawable覆盖
162 |
163 | 基本使用:
164 |
165 | ```java
166 | new XGridBuilder(this)
167 | //分割线间距,支持float dp 和DimenRes dp
168 | .setSpacing(2f)//这几个Spacing的优先级可看XGridBuilder说明
169 | .setVLineSpacing(4f)
170 | .setHLineSpacing(8f)
171 | //这几个color和drawable的优先级可看XGridBuilder说明
172 | .setColor(Color.BLUE)
173 | //可设置颜色和drawable,drawable>color
174 | // .setColorRes(R.color.white)
175 | // .setDrawable(new ColorDrawable(Color.WHITE))
176 | // .setDrawableRes(R.drawable.)
177 | .setHLineColor(Color.BLACK)
178 | // .setHLineDrawable()
179 | .setVLineColor(Color.RED)
180 | // .setVLineDrawable()
181 | //是否包括边界
182 | .setIncludeEdge(true)
183 | //竖直和水平分割线交叉处绘制的是竖直分割线颜色(交叉处属于竖直分割线)
184 | .setVerticalIncludeEdge(true)
185 | ;
186 | ```
187 |
188 | ### 3.StaggeredGridLayoutManager
189 | * 支持水平竖直方向StaggeredGridLayoutManager
190 | * 支持设置是否显示边界
191 | * 可设置水平方向和竖直方向的space、不支持color、drawable(基本不用)
192 | * 支持设置FullSpan情况
193 |
194 | XStaggeredGridBuilder属性表格
195 |
196 | 属性| 意义
197 | -------- | -----
198 | mSpacing| 分割线间距,默认0dp;可直接设置dp或dp对应的res
199 | mVLineSpacing| 竖直线的间距,默认0dp,会覆盖mSpacing
200 | mHLineSpacing| 水平线的间距,默认0dp,会覆盖mSpacing
201 | mIsIncludeEdge| 是否绘制边界,默认false
202 | mIsIgnoreFullSpan| 边界绘制是否忽略FullSpan的情况,默认false
203 |
204 |
205 | 基本使用:
206 |
207 | ```java
208 | new XStaggeredGridBuilder(this)
209 | //分割线间距,支持float dp 和DimenRes dp
210 | .setSpacing(2f)//这几个Spacing的优先级可看XGridBuilder说明
211 | .setVLineSpacing(4f)
212 | .setHLineSpacing(8f)
213 | //是否包括边界
214 | .setIncludeEdge(true)
215 | //是否忽略FullSpan的情况
216 | .setIgnoreFullSpan(true)
217 | ;
218 | ```
219 |
220 | 感谢:[ByRecyclerView](https://github.com/youlookwhat/ByRecyclerView),采纳了其对FullSpan处理的一些思想。
221 |
222 | ## 结语
223 |
224 | 使用中有问题或没有实现的功能都可以反馈给我,我一定会尽量满足大家的需求。希望这个库能够帮到大家,欢迎star~。
225 |
226 | [文章博客](https://blog.csdn.net/HHHceo/article/details/117453495)
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | }
4 |
5 | android {
6 | compileSdkVersion 30
7 |
8 | defaultConfig {
9 | applicationId "com.littlejerk.xrecyclerviewdivider"
10 | minSdkVersion 21
11 | targetSdkVersion 30
12 | versionCode 1
13 | versionName "1.0"
14 |
15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
16 | }
17 |
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | compileOptions {
25 | sourceCompatibility JavaVersion.VERSION_1_8
26 | targetCompatibility JavaVersion.VERSION_1_8
27 | }
28 | }
29 |
30 | dependencies {
31 |
32 | implementation 'androidx.appcompat:appcompat:1.2.0'
33 | implementation 'com.google.android.material:material:1.2.1'
34 | implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
35 | implementation project(path: ':baselib')
36 | testImplementation 'junit:junit:4.+'
37 | androidTestImplementation 'androidx.test.ext:junit:1.1.2'
38 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
39 | implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'
40 | }
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/littlejerk/xrecyclerviewdivider/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.xrecyclerviewdivider;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("com.littlejerk.xrecyclerviewdivider", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/littlejerk/xrecyclerviewdivider/GridActivity.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.xrecyclerviewdivider;
2 |
3 | import android.graphics.Color;
4 | import android.os.Bundle;
5 | import android.widget.RadioButton;
6 |
7 | import androidx.appcompat.app.AppCompatActivity;
8 | import androidx.recyclerview.widget.GridLayoutManager;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | import com.chad.library.adapter.base.BaseQuickAdapter;
12 | import com.chad.library.adapter.base.viewholder.BaseViewHolder;
13 | import com.littlejerk.rvdivider.builder.XGridBuilder;
14 |
15 | import org.jetbrains.annotations.NotNull;
16 | import org.jetbrains.annotations.Nullable;
17 |
18 | import java.util.Arrays;
19 | import java.util.List;
20 |
21 | public class GridActivity extends AppCompatActivity {
22 |
23 | private GridAdapter mAdapter;
24 | private GridLayoutManager mManager;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_grid);
30 |
31 | findViewById(R.id.iv_back).setOnClickListener(mView -> onBackPressed());
32 | RadioButton rb_v = findViewById(R.id.rb_v);
33 | RadioButton rb_h = findViewById(R.id.rb_h);
34 | RecyclerView recyclerView = findViewById(R.id.recycler_view);
35 |
36 | rb_v.setOnCheckedChangeListener((mCompoundButton, mB) -> {
37 | if (mB) {
38 | deleteItemDivider(recyclerView);
39 | mManager = new GridLayoutManager(this, 4, RecyclerView.VERTICAL, false);
40 | recyclerView.setLayoutManager(mManager);
41 | recyclerView.addItemDecoration(bindXGrid().build());
42 | mAdapter = new GridAdapter(R.layout.item_grid_vertical_list, getData());
43 | recyclerView.setAdapter(mAdapter);
44 | }
45 | });
46 | rb_h.setOnCheckedChangeListener((mCompoundButton, mB) -> {
47 | if (mB) {
48 | deleteItemDivider(recyclerView);
49 | mManager = new GridLayoutManager(this, 4, RecyclerView.HORIZONTAL, false);
50 | recyclerView.setLayoutManager(mManager);
51 | recyclerView.addItemDecoration(bindXGrid().build());
52 | mAdapter = new GridAdapter(R.layout.item_gird_horizontal_list, getData());
53 | recyclerView.setAdapter(mAdapter);
54 | }
55 | });
56 |
57 | rb_v.setChecked(true);
58 |
59 | }
60 |
61 | /**
62 | * 线性构造器
63 | *
64 | * @return
65 | */
66 | public XGridBuilder bindXGrid() {
67 | return new XGridBuilder(this)
68 | //分割线间距,支持float dp 和DimenRes dp
69 | .setSpacing(2f)//这几个Spacing的优先级可看XGridBuilder说明
70 | .setVLineSpacing(4f)
71 | .setHLineSpacing(8f)
72 | //这几个color和drawable的优先级可看XGridBuilder说明
73 | .setColor(Color.BLUE)
74 | //可设置颜色和drawable,drawable>color
75 | // .setColorRes(R.color.white)
76 | // .setDrawable(new ColorDrawable(Color.WHITE))
77 | // .setDrawableRes(R.drawable.)
78 | .setHLineColor(Color.BLACK)
79 | // .setHLineDrawable()
80 | .setVLineColor(Color.RED)
81 | // .setVLineDrawable()
82 | //是否包括边界
83 | .setIncludeEdge(true)
84 | //竖直和水平分割线交叉处绘制的是竖直分割线颜色(交叉处属于竖直分割线)
85 | .setVerticalIncludeEdge(true)
86 | ;
87 | }
88 |
89 | /**
90 | * 重新设置分割线时,需删除之前的分割线
91 | *
92 | * @param recyclerView
93 | */
94 | public void deleteItemDivider(RecyclerView recyclerView) {
95 | for (int i = 0; i < recyclerView.getItemDecorationCount(); i++) {
96 | recyclerView.removeItemDecoration(recyclerView.getItemDecorationAt(i));
97 | }
98 | }
99 |
100 |
101 | public static class GridAdapter extends BaseQuickAdapter {
102 |
103 | public GridAdapter(int layoutResId, @Nullable List data) {
104 | super(layoutResId, data);
105 | }
106 |
107 | @Override
108 | protected void convert(@NotNull BaseViewHolder holder, String mS) {
109 |
110 | }
111 | }
112 |
113 |
114 | public List getData() {
115 | return Arrays.asList("1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1");
116 | }
117 |
118 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/littlejerk/xrecyclerviewdivider/LinearActivity.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.xrecyclerviewdivider;
2 |
3 | import android.os.Bundle;
4 | import android.widget.RadioButton;
5 |
6 | import com.chad.library.adapter.base.BaseQuickAdapter;
7 | import com.chad.library.adapter.base.viewholder.BaseViewHolder;
8 | import com.littlejerk.rvdivider.builder.XLinearBuilder;
9 | import com.littlejerk.rvdivider.decoration.LDecoration;
10 |
11 | import org.jetbrains.annotations.NotNull;
12 | import org.jetbrains.annotations.Nullable;
13 |
14 | import java.util.Arrays;
15 | import java.util.List;
16 |
17 | import androidx.appcompat.app.AppCompatActivity;
18 | import androidx.recyclerview.widget.LinearLayoutManager;
19 | import androidx.recyclerview.widget.RecyclerView;
20 |
21 | public class LinearActivity extends AppCompatActivity {
22 |
23 | private LinearAdapter mAdapter;
24 | private LinearLayoutManager mManager;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_linear);
30 |
31 | findViewById(R.id.iv_back).setOnClickListener(mView -> onBackPressed());
32 | RadioButton rb_v = findViewById(R.id.rb_v);
33 | RadioButton rb_h = findViewById(R.id.rb_h);
34 | RecyclerView recyclerView = findViewById(R.id.recycler_view);
35 |
36 | rb_v.setOnCheckedChangeListener((mCompoundButton, mB) -> {
37 | if (mB) {
38 | deleteItemDivider(recyclerView);
39 | mManager = new LinearLayoutManager(this);
40 | recyclerView.setLayoutManager(mManager);
41 | recyclerView.addItemDecoration(bindXLinear().build());
42 | mAdapter = new LinearAdapter(R.layout.item_linear_vertical_list, getData());
43 | recyclerView.setAdapter(mAdapter);
44 | }
45 | });
46 | rb_h.setOnCheckedChangeListener((mCompoundButton, mB) -> {
47 | if (mB) {
48 | deleteItemDivider(recyclerView);
49 | mManager = new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false);
50 | recyclerView.setLayoutManager(mManager);
51 | recyclerView.addItemDecoration(bindXLinear().build());
52 | mAdapter = new LinearAdapter(R.layout.item_linear_horizontal_list, getData());
53 | recyclerView.setAdapter(mAdapter);
54 | }
55 | });
56 |
57 | rb_v.setChecked(true);
58 |
59 | }
60 |
61 | /**
62 | * 线性构造器
63 | *
64 | * @return
65 | */
66 | public XLinearBuilder bindXLinear() {
67 | return new XLinearBuilder(this)
68 | //分割线间距,支持float dp 和DimenRes dp
69 | .setSpacing(2f)
70 | .setShowFirstTopLine(true)
71 | .setShowLastLine(true)
72 | // .setColor(Color.BLACK)
73 | //可设置颜色和drawable,drawable>color
74 | // .setColorRes(R.color.white)
75 | // .setDrawable(new ColorDrawable(Color.WHITE))
76 | // .setDrawableRes(R.drawable.)
77 | //是否包含RecyclerView的padding,分为左右(竖直),上下(水平)
78 | .setIncludeParentHVPadding(false, false)
79 | //设置item分割线的padding,分为左右(竖直),上下(水平)
80 | .setPadding(4f)
81 | // .setLeftPadding(4f)
82 | // .setRightPadding(4f)
83 | // .setTopPadding(4f)
84 | // .setBottomPadding(4f)
85 | //设置哪几个position不绘制分割线,接受数组new int[]{0,1},返回null表示不处理
86 | .setOnItemNoDivider(() -> null)
87 | //定制某一item分割线样式,可改颜色和设置边沿分割线,返回null表示不处理
88 | .setOnItemDividerDecoration(new XLinearBuilder.OnItemDivider() {
89 | @Override
90 | public LDecoration getItemDividerDecoration(int position) {
91 | // if(position == 1){
92 | // return new LDecoration(LinearActivity.this)
93 | // //竖直
94 | // .setAroundEdge(true,null,true,null)
95 | // //水平
96 | // .setAroundEdge(null,true,null,true)
97 | //
98 | // //设置drawable和上面一样(针对某一条分割线)
99 | // .setColor(Color.RED)
100 | // //设置padding和上面一样
101 | // .setPadding(10f);
102 | //
103 | // }
104 | return null;
105 | }
106 | })
107 | ;
108 | }
109 |
110 | /**
111 | * 重新设置分割线时,需删除之前的分割线
112 | *
113 | * @param recyclerView
114 | */
115 | public void deleteItemDivider(RecyclerView recyclerView) {
116 | for (int i = 0; i < recyclerView.getItemDecorationCount(); i++) {
117 | recyclerView.removeItemDecoration(recyclerView.getItemDecorationAt(i));
118 | }
119 | }
120 |
121 |
122 | public static class LinearAdapter extends BaseQuickAdapter {
123 |
124 | public LinearAdapter(int layoutResId, @Nullable List data) {
125 | super(layoutResId, data);
126 | }
127 |
128 | @Override
129 | protected void convert(@NotNull BaseViewHolder holder, String mS) {
130 |
131 | }
132 | }
133 |
134 |
135 | public List getData() {
136 | return Arrays.asList("1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1");
137 | }
138 |
139 |
140 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/littlejerk/xrecyclerviewdivider/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.xrecyclerviewdivider;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 |
6 | import androidx.appcompat.app.AppCompatActivity;
7 |
8 | import static com.littlejerk.xrecyclerviewdivider.R.id.btn_StaggeredGridLayoutManager;
9 |
10 | public class MainActivity extends AppCompatActivity {
11 |
12 | @Override
13 | protected void onCreate(Bundle savedInstanceState) {
14 | super.onCreate(savedInstanceState);
15 | setContentView(R.layout.activity_main);
16 |
17 | findViewById(R.id.btn_LinearLayoutManager).setOnClickListener(v -> {
18 | startActivity(new Intent(MainActivity.this, LinearActivity.class));
19 | });
20 |
21 | findViewById(R.id.btn_GridLayoutManager).setOnClickListener(v -> {
22 | startActivity(new Intent(MainActivity.this, GridActivity.class));
23 |
24 | });
25 |
26 | findViewById(btn_StaggeredGridLayoutManager).setOnClickListener(v -> {
27 | startActivity(new Intent(MainActivity.this, StaggeredGridActivity.class));
28 |
29 | });
30 |
31 | }
32 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/littlejerk/xrecyclerviewdivider/StaggeredGridActivity.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.xrecyclerviewdivider;
2 |
3 | import android.os.Bundle;
4 | import android.view.ViewGroup;
5 | import android.widget.RadioButton;
6 | import android.widget.TextView;
7 |
8 | import androidx.appcompat.app.AppCompatActivity;
9 | import androidx.recyclerview.widget.RecyclerView;
10 | import androidx.recyclerview.widget.StaggeredGridLayoutManager;
11 |
12 | import com.chad.library.adapter.base.BaseQuickAdapter;
13 | import com.chad.library.adapter.base.viewholder.BaseViewHolder;
14 | import com.littlejerk.rvdivider.DividerHelper;
15 | import com.littlejerk.rvdivider.builder.XStaggeredGridBuilder;
16 |
17 | import org.jetbrains.annotations.NotNull;
18 | import org.jetbrains.annotations.Nullable;
19 |
20 | import java.util.Arrays;
21 | import java.util.List;
22 |
23 | public class StaggeredGridActivity extends AppCompatActivity {
24 |
25 | private StaggeredGridAdapter mAdapter;
26 | private StaggeredGridLayoutManager mManager;
27 |
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setContentView(R.layout.activity_staggered_grid);
32 | findViewById(R.id.iv_back).setOnClickListener(mView -> onBackPressed());
33 | RadioButton rb_v = findViewById(R.id.rb_v);
34 | RadioButton rb_h = findViewById(R.id.rb_h);
35 | RecyclerView recyclerView = findViewById(R.id.recycler_view);
36 |
37 | rb_v.setOnCheckedChangeListener((mCompoundButton, mB) -> {
38 | if (mB) {
39 | deleteItemDivider(recyclerView);
40 | mManager = new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL);
41 | recyclerView.setLayoutManager(mManager);
42 | recyclerView.addItemDecoration(bindXStaggeredGrid().build());
43 | mAdapter = new StaggeredGridAdapter(R.layout.item_grid_vertical_list, getData());
44 | recyclerView.setAdapter(mAdapter);
45 | }
46 | });
47 | rb_h.setOnCheckedChangeListener((mCompoundButton, mB) -> {
48 | if (mB) {
49 | deleteItemDivider(recyclerView);
50 | mManager = new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.HORIZONTAL);
51 | recyclerView.setLayoutManager(mManager);
52 | recyclerView.addItemDecoration(bindXStaggeredGrid().build());
53 | mAdapter = new StaggeredGridAdapter(R.layout.item_gird_horizontal_list, getData());
54 | recyclerView.setAdapter(mAdapter);
55 | }
56 | });
57 |
58 | rb_v.setChecked(true);
59 |
60 | }
61 |
62 | /**
63 | * 线性构造器
64 | *
65 | * @return
66 | */
67 | public XStaggeredGridBuilder bindXStaggeredGrid() {
68 | return new XStaggeredGridBuilder(this)
69 | //分割线间距,支持float dp 和DimenRes dp
70 | .setSpacing(2f)//这几个Spacing的优先级可看XGridBuilder说明
71 | .setVLineSpacing(4f)
72 | .setHLineSpacing(8f)
73 | //是否包括边界
74 | .setIncludeEdge(true)
75 | //是否忽略FullSpan的情况
76 | .setIgnoreFullSpan(true)
77 | ;
78 | }
79 |
80 | /**
81 | * 重新设置分割线时,需删除之前的分割线
82 | *
83 | * @param recyclerView
84 | */
85 | public void deleteItemDivider(RecyclerView recyclerView) {
86 | for (int i = 0; i < recyclerView.getItemDecorationCount(); i++) {
87 | recyclerView.removeItemDecoration(recyclerView.getItemDecorationAt(i));
88 | }
89 | }
90 |
91 |
92 | public static class StaggeredGridAdapter extends BaseQuickAdapter {
93 |
94 | public StaggeredGridAdapter(int layoutResId, @Nullable List data) {
95 | super(layoutResId, data);
96 | }
97 |
98 | @Override
99 | protected void convert(@NotNull BaseViewHolder holder, String mS) {
100 | TextView textView = holder.getView(R.id.tv_name);
101 | if (holder.getAdapterPosition() < 3) {
102 | ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
103 | if (lp instanceof StaggeredGridLayoutManager.LayoutParams) {
104 | StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
105 | p.setFullSpan(true);
106 | }
107 |
108 | } else {
109 | if (holder.getAdapterPosition() % 2 == 0) {
110 | ViewGroup.LayoutParams params = textView.getLayoutParams();
111 | //设置图片的相对于屏幕的宽高比
112 | params.width = DividerHelper.dp2px(150);
113 | params.height = DividerHelper.dp2px(100);
114 | textView.setLayoutParams(params);
115 | }
116 | }
117 | }
118 | }
119 |
120 |
121 | public List getData() {
122 | return Arrays.asList("1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1");
123 | }
124 |
125 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/icon_back_arrow_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/app/src/main/res/drawable-xxhdpi/icon_back_arrow_white.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_grid.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
22 |
23 |
32 |
33 |
34 |
35 |
40 |
46 |
52 |
53 |
54 |
58 |
59 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_linear.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
22 |
23 |
32 |
33 |
34 |
35 |
40 |
46 |
52 |
53 |
54 |
58 |
59 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
19 |
24 |
25 |
31 |
32 |
39 |
40 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_staggered_grid.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
22 |
23 |
32 |
33 |
34 |
35 |
40 |
46 |
52 |
53 |
54 |
58 |
59 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_gird_horizontal_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_grid_vertical_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_linear_horizontal_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_linear_vertical_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_staggered_grid_horizontal_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_staggered_grid_vertical_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
21 |
--------------------------------------------------------------------------------
/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/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 13sp
4 | 60dp
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | XRecyclerViewDivider
3 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/test/java/com/littlejerk/xrecyclerviewdivider/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.xrecyclerviewdivider;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/art/app-debug.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/art/app-debug.apk
--------------------------------------------------------------------------------
/art/grid_h_include_edge.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/art/grid_h_include_edge.jpg
--------------------------------------------------------------------------------
/art/grid_h_noinclude_edge.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/art/grid_h_noinclude_edge.jpg
--------------------------------------------------------------------------------
/art/grid_v_include_edge.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/art/grid_v_include_edge.jpg
--------------------------------------------------------------------------------
/art/grid_v_noinclude_edge.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/art/grid_v_noinclude_edge.jpg
--------------------------------------------------------------------------------
/art/linear_include_edge.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/art/linear_include_edge.jpg
--------------------------------------------------------------------------------
/art/linear_padding.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/art/linear_padding.jpg
--------------------------------------------------------------------------------
/art/staggeredgrid_h.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/art/staggeredgrid_h.jpg
--------------------------------------------------------------------------------
/art/staggeredgrid_v.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/art/staggeredgrid_v.jpg
--------------------------------------------------------------------------------
/baselib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/baselib/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | }
4 |
5 | android {
6 | compileSdkVersion 30
7 |
8 | defaultConfig {
9 | minSdkVersion 19
10 | targetSdkVersion 30
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
15 | consumerProguardFiles "consumer-rules.pro"
16 | }
17 |
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | compileOptions {
25 | sourceCompatibility JavaVersion.VERSION_1_8
26 | targetCompatibility JavaVersion.VERSION_1_8
27 | }
28 | }
29 |
30 | dependencies {
31 |
32 | implementation 'androidx.appcompat:appcompat:1.2.0'
33 | implementation 'com.google.android.material:material:1.2.1'
34 | testImplementation 'junit:junit:4.+'
35 | androidTestImplementation 'androidx.test.ext:junit:1.1.2'
36 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
37 | }
--------------------------------------------------------------------------------
/baselib/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/baselib/consumer-rules.pro
--------------------------------------------------------------------------------
/baselib/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
--------------------------------------------------------------------------------
/baselib/src/androidTest/java/com/littlejerk/rvdivider/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.rvdivider;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("com.littlejerk.baselib.test", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/baselib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/littlejerk/rvdivider/DividerHelper.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.rvdivider;
2 |
3 | import android.content.res.Resources;
4 | import android.graphics.Color;
5 | import android.util.DisplayMetrics;
6 | import android.util.TypedValue;
7 | import android.view.View;
8 |
9 | import com.littlejerk.rvdivider.builder.XLinearBuilder;
10 | import com.littlejerk.rvdivider.decoration.LDecoration;
11 |
12 | import java.lang.annotation.Retention;
13 | import java.lang.annotation.RetentionPolicy;
14 | import java.util.Objects;
15 |
16 | import androidx.annotation.IntDef;
17 | import androidx.recyclerview.widget.GridLayoutManager;
18 | import androidx.recyclerview.widget.LinearLayoutManager;
19 | import androidx.recyclerview.widget.RecyclerView;
20 | import androidx.recyclerview.widget.StaggeredGridLayoutManager;
21 |
22 | import static androidx.recyclerview.widget.LinearLayoutManager.VERTICAL;
23 |
24 |
25 | /**
26 | * @Author : HHotHeart
27 | * @Time : 2021/5/31 16:03
28 | * @Description : 设置分割线帮助类
29 | */
30 | public final class DividerHelper {
31 |
32 | private static final String TAG = "DividerHelper";
33 | public static final int NO_COLOR = Color.TRANSPARENT;
34 |
35 | private DividerHelper() {
36 | throw new UnsupportedOperationException("u can't instantiate me...");
37 | }
38 |
39 | /**
40 | * 是否为最后一行(Vertical)
41 | * 是否为最后一列(Horizontal)
42 | *
43 | * @param parent
44 | * @param childCount
45 | * @param childIndex
46 | * @return
47 | */
48 | public static boolean isLastRow(RecyclerView parent,
49 | int childCount,
50 | int childIndex) {
51 |
52 | int spanCount = getSpanCount(parent);
53 |
54 | if (getOrientation(parent) == VERTICAL) {
55 | return isLastItemEdgeValid((
56 | childIndex >= childCount - spanCount), parent, childCount, childIndex, true
57 | );
58 | } else {
59 | int spanIndex = getItemSpanIndex(parent, childIndex, true);
60 | int itemSpanSize = getItemSpanSize(parent, childIndex, true);
61 | return (spanIndex + itemSpanSize) == spanCount;
62 | }
63 |
64 | }
65 |
66 | /**
67 | * 是否为最后一列
68 | *
69 | * @param parent
70 | * @return
71 | */
72 | public static boolean isLastColumn(RecyclerView parent,
73 | int childCount,
74 | int childIndex) {
75 | int spanCount = getSpanCount(parent);
76 | if (getOrientation(parent) == VERTICAL) {
77 | int spanIndex = getItemSpanIndex(parent, childIndex, false);
78 | int itemSpanSize = getItemSpanSize(parent, childIndex, false);
79 | return (spanIndex + itemSpanSize) == spanCount;
80 | } else {
81 | return isLastItemEdgeValid((
82 | childIndex >= childCount - spanCount), parent, childCount, childIndex, false
83 | );
84 | }
85 | }
86 |
87 | // /**
88 | // * 是否为边界
89 | // *
90 | // * @param parent
91 | // * @param childCount
92 | // * @param childIndex
93 | // * @param itemSpanSize
94 | // * @param spanIndex
95 | // * @return
96 | // */
97 | // public static boolean isBottomEdge(RecyclerView parent,
98 | // int childCount,
99 | // int childIndex,
100 | // int itemSpanSize,
101 | // int spanIndex) {
102 | // int spanCount = getSpanCount(parent);
103 | // if (getOrientation(parent) == VERTICAL) {
104 | // return isLastItemEdgeValid((
105 | // childIndex
106 | // >= childCount - spanCount), parent, childCount, childIndex, spanIndex
107 | // );
108 | // } else {
109 | // return (spanIndex + itemSpanSize) == spanCount;
110 | // }
111 | // }
112 |
113 | protected static boolean isLastItemEdgeValid(boolean isOneOfLastItems,
114 | RecyclerView parent,
115 | int childCount,
116 | int childIndex, boolean isRow) {
117 | int totalSpanRemaining = 0;
118 | if (isOneOfLastItems) {
119 | for (int i = childIndex; i < childCount; i++) {
120 | totalSpanRemaining = totalSpanRemaining + getItemSpanSize(parent, i, isRow);
121 | }
122 | }
123 | int spanIndex = getItemSpanIndex(parent, childIndex, isRow);
124 | return isOneOfLastItems && (totalSpanRemaining <= getSpanCount(parent) - spanIndex);
125 | }
126 |
127 | /**
128 | * 获取RecyclerView布局方向
129 | *
130 | * @param parent
131 | * @return
132 | */
133 | protected static int getOrientation(RecyclerView parent) {
134 | RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
135 | if (layoutManager instanceof GridLayoutManager) {
136 | return ((GridLayoutManager) layoutManager).getOrientation();
137 | } else if (layoutManager instanceof LinearLayoutManager) {
138 | return ((LinearLayoutManager) layoutManager).getOrientation();
139 | } else if (layoutManager instanceof StaggeredGridLayoutManager) {
140 | return ((StaggeredGridLayoutManager) layoutManager).getOrientation();
141 | }
142 |
143 | return VERTICAL;
144 | }
145 |
146 | /**
147 | * 获取item跨的列数
148 | *
149 | * @param parent
150 | * @param childIndex
151 | * @return
152 | */
153 | protected static int getItemSpanSize(RecyclerView parent, int childIndex, boolean isRow) {
154 | RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
155 | if (layoutManager instanceof GridLayoutManager) {
156 | return ((GridLayoutManager) layoutManager).getSpanSizeLookup().getSpanSize(childIndex);
157 | } else if (layoutManager instanceof StaggeredGridLayoutManager) {
158 | //瀑布流是不规则的,对其区别处理
159 | if (isRow) {
160 | return 1;
161 | } else {
162 | View view = layoutManager.findViewByPosition(childIndex);
163 | Objects.requireNonNull(view, "findViewByPosition for view is null");
164 | StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
165 | return params.isFullSpan() ? getSpanCount(parent) : 1;
166 | }
167 | } else if (layoutManager instanceof LinearLayoutManager) {
168 | return 1;
169 | }
170 |
171 | return -1;
172 | }
173 |
174 | /**
175 | * 获取item的第一个检索
176 | *
177 | * @param parent
178 | * @param childIndex
179 | * @return
180 | */
181 | protected static int getItemSpanIndex(RecyclerView parent, int childIndex, boolean isRow) {
182 | int spanCount = getSpanCount(parent);
183 | RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
184 | if (layoutManager instanceof GridLayoutManager) {
185 | return ((GridLayoutManager) layoutManager).getSpanSizeLookup().getSpanIndex(childIndex, spanCount);
186 | } else if (layoutManager instanceof StaggeredGridLayoutManager) {
187 | //瀑布流是不规则的,对其区别处理
188 | if (isRow) {
189 | return childIndex % spanCount;
190 | } else {
191 | View view = layoutManager.findViewByPosition(childIndex);
192 | Objects.requireNonNull(view, "findViewByPosition for view is null");
193 | StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
194 | // 列
195 | return params.getSpanIndex();
196 | }
197 | } else if (layoutManager instanceof LinearLayoutManager) {
198 | return 0;
199 | }
200 |
201 | return -1;
202 | }
203 |
204 |
205 | /**
206 | * 获取LayoutManager的span
207 | *
208 | * @param parent
209 | * @return
210 | */
211 | public static int getSpanCount(RecyclerView parent) {
212 | int spanCount = -1;
213 | RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
214 | if (layoutManager instanceof GridLayoutManager) {
215 | spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
216 | } else if (layoutManager instanceof StaggeredGridLayoutManager) {
217 | spanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
218 | } else if (layoutManager instanceof LinearLayoutManager) {
219 | spanCount = 1;
220 | }
221 | return spanCount;
222 | }
223 |
224 | /**
225 | * 获取当前RecyclerView分割线类型
226 | *
227 | * @param parent
228 | * @return
229 | */
230 | public static DividerType getDividerType(RecyclerView parent) {
231 | RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
232 | if (layoutManager instanceof GridLayoutManager) {
233 | int orientation = ((GridLayoutManager) layoutManager).getOrientation();
234 | return orientation == GridLayoutManager.VERTICAL ?
235 | DividerType.GRID_VERTICAL : DividerType.GRID_HORIZONTAL;
236 | } else if (layoutManager instanceof LinearLayoutManager) {
237 | int orientation = ((LinearLayoutManager) layoutManager).getOrientation();
238 | return orientation == LinearLayoutManager.VERTICAL ?
239 | DividerType.LINEAR_VERTICAL : DividerType.LINEAR_HORIZONTAL;
240 | } else if (layoutManager instanceof StaggeredGridLayoutManager) {
241 | int orientation = ((StaggeredGridLayoutManager) layoutManager).getOrientation();
242 | return orientation == StaggeredGridLayoutManager.VERTICAL ?
243 | DividerType.STAGGERED_GRID_VERTICAL : DividerType.STAGGERED_GRID_HORIZONTAL;
244 | } else {
245 | return DividerType.UNKNOWN;
246 | }
247 | }
248 |
249 |
250 | public enum DividerType {
251 |
252 | LINEAR_VERTICAL,
253 | LINEAR_HORIZONTAL,
254 | GRID_VERTICAL,
255 | GRID_HORIZONTAL,
256 | STAGGERED_GRID_VERTICAL,
257 | STAGGERED_GRID_HORIZONTAL,
258 | UNKNOWN
259 |
260 | }
261 |
262 | @Retention(RetentionPolicy.SOURCE)
263 | @IntDef({Edge.LEFT, Edge.TOP, Edge.RIGHT, Edge.BOTTOM})
264 | public @interface Edge {
265 | int LEFT = 0;
266 | int TOP = 1;
267 | int RIGHT = 2;
268 | int BOTTOM = 3;
269 | }
270 |
271 |
272 | /**
273 | * 检测数组是否存在某个position
274 | *
275 | * @param list
276 | * @param position
277 | * @return
278 | */
279 | public static boolean isContains(int[] list, int position) {
280 | for (int j : list) {
281 | if (position == j) {
282 | return true;
283 | }
284 | }
285 | return false;
286 | }
287 |
288 | /**
289 | * 获取分割线装饰器
290 | *
291 | * @param builder
292 | * @param itemPosition
293 | * @return
294 | */
295 | public static LDecoration getDecoration(XLinearBuilder builder, int itemPosition) {
296 | if (builder.getItemDividerDecoration() != null && builder.getItemDividerDecoration().getItemDividerDecoration(itemPosition) != null) {
297 | return builder.getItemDividerDecoration().getItemDividerDecoration(itemPosition);
298 | }
299 | return null;
300 | }
301 |
302 |
303 | /**
304 | * 获取Decoration的左内边距
305 | *
306 | * @param decoration
307 | * @return
308 | */
309 | public static int getDecorationLeftPadding(LDecoration decoration) {
310 | if (decoration == null) return 0;
311 | return decoration.getLeftPadding();
312 | }
313 |
314 | /**
315 | * 获取Decoration的右内边距
316 | *
317 | * @param decoration
318 | * @return
319 | */
320 | public static int getDecorationRightPadding(LDecoration decoration) {
321 | if (decoration == null) return 0;
322 | return decoration.getRightPadding();
323 | }
324 |
325 | /**
326 | * 获取Decoration的顶部内边距
327 | *
328 | * @param decoration
329 | * @return
330 | */
331 | public static int getDecorationTopPadding(LDecoration decoration) {
332 | if (decoration == null) return 0;
333 | return decoration.getTopPadding();
334 | }
335 |
336 | /**
337 | * 获取Decoration的底部内边距
338 | *
339 | * @param decoration
340 | * @return
341 | */
342 | public static int getDecorationBottomPadding(LDecoration decoration) {
343 | if (decoration == null) return 0;
344 | return decoration.getBottomPadding();
345 | }
346 |
347 |
348 | /**
349 | * 是否绘制边界的颜色
350 | *
351 | * @param decoration
352 | * @param edge
353 | * @return
354 | */
355 | public static Boolean isDrawEdge(LDecoration decoration, @Edge int edge) {
356 | if (decoration == null) return null;
357 | Boolean[] aroundEdge = decoration.getAroundEdge();
358 | return aroundEdge[edge];
359 | }
360 |
361 | /**
362 | * dp转px
363 | */
364 | public static int dp2px(final float dpValue) {
365 | final float scale = Resources.getSystem().getDisplayMetrics().density;
366 | return (int) (dpValue * scale + 0.5f);
367 | }
368 |
369 | /**
370 | * px转dp
371 | */
372 | public static int px2dp(final float pxValue) {
373 | final float scale = Resources.getSystem().getDisplayMetrics().density;
374 | return (int) (pxValue / scale + 0.5f);
375 | }
376 |
377 | /**
378 | * sp转px
379 | */
380 | public static int sp2px(final float spValue) {
381 | final float fontScale = Resources.getSystem().getDisplayMetrics().scaledDensity;
382 | return (int) (spValue * fontScale + 0.5f);
383 | }
384 |
385 | /**
386 | * px转sp
387 | */
388 | public static int px2sp(final float pxValue) {
389 | final float fontScale = Resources.getSystem().getDisplayMetrics().scaledDensity;
390 | return (int) (pxValue / fontScale + 0.5f);
391 | }
392 |
393 | /**
394 | * 不同单位的值转px
395 | *
396 | * @param value
397 | * @param unit
398 | * @return
399 | */
400 | public static float applyDimension(final float value, final int unit) {
401 | DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
402 | switch (unit) {
403 | case TypedValue.COMPLEX_UNIT_PX:
404 | return value;
405 | case TypedValue.COMPLEX_UNIT_DIP:
406 | return value * metrics.density;
407 | case TypedValue.COMPLEX_UNIT_SP:
408 | return value * metrics.scaledDensity;
409 | case TypedValue.COMPLEX_UNIT_PT:
410 | return value * metrics.xdpi * (1.0f / 72);
411 | case TypedValue.COMPLEX_UNIT_IN:
412 | return value * metrics.xdpi;
413 | case TypedValue.COMPLEX_UNIT_MM:
414 | return value * metrics.xdpi * (1.0f / 25.4f);
415 | }
416 | return 0;
417 | }
418 | }
419 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/littlejerk/rvdivider/builder/XDividerDecoration.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.rvdivider.builder;
2 |
3 |
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.graphics.Rect;
7 | import android.graphics.drawable.Drawable;
8 | import android.view.View;
9 |
10 | import com.littlejerk.rvdivider.DividerHelper;
11 | import com.littlejerk.rvdivider.decoration.LDecoration;
12 |
13 | import java.util.Objects;
14 |
15 | import androidx.annotation.NonNull;
16 | import androidx.recyclerview.widget.GridLayoutManager;
17 | import androidx.recyclerview.widget.RecyclerView;
18 | import androidx.recyclerview.widget.StaggeredGridLayoutManager;
19 |
20 | import static androidx.recyclerview.widget.RecyclerView.VERTICAL;
21 | import static com.littlejerk.rvdivider.DividerHelper.DividerType.LINEAR_VERTICAL;
22 | import static com.littlejerk.rvdivider.DividerHelper.getDividerType;
23 |
24 | /**
25 | * @Author : HHotHeart
26 | * @Time : 2021/5/31 15:27
27 | * @Description : RecyclerView分割线Decoration
28 | */
29 | final class XDividerDecoration extends RecyclerView.ItemDecoration {
30 |
31 | private Builder mBuilder;
32 | private int mFullSpanPosition = -1;
33 |
34 | private XDividerDecoration() {
35 | }
36 |
37 | /**
38 | * 分割线构造器绑定
39 | *
40 | * @param builder
41 | * @return
42 | */
43 | private XDividerDecoration bind(Builder builder) {
44 | mBuilder = builder;
45 | return this;
46 | }
47 |
48 | @Override
49 | public void onDraw(@NonNull Canvas c,
50 | @NonNull RecyclerView parent,
51 | @NonNull RecyclerView.State state) {
52 | DividerHelper.DividerType type = getDividerType(parent);
53 | switch (type) {
54 | case LINEAR_HORIZONTAL:
55 | drawDividerForHLinear(c, parent, (XLinearBuilder) mBuilder);
56 | break;
57 | case LINEAR_VERTICAL:
58 | drawDividerForVLinear(c, parent, (XLinearBuilder) mBuilder);
59 | break;
60 | case GRID_VERTICAL:
61 | drawDividerForVGrid(c, parent, (XGridBuilder) mBuilder);
62 | break;
63 | case GRID_HORIZONTAL:
64 | drawDividerForHGrid(c, parent, (XGridBuilder) mBuilder);
65 | break;
66 | case STAGGERED_GRID_HORIZONTAL:
67 | case STAGGERED_GRID_VERTICAL:
68 | //瀑布流的drawable用的不多,暂时不支持,只是单纯设置分割线
69 | break;
70 | case UNKNOWN:
71 | default:
72 | super.onDraw(c, parent, state);
73 | }
74 |
75 | }
76 |
77 | @Override
78 | public void getItemOffsets(@NonNull Rect outRect,
79 | @NonNull View view,
80 | @NonNull RecyclerView parent,
81 | @NonNull RecyclerView.State state) {
82 | DividerHelper.DividerType type = getDividerType(parent);
83 | switch (type) {
84 | case LINEAR_HORIZONTAL:
85 | case LINEAR_VERTICAL:
86 | getItemOffsetsForLinear(outRect, view, parent, type);
87 | break;
88 | case GRID_VERTICAL:
89 | case GRID_HORIZONTAL:
90 | getItemOffsetsForGrid(outRect, view, parent, (XGridBuilder) mBuilder);
91 | break;
92 | case STAGGERED_GRID_VERTICAL:
93 | case STAGGERED_GRID_HORIZONTAL:
94 | getItemOffsetsForStaggeredGrid(outRect, view, parent, (XStaggeredGridBuilder) mBuilder);
95 | break;
96 | case UNKNOWN:
97 | default:
98 | super.getItemOffsets(outRect, view, parent, state);
99 | }
100 | }
101 |
102 | /**
103 | * 绘制水平方向分割线(对应LayoutManage的竖直方法)
104 | *
105 | * @param c
106 | * @param parent
107 | * @param builder
108 | */
109 | protected void drawDividerForVLinear(Canvas c, RecyclerView parent, XLinearBuilder builder) {
110 | c.save();
111 | Objects.requireNonNull(parent.getAdapter(), "RecyclerView请设置Adapter");
112 | Objects.requireNonNull(builder, "LinearLayoutManager分割线必须设置LinearBuilder");
113 | int count = builder.isShowLastLine() ? parent.getAdapter().getItemCount() : parent.getAdapter().getItemCount() - 1;
114 | int parentLPadding = builder.isIncludeParentLTPadding() ? 0 : parent.getPaddingLeft();
115 | int parentRPadding = builder.isIncludeParentRBPadding() ? 0 : parent.getPaddingRight();
116 |
117 | int childCount = parent.getChildCount();
118 | Drawable drawable = null;
119 | for (int i = 0; i < childCount; i++) {
120 | View child = parent.getChildAt(i);
121 | RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
122 | //这个才是真正的layout position
123 | int itemPosition = params.getViewLayoutPosition();
124 | LDecoration decoration = DividerHelper.getDecoration(builder, itemPosition);
125 | if (decoration != null) {
126 | drawable = decoration.getDividerDrawable();
127 | } else {
128 | drawable = builder.getDividerDrawable();
129 | }
130 | int decorationLeftPadding = DividerHelper.getDecorationLeftPadding(decoration);
131 | int decorationRightPadding = DividerHelper.getDecorationRightPadding(decoration);
132 | int leftPadding = decorationLeftPadding == 0 ? builder.getLeftPadding() : decorationLeftPadding;
133 | int rightPadding = decorationRightPadding == 0 ? builder.getRightPadding() : decorationRightPadding;
134 |
135 | int left = parentLPadding + leftPadding;
136 | int right = parent.getWidth() - parentRPadding - rightPadding;
137 | int top = child.getBottom() + params.bottomMargin;
138 | int bottom = top + builder.getSpacing();
139 |
140 | Boolean isDrawLeft = DividerHelper.isDrawEdge(decoration, DividerHelper.Edge.LEFT);
141 | Boolean isDrawRight = DividerHelper.isDrawEdge(decoration, DividerHelper.Edge.RIGHT);
142 | if (isDrawLeft != null && isDrawLeft) {
143 | int edgTop = child.getTop() + params.topMargin;
144 | int edgBottom = child.getBottom() + params.bottomMargin;
145 | int edgRight = left + builder.getSpacing();
146 | drawable.setBounds(left, edgTop, edgRight, edgBottom);
147 | drawable.draw(c);
148 | }
149 | if (isDrawRight != null && isDrawRight) {
150 | int edgTop = child.getTop() + params.topMargin;
151 | int edgBottom = child.getBottom() + params.bottomMargin;
152 | int edgLeft = right - builder.getSpacing();
153 | drawable.setBounds(edgLeft, edgTop, right, edgBottom);
154 | drawable.draw(c);
155 | }
156 |
157 | if (i == 0 && builder.isShowFirstTopLine()) {
158 | int edgBottom = child.getTop() - params.topMargin;
159 | int edgTop = edgBottom - builder.getSpacing();
160 | drawable.setBounds(left, edgTop, right, edgBottom);
161 | drawable.draw(c);
162 | }
163 | if (i < count) {
164 | drawable.setBounds(left, top, right, bottom);
165 | } else {
166 | drawable.setBounds(left, top, right, top);
167 | }
168 | drawable.draw(c);
169 | }
170 | c.restore();
171 | }
172 |
173 |
174 | /**
175 | * 绘制竖直方向分割线(对应LayoutManage的水平方法)
176 | *
177 | * @param c
178 | * @param parent
179 | * @param builder
180 | */
181 | protected void drawDividerForHLinear(Canvas c, RecyclerView parent, XLinearBuilder builder) {
182 | c.save();
183 | Objects.requireNonNull(parent.getAdapter(), "RecyclerView请设置Adapter");
184 | Objects.requireNonNull(builder, "LinearLayoutManager分割线必须设置LinearBuilder");
185 | int count = builder.isShowLastLine() ? parent.getAdapter().getItemCount() : parent.getAdapter().getItemCount() - 1;
186 | int parentTPadding = builder.isIncludeParentLTPadding() ? 0 : parent.getPaddingTop();
187 | int parentBPadding = builder.isIncludeParentRBPadding() ? 0 : parent.getPaddingBottom();
188 |
189 | int childCount = parent.getChildCount();
190 | Drawable drawable = null;
191 | for (int i = 0; i < childCount; i++) {
192 | View child = parent.getChildAt(i);
193 | RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
194 | //这个才是真正的layout position
195 | int itemPosition = params.getViewLayoutPosition();
196 | LDecoration decoration = DividerHelper.getDecoration(builder, itemPosition);
197 | if (decoration != null) {
198 | drawable = decoration.getDividerDrawable();
199 | } else {
200 | drawable = builder.getDividerDrawable();
201 | }
202 |
203 | int decorationTopPadding = DividerHelper.getDecorationTopPadding(decoration);
204 | int decorationBottomPadding = DividerHelper.getDecorationBottomPadding(decoration);
205 | int topPadding = decorationTopPadding == 0 ? builder.getLeftPadding() : decorationTopPadding;
206 | int bottomPadding = decorationBottomPadding == 0 ? builder.getRightPadding() : decorationBottomPadding;
207 |
208 | int top = parentTPadding + topPadding;
209 | int bottom = parent.getHeight() - parentBPadding - bottomPadding;
210 | int left = child.getRight() + params.rightMargin;
211 | int right = left + builder.getSpacing();
212 |
213 | Boolean isDrawTop = DividerHelper.isDrawEdge(decoration, DividerHelper.Edge.TOP);
214 | Boolean isDrawBottom = DividerHelper.isDrawEdge(decoration, DividerHelper.Edge.BOTTOM);
215 | if (isDrawTop != null && isDrawTop) {
216 | int edgLeft = child.getLeft() + params.leftMargin;
217 | int edgTop = child.getTop() - params.topMargin - builder.getSpacing();
218 | int edgRight = child.getRight() + params.rightMargin;
219 | int edgBottom = edgTop + builder.getSpacing();
220 | drawable.setBounds(edgLeft, edgTop, edgRight, edgBottom);
221 | drawable.draw(c);
222 | }
223 |
224 | if (isDrawBottom != null && isDrawBottom) {
225 | int edgTop = child.getBottom() + params.bottomMargin;
226 | int edgBottom = edgTop + builder.getSpacing();
227 | int edgLeft = child.getLeft() - params.leftMargin;
228 | int edgRight = child.getRight() + params.rightMargin;
229 | drawable.setBounds(edgLeft, edgTop, edgRight, edgBottom);
230 | drawable.draw(c);
231 | }
232 |
233 | if (i == 0 && builder.isShowFirstTopLine()) {
234 | int edgRight = child.getLeft() - params.leftMargin;
235 | int edgLeft = edgRight - builder.getSpacing();
236 | drawable.setBounds(edgLeft, top, edgRight, bottom);
237 | drawable.draw(c);
238 | }
239 |
240 | if (i < count) {
241 | drawable.setBounds(left, top, right, bottom);
242 | drawable.draw(c);
243 | } else {
244 | drawable.setBounds(left, top, left, bottom);
245 | }
246 | }
247 | c.restore();
248 | }
249 |
250 |
251 | /**
252 | * 绘制LinearLayoutManger的分割线
253 | *
254 | * @param outRect
255 | * @param view
256 | * @param parent
257 | * @param type
258 | */
259 | protected void getItemOffsetsForLinear(Rect outRect, View view, RecyclerView parent, DividerHelper.DividerType type) {
260 | XLinearBuilder builder = (XLinearBuilder) mBuilder;
261 | Objects.requireNonNull(parent.getAdapter(), "RecyclerView请设置Adapter");
262 | //最后分割线
263 | int count = parent.getAdapter().getItemCount();
264 | int itemPosition = parent.getChildAdapterPosition(view);
265 | if (builder.getOnItemNoDivider() != null && builder.getOnItemNoDivider().getNoDividerPosition() != null) {
266 | int[] noDivider = builder.getOnItemNoDivider().getNoDividerPosition();
267 | if (DividerHelper.isContains(noDivider, itemPosition)) {
268 | outRect.set(0, 0, 0, 0);
269 | return;
270 | }
271 | }
272 |
273 | LDecoration decoration = DividerHelper.getDecoration(builder, itemPosition);
274 | int dividerSpace = builder.getSpacing();
275 |
276 | if (type == LINEAR_VERTICAL) {
277 | int top = 0, bottom = dividerSpace;
278 |
279 | Boolean isDrawLeft = DividerHelper.isDrawEdge(decoration, DividerHelper.Edge.LEFT);
280 | Boolean isDrawRight = DividerHelper.isDrawEdge(decoration, DividerHelper.Edge.RIGHT);
281 |
282 | int left = isDrawLeft == null ? 0 : dividerSpace;
283 | int right = isDrawRight == null ? 0 : dividerSpace;
284 | //第一条顶部分割线
285 | if (builder.isShowFirstTopLine() && itemPosition == 0) {
286 | top = dividerSpace;
287 | }
288 | //最后分割线
289 | if (!builder.isShowLastLine() && itemPosition == count - 1) {
290 | bottom = 0;
291 | }
292 |
293 | if (itemPosition < count) {
294 | outRect.set(left, top, right, bottom);
295 | }
296 |
297 | } else {
298 | int left = 0, right = dividerSpace;
299 | Boolean isDrawTop = DividerHelper.isDrawEdge(decoration, DividerHelper.Edge.TOP);
300 | Boolean isDrawBottom = DividerHelper.isDrawEdge(decoration, DividerHelper.Edge.BOTTOM);
301 |
302 | int top = isDrawTop == null ? 0 : dividerSpace;
303 | int bottom = isDrawBottom == null ? 0 : dividerSpace;
304 |
305 | //第一条顶部分割线
306 | if (builder.isShowFirstTopLine() && itemPosition == 0) {
307 | left = dividerSpace;
308 | }
309 | //最后分割线
310 | if (!builder.isShowLastLine() && itemPosition == count - 1) {
311 | right = 0;
312 | }
313 | if (itemPosition < count) {
314 | outRect.set(left, top, right, bottom);
315 | }
316 | }
317 |
318 | }
319 |
320 |
321 | /**
322 | * 为Grid绘制有Drawable的线(GridLayoutManage方向为竖直V方向)
323 | * getItemOffsets方法限制了item的偏移量
324 | */
325 | protected void drawDividerForVGrid(Canvas c, RecyclerView parent, XGridBuilder builder) {
326 | c.save();
327 | drawHDividerForVGrid(c, parent, builder);
328 | drawVDividerForVGrid(c, parent, builder);
329 | c.restore();
330 | }
331 |
332 | /**
333 | * 为Grid画水平方向的分割线(GridLinearLayoutManage的布局方向是竖直)
334 | *
335 | * @param c
336 | * @param parent
337 | * @param builder
338 | */
339 | private void drawHDividerForVGrid(Canvas c, RecyclerView parent, XGridBuilder builder) {
340 | Objects.requireNonNull(parent.getAdapter(), "RecyclerView请设置Adapter");
341 | Objects.requireNonNull(builder, "GridLinearLayoutManage分割线必须设置GridBuilder");
342 | if (builder.getHLineDividerDrawable() == null) {
343 | return;
344 | }
345 | int hLineSpacing = builder.getHLineSpacing() == 0 ? builder.getSpacing() : builder.getHLineSpacing();
346 | int vLineSpacing = builder.getVLineSpacing() == 0 ? builder.getSpacing() : builder.getVLineSpacing();
347 |
348 | int childCount = parent.getChildCount();
349 | // int spanCount = getSpanCount(parent);
350 | GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();
351 | Objects.requireNonNull(gridLayoutManager, "RecyclerView LayoutManager请设置GridLayoutManager");
352 | GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
353 | int spanCount = gridLayoutManager.getSpanCount();
354 |
355 | for (int i = 0; i < childCount; i++) {
356 | View child = parent.getChildAt(i);
357 | RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
358 | // 当前i的itemSpanSize
359 | int itemSpanSize = spanSizeLookup.getSpanSize(i);
360 | // spanIndex = 0 表示是最左边(当前item起始的index)
361 | int spanIndex = spanSizeLookup.getSpanIndex(i, spanCount);
362 | // 行
363 | int spanGroupIndex = spanSizeLookup.getSpanGroupIndex(i, spanCount);
364 |
365 | int left = child.getLeft() - params.leftMargin;
366 | int top = child.getBottom() + params.bottomMargin;
367 | int right = child.getRight() + params.rightMargin;
368 | int bottom = top + hLineSpacing;
369 |
370 | int edgeTop = child.getTop() - params.topMargin - hLineSpacing;
371 | int edgeBottom = child.getTop() - params.topMargin;
372 | if (builder.isIncludeEdge()) {
373 | //竖直方向分割线不包括角边
374 | if (!builder.isVerticalIncludeEdge()) {
375 | // if (spanIndex == 0) {
376 | // left = left - vLineSpacing;
377 | // }
378 | //会重复绘制
379 | left = left - vLineSpacing;
380 | right = right + vLineSpacing;
381 | }
382 | //第一行
383 | if (spanGroupIndex == 0) {
384 | builder.getHLineDividerDrawable().setBounds(left, edgeTop, right, edgeBottom);
385 | builder.getHLineDividerDrawable().draw(c);
386 | }
387 | //如果item跨span
388 | if (spanGroupIndex != 0 && itemSpanSize > 1) {
389 | builder.getHLineDividerDrawable().setBounds(left, edgeTop, right, edgeBottom);
390 | builder.getHLineDividerDrawable().draw(c);
391 | }
392 | builder.getHLineDividerDrawable().setBounds(left, top, right, bottom);
393 | builder.getHLineDividerDrawable().draw(c);
394 |
395 | } else {
396 | //竖直方向分割线不包括角边
397 | if (!builder.isVerticalIncludeEdge()) {
398 | // if (spanIndex == 0) {
399 | // left = left - vLineSpacing;
400 | // }
401 | //会重复绘制
402 | left = left - vLineSpacing;
403 | right = right + vLineSpacing;
404 | }
405 | //如果item跨span
406 | if (spanGroupIndex != 0 && itemSpanSize > 1) {
407 | builder.getHLineDividerDrawable().setBounds(left, edgeTop, right, edgeBottom);
408 | builder.getHLineDividerDrawable().draw(c);
409 | }
410 | // //最后一行不绘制分割线
411 | // if (!DividerHelper.isLastRow(parent, childCount, i, itemSpanSize, spanIndex)) {
412 | // builder.getHLineDividerDrawable().setBounds(left, top, right, bottom);
413 | // builder.getHLineDividerDrawable().draw(c);
414 | // }
415 | builder.getHLineDividerDrawable().setBounds(left, top, right, bottom);
416 | builder.getHLineDividerDrawable().draw(c);
417 | }
418 | }
419 | }
420 |
421 | /**
422 | * 为Grid画竖直方向的分割线(GridLinearLayoutManage的布局方向是竖直)
423 | *
424 | * @param c
425 | * @param parent
426 | * @param builder
427 | */
428 | private void drawVDividerForVGrid(Canvas c, RecyclerView parent, XGridBuilder builder) {
429 | Objects.requireNonNull(parent.getAdapter(), "RecyclerView请设置Adapter");
430 | if (builder.getVLineDividerDrawable() == null) {
431 | return;
432 | }
433 | int hLineSpacing = builder.getHLineSpacing() == 0 ? builder.getSpacing() : builder.getHLineSpacing();
434 | int vLineSpacing = builder.getVLineSpacing() == 0 ? builder.getSpacing() : builder.getVLineSpacing();
435 |
436 | int childCount = parent.getChildCount();
437 | GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();
438 | Objects.requireNonNull(gridLayoutManager, "RecyclerView LayoutManager请设置GridLayoutManager");
439 | GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
440 | int spanCount = gridLayoutManager.getSpanCount();
441 |
442 | for (int i = 0; i < childCount; i++) {
443 | View child = parent.getChildAt(i);
444 | RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
445 | // 当前item的spanSize
446 | int spanSize = spanSizeLookup.getSpanSize(i);
447 | // spanIndex = 0 表示是最左边(当前item起始的index)
448 | int spanIndex = spanSizeLookup.getSpanIndex(i, spanCount);
449 |
450 | int left = child.getRight() + params.rightMargin;
451 | int top = child.getTop() - params.topMargin;
452 | int right = left + vLineSpacing;
453 | int bottom = child.getBottom() + params.bottomMargin;
454 |
455 | if (builder.isIncludeEdge()) {
456 | int edgeLeft = child.getLeft() - params.leftMargin - vLineSpacing;
457 | int edgeRight = child.getLeft() - params.leftMargin;
458 |
459 | if (builder.isVerticalIncludeEdge()) {
460 | top = top - hLineSpacing;
461 | bottom = bottom + hLineSpacing;
462 | }
463 | //第一列
464 | if (spanIndex == 0) {
465 | builder.getVLineDividerDrawable().setBounds(edgeLeft, top, edgeRight, bottom);
466 | builder.getVLineDividerDrawable().draw(c);
467 | }
468 |
469 | } else {
470 |
471 | if (builder.isVerticalIncludeEdge()) {
472 | bottom = bottom + hLineSpacing;
473 | // if (DividerHelper.isLastRow(parent, childCount, i, spanSize, spanIndex)) {
474 | // bottom -= hLineSpacing;
475 | // HLog.e("lastRaw:" + i);
476 | // }
477 | }
478 | }
479 | builder.getVLineDividerDrawable().setBounds(left, top, right, bottom);
480 | builder.getVLineDividerDrawable().draw(c);
481 | }
482 | }
483 |
484 |
485 | /**
486 | * 为分割线设置item偏移量
487 | *
488 | * @param outRect
489 | * @param view
490 | * @param parent
491 | * @param builder
492 | */
493 | public void getItemOffsetsForGrid(Rect outRect,
494 | View view,
495 | RecyclerView parent,
496 | XGridBuilder builder) {
497 |
498 | Objects.requireNonNull(builder, " GridLayoutManager分割线必须设置GridBuilder");
499 | int hLineSpacing = builder.getHLineSpacing() == 0 ? builder.getSpacing() : builder.getHLineSpacing();
500 | int vLineSpacing = builder.getVLineSpacing() == 0 ? builder.getSpacing() : builder.getVLineSpacing();
501 |
502 | int lastPosition = Objects.requireNonNull(parent.getAdapter(), "RecyclerView请设置Adapter").getItemCount() - 1;
503 | int position = parent.getChildAdapterPosition(view);
504 | if (position > lastPosition) {
505 | return;
506 | }
507 | GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager();
508 | Objects.requireNonNull(layoutManager, "RecyclerView LayoutManager请设置GridLayoutManager");
509 | //规则是第n列item的outRect.right + 第n+1列的outRect.left 等于 spacing,以此类推
510 | GridLayoutManager.SpanSizeLookup spanSizeLookup = layoutManager.getSpanSizeLookup();
511 | int spanCount = layoutManager.getSpanCount();
512 | // 当前position的itemSpanSize
513 | int itemSpanSize = spanSizeLookup.getSpanSize(position);
514 | // 一行几个
515 | int rowSpanCount = spanCount / itemSpanSize;
516 | // spanIndex = 0 表示是最左边,即第一列
517 | int spanIndex = spanSizeLookup.getSpanIndex(position, spanCount);
518 | // 列
519 | int column = spanIndex / itemSpanSize;
520 | // 行 可在这控制底部Footer绘制
521 | int spanGroupIndex = spanSizeLookup.getSpanGroupIndex(position, spanCount);
522 | int orientation = layoutManager.getOrientation();
523 |
524 | if (builder.isIncludeEdge()) {
525 | //包括边界:第一列的outRect.left = spacing,第column + 1 = realSpanCount列outRect.right = spacing
526 | if (orientation == VERTICAL) {
527 | outRect.left = vLineSpacing - column * vLineSpacing / rowSpanCount;
528 | outRect.right = (column + 1) * vLineSpacing / rowSpanCount;
529 | } else {
530 | outRect.top = hLineSpacing - column * hLineSpacing / rowSpanCount;
531 | outRect.bottom = (column + 1) * hLineSpacing / rowSpanCount;
532 | }
533 | //第一行才有间距
534 | if (spanGroupIndex < 1 && position < rowSpanCount) {
535 | if (orientation == VERTICAL) {
536 | // 上间距
537 | outRect.top = hLineSpacing;
538 | } else {
539 | // 左间距
540 | outRect.left = vLineSpacing;
541 | }
542 | }
543 | if (orientation == VERTICAL) {
544 | // 下边偏移量
545 | outRect.bottom = hLineSpacing;
546 | } else {
547 | // 右边偏移量
548 | outRect.right = vLineSpacing;
549 | }
550 | } else {
551 | if (orientation == VERTICAL) {
552 | outRect.left = column * vLineSpacing / rowSpanCount;
553 | outRect.right = vLineSpacing - (column + 1) * vLineSpacing / rowSpanCount;
554 | } else {
555 | outRect.top = column * hLineSpacing / rowSpanCount;
556 | outRect.bottom = hLineSpacing - (column + 1) * hLineSpacing / rowSpanCount;
557 | }
558 |
559 | if (spanGroupIndex >= 1) {
560 | if (orientation == VERTICAL) {
561 | // 超过第0行都显示上间距
562 | outRect.top = hLineSpacing;
563 | } else {
564 | // 超过第0列都显示左间距
565 | outRect.left = vLineSpacing;
566 |
567 | }
568 | }
569 | }
570 |
571 | }
572 |
573 | /**
574 | * 为Grid绘制有Drawable的线(GridLayoutManage方向为竖直H方向)
575 | */
576 | protected void drawDividerForHGrid(Canvas c, RecyclerView parent, XGridBuilder builder) {
577 | //行实际上是LayoutManager的列
578 | //列实际上是LayoutManager的行
579 | //layoutManage的方向是水平
580 | c.save();
581 | drawHDividerForHGrid(c, parent, builder);
582 | drawVDividerForHGrid(c, parent, builder);
583 | c.restore();
584 | }
585 |
586 | /**
587 | * 为Grid画水平方向的分割线(GridLinearLayoutManage的布局方向是水平)
588 | *
589 | * @param c
590 | * @param parent
591 | * @param builder
592 | */
593 | private void drawHDividerForHGrid(Canvas c, RecyclerView parent, XGridBuilder builder) {
594 | Objects.requireNonNull(builder, "GridLinearLayoutManage分割线必须设置GridBuilder");
595 | if (builder.getHLineDividerDrawable() == null) {
596 | return;
597 | }
598 | int hLineSpacing = builder.getHLineSpacing() == 0 ? builder.getSpacing() : builder.getHLineSpacing();
599 | int vLineSpacing = builder.getVLineSpacing() == 0 ? builder.getSpacing() : builder.getVLineSpacing();
600 |
601 | int childCount = parent.getChildCount();
602 | // int spanCount = DividerHelper.getSpanCount(parent);
603 | GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();
604 | Objects.requireNonNull(gridLayoutManager, "RecyclerView LayoutManager请设置GridLayoutManager");
605 | GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
606 | int spanCount = gridLayoutManager.getSpanCount();
607 |
608 | for (int i = 0; i < childCount; i++) {
609 | View child = parent.getChildAt(i);
610 | RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
611 | // 当前i的itemSpanSize
612 | int itemSpanSize = spanSizeLookup.getSpanSize(i);
613 | // spanIndex = 0 表示是最左边(当前item起始的index)
614 | int spanIndex = spanSizeLookup.getSpanIndex(i, spanCount);
615 | // 行
616 | int spanGroupIndex = spanSizeLookup.getSpanGroupIndex(i, spanCount);
617 |
618 | int left = child.getLeft() - params.leftMargin;
619 | int top = child.getBottom() + params.bottomMargin;
620 | int right = child.getRight() + params.rightMargin;
621 | int bottom = top + hLineSpacing;
622 |
623 | if (builder.isIncludeEdge()) {
624 | int edgeTop = child.getTop() - params.topMargin - hLineSpacing;
625 | int edgeBottom = child.getTop() - params.topMargin;
626 | if (!builder.isVerticalIncludeEdge()) {
627 | // //第一列
628 | // if (spanGroupIndex == 0) {
629 | // left = left - vLineSpacing;
630 | //
631 | // }
632 | //会重复绘制
633 | left = left - vLineSpacing;
634 | right = right + vLineSpacing;
635 | }
636 | //第一行
637 | if (spanIndex == 0) {
638 | builder.getHLineDividerDrawable().setBounds(left, edgeTop, right, edgeBottom);
639 | builder.getHLineDividerDrawable().draw(c);
640 | }
641 |
642 | } else {
643 | if (!builder.isVerticalIncludeEdge()) {
644 | //非最最后一列
645 | if (!DividerHelper.isLastColumn(parent, childCount, i)) {
646 | right = right + vLineSpacing;
647 | }
648 |
649 | }
650 | }
651 | builder.getHLineDividerDrawable().setBounds(left, top, right, bottom);
652 | builder.getHLineDividerDrawable().draw(c);
653 | }
654 | }
655 |
656 | /**
657 | * 为Grid画竖直方向的分割线(GridLinearLayoutManage的布局方向是水平)
658 | *
659 | * @param c
660 | * @param parent
661 | * @param builder
662 | */
663 | private void drawVDividerForHGrid(Canvas c, RecyclerView parent, XGridBuilder builder) {
664 | Objects.requireNonNull(builder, "GridLinearLayoutManage分割线必须设置GridBuilder");
665 | if (builder.getVLineDividerDrawable() == null) {
666 | return;
667 | }
668 | int hLineSpacing = builder.getHLineSpacing() == 0 ? builder.getSpacing() : builder.getHLineSpacing();
669 | int vLineSpacing = builder.getVLineSpacing() == 0 ? builder.getSpacing() : builder.getVLineSpacing();
670 |
671 | int childCount = parent.getChildCount();
672 | GridLayoutManager gridLayoutManager = (GridLayoutManager) parent.getLayoutManager();
673 | Objects.requireNonNull(gridLayoutManager, "RecyclerView LayoutManager请设置GridLayoutManager");
674 | GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup();
675 | int spanCount = gridLayoutManager.getSpanCount();
676 |
677 | for (int i = 0; i < childCount; i++) {
678 | View child = parent.getChildAt(i);
679 | RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
680 | // 当前i的itemSpanSize
681 | int itemSpanSize = spanSizeLookup.getSpanSize(i);
682 | // spanIndex = 0 表示是最左边(当前item起始的index)
683 | int spanIndex = spanSizeLookup.getSpanIndex(i, spanCount);
684 | // 行
685 | int spanGroupIndex = spanSizeLookup.getSpanGroupIndex(i, spanCount);
686 |
687 | //绘制item右边界
688 | int left = child.getRight() + params.rightMargin;
689 | int top = child.getTop() - params.topMargin;
690 | int right = left + vLineSpacing;
691 | int bottom = child.getBottom() + params.bottomMargin;
692 |
693 | if (builder.isIncludeEdge()) {
694 | if (builder.isVerticalIncludeEdge()) {
695 | //第一行
696 | if (spanIndex == 0) {
697 | top = top - hLineSpacing;
698 | }
699 | bottom = bottom + hLineSpacing;
700 | }
701 | //第一列
702 | if (spanGroupIndex == 0) {
703 | int edgeLeft = child.getLeft() - params.leftMargin - vLineSpacing;
704 | int edgeRight = child.getLeft() - params.leftMargin;
705 | builder.getVLineDividerDrawable().setBounds(edgeLeft, top, edgeRight, bottom);
706 | builder.getVLineDividerDrawable().draw(c);
707 | }
708 | builder.getVLineDividerDrawable().setBounds(left, top, right, bottom);
709 | builder.getVLineDividerDrawable().draw(c);
710 | } else {
711 | if (builder.isVerticalIncludeEdge()) {
712 | bottom = bottom + hLineSpacing;
713 | }
714 | // //最后一行
715 | // if (spanIndex + itemSpanSize == spanCount) {
716 | // HLog.e("ttt", i + "");
717 | // bottom -= hLineSpacing;
718 | // }
719 | //非最最后一列
720 | if (!DividerHelper.isLastColumn(parent, childCount, i)) {
721 | builder.getVLineDividerDrawable().setBounds(left, top, right, bottom);
722 | builder.getVLineDividerDrawable().draw(c);
723 | }
724 | }
725 | //处理item跨多个span的情况(会重复绘制)
726 | if (spanGroupIndex != 0) {
727 | int edgeLeft = child.getLeft() - params.leftMargin - vLineSpacing;
728 | int edgeRight = child.getLeft() - params.leftMargin;
729 | builder.getVLineDividerDrawable().setBounds(edgeLeft, top, edgeRight, bottom);
730 | builder.getVLineDividerDrawable().draw(c);
731 | }
732 | }
733 | }
734 |
735 |
736 | /**
737 | * 为分割线设置item偏移量
738 | *
739 | * @param outRect
740 | * @param view
741 | * @param parent
742 | * @param builder
743 | */
744 | public void getItemOffsetsForStaggeredGrid(Rect outRect, View view,
745 | RecyclerView parent,
746 | XStaggeredGridBuilder builder) {
747 | Objects.requireNonNull(builder, "GridLinearLayoutManage分割线必须设置XStaggeredGridBuilder");
748 | int hLineSpacing = builder.getHLineSpacing() == 0 ? builder.getSpacing() : builder.getHLineSpacing();
749 | int vLineSpacing = builder.getVLineSpacing() == 0 ? builder.getSpacing() : builder.getVLineSpacing();
750 |
751 | int lastPosition = Objects.requireNonNull(parent.getAdapter(), "RecyclerView请设置Adapter").getItemCount() - 1;
752 | int position = parent.getChildAdapterPosition(view);
753 | if (position > lastPosition) {
754 | return;
755 | }
756 | StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) parent.getLayoutManager();
757 | Objects.requireNonNull(layoutManager, "RecyclerView LayoutManager请设置StaggeredGridLayoutManager");
758 | // 瀑布流获取列方式不一样
759 | StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
760 | // 瀑布流item处于那一列
761 | int column = params.getSpanIndex();
762 | // 瀑布流是否占满一行
763 | boolean isFullSpan = params.isFullSpan();
764 | int spanCount = layoutManager.getSpanCount();
765 | //真正的spanCount
766 | spanCount = spanCount / (isFullSpan ? spanCount : 1);
767 | int orientation = layoutManager.getOrientation();
768 |
769 | if (builder.isIncludeEdge()) {
770 | if (isFullSpan && !builder.isIgnoreFullSpan()) {
771 | outRect.left = 0;
772 | outRect.right = 0;
773 | } else {
774 | if (orientation == VERTICAL) {
775 | outRect.left = vLineSpacing - column * vLineSpacing / spanCount;
776 | outRect.right = (column + 1) * vLineSpacing / spanCount;
777 | } else {
778 | outRect.top = hLineSpacing - column * hLineSpacing / spanCount;
779 | outRect.bottom = (column + 1) * hLineSpacing / spanCount;
780 | }
781 | }
782 |
783 | // 找到头部第一个整行的position,后面的上间距都不显示
784 | if (mFullSpanPosition == -1 && position < spanCount && isFullSpan) {
785 | mFullSpanPosition = position;
786 | }
787 | //显示上间距: 头部没有整行||头部体验整行但是在之前的position
788 | boolean isFirstLineStagger = (mFullSpanPosition == -1 || position < mFullSpanPosition) && (position < spanCount);
789 | if (isFirstLineStagger) {
790 | if (orientation == VERTICAL) {
791 | // 上间距
792 | outRect.top = hLineSpacing;
793 | } else {
794 | // 左间距
795 | outRect.left = vLineSpacing;
796 | }
797 | }
798 | if (orientation == VERTICAL) {
799 | // 底部偏移量
800 | outRect.bottom = hLineSpacing;
801 | } else {
802 | // 右边偏移量
803 | outRect.right = vLineSpacing;
804 | }
805 | } else {
806 | if (isFullSpan && !builder.isIgnoreFullSpan()) {
807 | outRect.left = 0;
808 | outRect.right = 0;
809 | } else {
810 | if (orientation == VERTICAL) {
811 | outRect.left = column * vLineSpacing / spanCount;
812 | outRect.right = vLineSpacing - (column + 1) * vLineSpacing / spanCount;
813 | } else {
814 | outRect.top = column * hLineSpacing / spanCount;
815 | outRect.bottom = hLineSpacing - (column + 1) * hLineSpacing / spanCount;
816 | }
817 | }
818 |
819 | // 找到头部第一个整行的position
820 | if (mFullSpanPosition == -1 && position < spanCount && isFullSpan) {
821 | mFullSpanPosition = position;
822 | }
823 | // 上间距显示规则
824 | boolean isStaggerShowTop = position >= spanCount || (isFullSpan && position != 0) || (mFullSpanPosition != -1 && position != 0);
825 |
826 | if (isStaggerShowTop) {
827 | if (orientation == VERTICAL) {
828 | // 超过第0行都显示上间距
829 | outRect.top = hLineSpacing;
830 | } else {
831 | // 超过第0列都显示左间距
832 | outRect.left = vLineSpacing;
833 | }
834 | }
835 | }
836 |
837 |
838 | }
839 |
840 | /**
841 | * 提供初始化XDividerDecoration
842 | */
843 | protected static class Builder {
844 | //上下文
845 | protected Context mContext;
846 |
847 | protected Builder(Context context) {
848 | this.mContext = context;
849 | }
850 |
851 | /**
852 | * XDividerDecoration初始化
853 | *
854 | * @return RecyclerView.ItemDecoration
855 | */
856 | public RecyclerView.ItemDecoration build() {
857 | return new XDividerDecoration().bind(this);
858 | }
859 |
860 | }
861 |
862 | }
863 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/littlejerk/rvdivider/builder/XGridBuilder.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.rvdivider.builder;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.graphics.drawable.ColorDrawable;
6 | import android.graphics.drawable.Drawable;
7 | import android.util.TypedValue;
8 |
9 | import com.littlejerk.rvdivider.DividerHelper;
10 |
11 | import androidx.annotation.ColorInt;
12 | import androidx.annotation.ColorRes;
13 | import androidx.annotation.DimenRes;
14 | import androidx.annotation.DrawableRes;
15 | import androidx.core.content.ContextCompat;
16 |
17 | import static com.littlejerk.rvdivider.DividerHelper.NO_COLOR;
18 |
19 | /**
20 | * @Author : HHotHeart
21 | * @Time : 2021/5/31 15:30
22 | * @Description : GridLayoutManager分割线构造器
23 | */
24 | public final class XGridBuilder extends XDividerDecoration.Builder {
25 |
26 | /**
27 | * 分割线宽或高,mVLineSpacing||mHLineSpacing > mSpacing
28 | */
29 | private int mVLineSpacing;
30 | private int mHLineSpacing;
31 | private int mSpacing;
32 | /**
33 | * 是否需要画边界
34 | */
35 | private boolean mIsIncludeEdge;
36 | /**
37 | * 竖直方向分割线是否包括item角边的距离
38 | */
39 | private boolean mVerticalIncludeEdge;
40 | /**
41 | * 分割线颜色,mVLineColor||mHLineColor > mColor
42 | */
43 | private int mVLineColor = NO_COLOR;
44 | private int mHLineColor = NO_COLOR;
45 | private int mColor = NO_COLOR;
46 | /**
47 | * 分割线drawable,mVLineDividerDrawable||mHLineDividerDrawable > mDividerDrawable
48 | */
49 | private Drawable mVLineDividerDrawable;
50 | private Drawable mHLineDividerDrawable;
51 | private Drawable mDividerDrawable;
52 |
53 | public XGridBuilder(Context context) {
54 | super(context);
55 | }
56 |
57 | public int getSpacing() {
58 | return mSpacing;
59 | }
60 |
61 | /**
62 | * 设置分割线间距
63 | *
64 | * @param dpValueSpacing
65 | * @return
66 | */
67 | public XGridBuilder setSpacing(float dpValueSpacing) {
68 | this.mSpacing = (int) DividerHelper.applyDimension(dpValueSpacing, TypedValue.COMPLEX_UNIT_DIP);
69 | return this;
70 | }
71 |
72 | /**
73 | * 设置分割线间距
74 | *
75 | * @param dimenResId
76 | * @return
77 | */
78 | public XGridBuilder setSpacing(@DimenRes int dimenResId) {
79 | this.mSpacing = Resources.getSystem().getDimensionPixelSize(dimenResId);
80 | return this;
81 |
82 | }
83 |
84 | public int getVLineSpacing() {
85 | return mVLineSpacing;
86 | }
87 |
88 | /**
89 | * 设置竖直线间距
90 | *
91 | * @param dpValueVLineSpacing
92 | * @return
93 | */
94 | public XGridBuilder setVLineSpacing(float dpValueVLineSpacing) {
95 | this.mVLineSpacing = (int) DividerHelper.applyDimension(dpValueVLineSpacing, TypedValue.COMPLEX_UNIT_DIP);
96 | return this;
97 | }
98 |
99 | public XGridBuilder setVLineSpacing(@DimenRes int dimenResId) {
100 | this.mVLineSpacing = Resources.getSystem().getDimensionPixelSize(dimenResId);
101 | return this;
102 | }
103 |
104 |
105 | public int getHLineSpacing() {
106 | return mHLineSpacing;
107 | }
108 |
109 | /**
110 | * 设置水平线间距
111 | *
112 | * @param dpValueHLineSpacing
113 | * @return
114 | */
115 | public XGridBuilder setHLineSpacing(float dpValueHLineSpacing) {
116 | this.mHLineSpacing = (int) DividerHelper.applyDimension(dpValueHLineSpacing, TypedValue.COMPLEX_UNIT_DIP);
117 | return this;
118 |
119 | }
120 |
121 | public XGridBuilder setHLineSpacing(@DimenRes int dimenResId) {
122 | this.mHLineSpacing = Resources.getSystem().getDimensionPixelSize(dimenResId);
123 | return this;
124 | }
125 |
126 | public boolean isIncludeEdge() {
127 | return mIsIncludeEdge;
128 | }
129 |
130 | /**
131 | * 设置是否包含边界
132 | *
133 | * @param includeEdge
134 | * @return
135 | */
136 | public XGridBuilder setIncludeEdge(boolean includeEdge) {
137 | mIsIncludeEdge = includeEdge;
138 | return this;
139 | }
140 |
141 | public boolean isVerticalIncludeEdge() {
142 | return mVerticalIncludeEdge;
143 | }
144 |
145 | /**
146 | * 设置边界是否包含于竖直方向上的分割线
147 | *
148 | * @param verticalIncludeEdge
149 | * @return
150 | */
151 | public XGridBuilder setVerticalIncludeEdge(boolean verticalIncludeEdge) {
152 | this.mVerticalIncludeEdge = verticalIncludeEdge;
153 | return this;
154 | }
155 |
156 |
157 | public int getVLineColor() {
158 | return mVLineColor;
159 | }
160 |
161 | /**
162 | * 设置竖直分割线颜色
163 | *
164 | * @param vLineColor
165 | * @return
166 | */
167 | public XGridBuilder setVLineColor(@ColorInt int vLineColor) {
168 | this.mVLineColor = vLineColor;
169 | return this;
170 | }
171 |
172 | /**
173 | * 通过资源id设置竖直分割线颜色
174 | *
175 | * @param colorResId
176 | * @return
177 | */
178 | public XGridBuilder setVLineColorRes(@ColorRes int colorResId) {
179 | setVLineColor(ContextCompat.getColor(mContext, colorResId));
180 | return this;
181 | }
182 |
183 |
184 | public int getHLineColor() {
185 | return mHLineColor;
186 | }
187 |
188 | /**
189 | * 设置水平分割线颜色
190 | *
191 | * @param hLineColor
192 | * @return
193 | */
194 | public XGridBuilder setHLineColor(@ColorInt int hLineColor) {
195 | this.mHLineColor = hLineColor;
196 | return this;
197 | }
198 |
199 | /**
200 | * 通过资源id设置水平分割线颜色
201 | *
202 | * @param colorResId
203 | * @return
204 | */
205 | public XGridBuilder setHLineColorRes(@ColorRes int colorResId) {
206 | setHLineColor(ContextCompat.getColor(mContext, colorResId));
207 | return this;
208 | }
209 |
210 |
211 | /**
212 | * 通过资源id设置颜色
213 | *
214 | * @param colorResId
215 | * @return
216 | */
217 | public XGridBuilder setColorRes(@ColorRes int colorResId) {
218 | setColor(ContextCompat.getColor(mContext, colorResId));
219 | return this;
220 | }
221 |
222 |
223 | /**
224 | * 设置颜色,如果不设置mHLineColor的颜色,默认水平方向和竖直共用此颜色
225 | *
226 | * @param color
227 | * @return
228 | */
229 | public XGridBuilder setColor(@ColorInt int color) {
230 | mColor = color;
231 | return this;
232 | }
233 |
234 | /**
235 | * 获取颜色值
236 | *
237 | * @return
238 | */
239 | protected int getColor() {
240 | return mColor;
241 | }
242 |
243 | /**
244 | * 设置竖直方向分割线的drawable
245 | *
246 | * @param vLineDividerDrawable
247 | * @return
248 | */
249 | public XGridBuilder setVLineDrawable(Drawable vLineDividerDrawable) {
250 | this.mVLineDividerDrawable = vLineDividerDrawable;
251 | return this;
252 | }
253 |
254 | /**
255 | * 通过资源id设置竖直方向分割线的drawable
256 | */
257 | public XGridBuilder setVLineDrawableRes(@DrawableRes int drawableResId) {
258 | setVLineDrawable(ContextCompat.getDrawable(mContext, drawableResId));
259 | return this;
260 | }
261 |
262 | /**
263 | * 设置水平方向分割线的drawable
264 | *
265 | * @param hLineDividerDrawable
266 | * @return
267 | */
268 | public XGridBuilder setHLineDrawable(Drawable hLineDividerDrawable) {
269 | this.mHLineDividerDrawable = hLineDividerDrawable;
270 | return this;
271 | }
272 |
273 | /**
274 | * 通过资源id设置水平方向分割线的drawable
275 | */
276 | public XGridBuilder setHLineDrawableRes(@DrawableRes int drawableResId) {
277 | setHLineDrawable(ContextCompat.getDrawable(mContext, drawableResId));
278 | return this;
279 | }
280 |
281 | /**
282 | * 通过资源id设置Drawable
283 | */
284 | public XGridBuilder setDrawableRes(@DrawableRes int drawableResId) {
285 | setDrawable(ContextCompat.getDrawable(mContext, drawableResId));
286 | return this;
287 | }
288 |
289 | /**
290 | * 设置分割线Drawable
291 | */
292 | public XGridBuilder setDrawable(Drawable drawable) {
293 | mDividerDrawable = drawable;
294 | return this;
295 | }
296 |
297 | /**
298 | * 获取分割线Drawable
299 | *
300 | * @return
301 | */
302 | public Drawable getVLineDividerDrawable() {
303 | //创建Drawable
304 | if (mVLineDividerDrawable == null) {
305 | if (mVLineColor == NO_COLOR) {
306 | if (mDividerDrawable == null) {
307 | if (mColor != NO_COLOR) {
308 | mVLineDividerDrawable = new ColorDrawable(mColor);
309 | }
310 | } else {
311 | mVLineDividerDrawable = mDividerDrawable;
312 | }
313 | } else {
314 | mVLineDividerDrawable = new ColorDrawable(mVLineColor);
315 | }
316 | }
317 | return mVLineDividerDrawable;
318 | }
319 |
320 |
321 | /**
322 | * 获取分割线Drawable
323 | *
324 | * @return
325 | */
326 | public Drawable getHLineDividerDrawable() {
327 | //创建Drawable
328 | if (mHLineDividerDrawable == null) {
329 | if (mHLineColor == NO_COLOR) {
330 | if (mDividerDrawable == null) {
331 | if (mColor != NO_COLOR) {
332 | mHLineDividerDrawable = new ColorDrawable(mColor);
333 | }
334 | } else {
335 | mHLineDividerDrawable = mDividerDrawable;
336 | }
337 | } else {
338 | mHLineDividerDrawable = new ColorDrawable(mHLineColor);
339 | }
340 | }
341 | return mHLineDividerDrawable;
342 | }
343 | }
344 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/littlejerk/rvdivider/builder/XLinearBuilder.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.rvdivider.builder;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.graphics.drawable.ColorDrawable;
6 | import android.graphics.drawable.Drawable;
7 | import android.util.TypedValue;
8 |
9 | import com.littlejerk.rvdivider.DividerHelper;
10 | import com.littlejerk.rvdivider.decoration.ILDecoration;
11 | import com.littlejerk.rvdivider.decoration.LDecoration;
12 |
13 | import androidx.annotation.ColorInt;
14 | import androidx.annotation.ColorRes;
15 | import androidx.annotation.DimenRes;
16 | import androidx.annotation.DrawableRes;
17 | import androidx.core.content.ContextCompat;
18 |
19 |
20 | /**
21 | * @Author : HHotHeart
22 | * @Time : 2021/5/31 15:25
23 | * @Description : LinearLayoutManager分割线构造器
24 | */
25 | public final class XLinearBuilder extends XDividerDecoration.Builder implements ILDecoration {
26 |
27 | /**
28 | * 默认分割线的宽(高)度,单位像素px
29 | */
30 | private int mSpacing = DividerHelper.dp2px(1);
31 | /**
32 | * 是否绘制最后一条分割线
33 | */
34 | private boolean mShowLastLine = false;
35 | /**
36 | * 是否绘制第一个item的顶部分割线
37 | */
38 | private boolean mShowFirstTopLine = false;
39 | /**
40 | * 是否绘制RecyclerView的左右padding(竖直)或上下padding(水平)
41 | */
42 | private boolean mIsIncludeParentLTPadding = false;
43 | private boolean mIsIncludeParentRBPadding = false;
44 | /**
45 | * 分割线左右内边距(垂直)
46 | */
47 | private int mLeftPadding = 0;
48 | private int mRightPadding = 0;
49 | /**
50 | * 分割线上下内边距(水平)
51 | */
52 | private int mTopPadding = 0;
53 | private int mBottomPadding = 0;
54 | /**
55 | * 分割线颜色或背景
56 | */
57 | private int mColor;
58 | private Drawable mDividerDrawable;
59 | /**
60 | * 不画分割线position的回调
61 | */
62 | private OnNoDividerPosition mOnNoDividerPosition;
63 | /**
64 | * item分割线绘制回调
65 | */
66 | private OnItemDivider mOnItemDivider;
67 |
68 | public XLinearBuilder(Context context) {
69 | super(context);
70 | }
71 |
72 | /**
73 | * 设置分割线宽(高)度
74 | */
75 | public XLinearBuilder setSpacing(float dpValueSpanSpace) {
76 | mSpacing = (int) DividerHelper.applyDimension(dpValueSpanSpace, TypedValue.COMPLEX_UNIT_DIP);
77 | return this;
78 | }
79 |
80 | /**
81 | * 设置分割线宽(高)度
82 | */
83 | public XLinearBuilder setSpacing(@DimenRes int dimenResId) {
84 | mSpacing = Resources.getSystem().getDimensionPixelSize(dimenResId);
85 | return this;
86 | }
87 |
88 | /**
89 | * 设置左右间距
90 | */
91 | @Override
92 | public XLinearBuilder setPadding(float dpValuePadding) {
93 | setLeftPadding(dpValuePadding);
94 | setRightPadding(dpValuePadding);
95 | setTopPadding(dpValuePadding);
96 | setBottomPadding(dpValuePadding);
97 | return this;
98 | }
99 |
100 | /**
101 | * 设置左右间距
102 | */
103 | @Override
104 | public XLinearBuilder setPadding(@DimenRes int dimenResId) {
105 | setLeftPadding(dimenResId);
106 | setRightPadding(dimenResId);
107 | setTopPadding(dimenResId);
108 | setBottomPadding(dimenResId);
109 | return this;
110 | }
111 |
112 | /**
113 | * 设置左间距
114 | */
115 | @Override
116 | public XLinearBuilder setLeftPadding(float dpValuePadding) {
117 | mLeftPadding = (int) DividerHelper.applyDimension(dpValuePadding, TypedValue.COMPLEX_UNIT_DIP);
118 | return this;
119 | }
120 |
121 | /**
122 | * 设置右间距
123 | */
124 | @Override
125 | public XLinearBuilder setRightPadding(float dpValuePadding) {
126 | mRightPadding = (int) DividerHelper.applyDimension(dpValuePadding, TypedValue.COMPLEX_UNIT_DIP);
127 | return this;
128 | }
129 |
130 | /**
131 | * 通过资源id设置左间距
132 | */
133 | @Override
134 | public XLinearBuilder setLeftPadding(@DimenRes int dimenResId) {
135 | mLeftPadding = Resources.getSystem().getDimensionPixelSize(dimenResId);
136 | return this;
137 | }
138 |
139 | /**
140 | * 通过资源id设置右间距
141 | */
142 | @Override
143 | public XLinearBuilder setRightPadding(@DimenRes int dimenResId) {
144 | mRightPadding = Resources.getSystem().getDimensionPixelSize(dimenResId);
145 | return this;
146 | }
147 |
148 | /**
149 | * 设置上间距
150 | */
151 | @Override
152 | public XLinearBuilder setTopPadding(float dpValuePadding) {
153 | mTopPadding = (int) DividerHelper.applyDimension(dpValuePadding, TypedValue.COMPLEX_UNIT_DIP);
154 | return this;
155 | }
156 |
157 | /**
158 | * 设置下间距
159 | */
160 | @Override
161 | public XLinearBuilder setBottomPadding(float dpValuePadding) {
162 | mBottomPadding = (int) DividerHelper.applyDimension(dpValuePadding, TypedValue.COMPLEX_UNIT_DIP);
163 | return this;
164 | }
165 |
166 | /**
167 | * 通过资源id设置上间距
168 | */
169 | @Override
170 | public XLinearBuilder setTopPadding(@DimenRes int dimenResId) {
171 | mTopPadding = Resources.getSystem().getDimensionPixelSize(dimenResId);
172 | return this;
173 | }
174 |
175 | /**
176 | * 通过资源id设置下间距
177 | */
178 | @Override
179 | public XLinearBuilder setBottomPadding(@DimenRes int dimenResId) {
180 | mBottomPadding = Resources.getSystem().getDimensionPixelSize(dimenResId);
181 | return this;
182 | }
183 |
184 | /**
185 | * 设置是否展示最后分割线
186 | *
187 | * @param showLastLine
188 | * @return
189 | */
190 | public XLinearBuilder setShowLastLine(boolean showLastLine) {
191 | mShowLastLine = showLastLine;
192 | return this;
193 | }
194 |
195 | /**
196 | * 设置是否展示第一个item顶部分割线
197 | *
198 | * @param showFirstTopLine
199 | * @return
200 | */
201 | public XLinearBuilder setShowFirstTopLine(boolean showFirstTopLine) {
202 | this.mShowFirstTopLine = showFirstTopLine;
203 | return this;
204 | }
205 |
206 | /**
207 | * 是否展示顶部分割线
208 | *
209 | * @return
210 | */
211 | public boolean isShowFirstTopLine() {
212 | return mShowFirstTopLine;
213 | }
214 |
215 | /**
216 | * 是否最后一条显示分割线
217 | *
218 | * @return
219 | */
220 | public boolean isShowLastLine() {
221 | return mShowLastLine;
222 | }
223 |
224 | /**
225 | * 是否忽略RecyclerView的padding
226 | *
227 | * @return
228 | */
229 | public boolean isIncludeParentLTPadding() {
230 | return mIsIncludeParentLTPadding;
231 | }
232 |
233 | public boolean isIncludeParentRBPadding() {
234 | return mIsIncludeParentRBPadding;
235 | }
236 |
237 | /**
238 | * 设置是否忽略RecyclerView的padding
239 | *
240 | * @param includeParentLTPadding
241 | * @param includeParentRBPadding
242 | * @return
243 | */
244 | public XLinearBuilder setIncludeParentHVPadding(boolean includeParentLTPadding, boolean includeParentRBPadding) {
245 | mIsIncludeParentLTPadding = includeParentLTPadding;
246 | mIsIncludeParentRBPadding = includeParentRBPadding;
247 | return this;
248 | }
249 |
250 | /**
251 | * 获取分割线宽(高)度
252 | *
253 | * @return
254 | */
255 | public int getSpacing() {
256 | return mSpacing;
257 | }
258 |
259 | /**
260 | * 获取分割线左内边距
261 | *
262 | * @return
263 | */
264 | @Override
265 | public int getLeftPadding() {
266 | return mLeftPadding;
267 | }
268 |
269 | /**
270 | * 获取分割线右内边距
271 | *
272 | * @return
273 | */
274 | @Override
275 | public int getRightPadding() {
276 | return mRightPadding;
277 | }
278 |
279 | /**
280 | * 获取分割线上内边距
281 | *
282 | * @return
283 | */
284 | @Override
285 | public int getTopPadding() {
286 | return mTopPadding;
287 | }
288 |
289 | /**
290 | * 获取分割线下内边距
291 | *
292 | * @return
293 | */
294 | @Override
295 | public int getBottomPadding() {
296 | return mBottomPadding;
297 | }
298 |
299 |
300 | /**
301 | * 通过资源id设置颜色
302 | */
303 | @Override
304 | public XLinearBuilder setColorRes(@ColorRes int colorResId) {
305 | setColor(ContextCompat.getColor(mContext, colorResId));
306 | return this;
307 | }
308 |
309 | /**
310 | * 设置颜色
311 | */
312 | @Override
313 | public XLinearBuilder setColor(@ColorInt int color) {
314 | mColor = color;
315 | return this;
316 | }
317 |
318 | /**
319 | * 获取颜色值
320 | *
321 | * @return
322 | */
323 | protected int getColor() {
324 | return mColor;
325 | }
326 |
327 |
328 | /**
329 | * 通过资源id设置Drawable
330 | */
331 | @Override
332 | public XLinearBuilder setDrawableRes(@DrawableRes int drawableResId) {
333 | setDrawable(ContextCompat.getDrawable(mContext, drawableResId));
334 | return this;
335 | }
336 |
337 | /**
338 | * 设置分割线Drawable
339 | */
340 | @Override
341 | public XLinearBuilder setDrawable(Drawable drawable) {
342 | mDividerDrawable = drawable;
343 | return this;
344 | }
345 |
346 |
347 | /**
348 | * 获取分割线Drawable
349 | *
350 | * @return
351 | */
352 | @Override
353 | public Drawable getDividerDrawable() {
354 | //创建Drawable
355 | if (mDividerDrawable == null) {
356 | mDividerDrawable = new ColorDrawable(mColor);
357 | }
358 | return mDividerDrawable;
359 | }
360 |
361 |
362 | /**
363 | * 获取回调
364 | *
365 | * @return
366 | */
367 | public OnNoDividerPosition getOnItemNoDivider() {
368 | return mOnNoDividerPosition;
369 | }
370 |
371 | /**
372 | * 设置不画分割线position的回调
373 | *
374 | * @param onNoDividerPosition
375 | * @return
376 | */
377 | public XLinearBuilder setOnItemNoDivider(OnNoDividerPosition onNoDividerPosition) {
378 | this.mOnNoDividerPosition = onNoDividerPosition;
379 | return this;
380 | }
381 |
382 | /**
383 | * 是否画分割线的回调
384 | */
385 | public interface OnNoDividerPosition {
386 | int[] getNoDividerPosition();
387 | }
388 |
389 |
390 | /**
391 | * 获取分割线绘制的回调
392 | *
393 | * @return
394 | */
395 | public OnItemDivider getItemDividerDecoration() {
396 | return mOnItemDivider;
397 | }
398 |
399 | /**
400 | * 设置分割线绘制监听
401 | *
402 | * @param onItemDivider
403 | * @return
404 | */
405 | public XLinearBuilder setOnItemDividerDecoration(OnItemDivider onItemDivider) {
406 | this.mOnItemDivider = onItemDivider;
407 | return this;
408 | }
409 |
410 | public interface OnItemDivider {
411 | LDecoration getItemDividerDecoration(int position);
412 | }
413 |
414 | }
415 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/littlejerk/rvdivider/builder/XStaggeredGridBuilder.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.rvdivider.builder;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.util.TypedValue;
6 |
7 | import com.littlejerk.rvdivider.DividerHelper;
8 |
9 | import androidx.annotation.DimenRes;
10 |
11 | /**
12 | * @Author : HHotHeart
13 | * @Time : 2021/5/31 15:38
14 | * @Description : StaggeredGridLayoutManager分割线构造器(不支持draw颜色设置)
15 | */
16 | public final class XStaggeredGridBuilder extends XDividerDecoration.Builder {
17 |
18 | /**
19 | * 分割线宽或高,mVLineSpacing||mHLineSpacing > mSpacing
20 | */
21 | private int mVLineSpacing;
22 | private int mHLineSpacing;
23 | private int mSpacing;
24 | /**
25 | * 是否需要画边界
26 | */
27 | private boolean mIsIncludeEdge;
28 | /**
29 | * 是否忽略fullSpan的情况
30 | */
31 | private boolean mIsIgnoreFullSpan = false;
32 |
33 | public XStaggeredGridBuilder(Context context) {
34 | super(context);
35 | }
36 |
37 | public int getSpacing() {
38 | return mSpacing;
39 | }
40 |
41 | /**
42 | * 设置分割线间距
43 | *
44 | * @param dpValueSpacing
45 | * @return
46 | */
47 | public XStaggeredGridBuilder setSpacing(float dpValueSpacing) {
48 | this.mSpacing = (int) DividerHelper.applyDimension(dpValueSpacing, TypedValue.COMPLEX_UNIT_DIP);
49 | return this;
50 | }
51 |
52 | /**
53 | * 设置分割线间距
54 | *
55 | * @param dimenResId
56 | * @return
57 | */
58 | public XStaggeredGridBuilder setSpacing(@DimenRes int dimenResId) {
59 | this.mSpacing = Resources.getSystem().getDimensionPixelSize(dimenResId);
60 | return this;
61 |
62 | }
63 |
64 | public int getVLineSpacing() {
65 | return mVLineSpacing;
66 | }
67 |
68 | /**
69 | * 设置竖直线间距
70 | *
71 | * @param dpValueVLineSpacing
72 | * @return
73 | */
74 | public XStaggeredGridBuilder setVLineSpacing(float dpValueVLineSpacing) {
75 | this.mVLineSpacing = (int) DividerHelper.applyDimension(dpValueVLineSpacing, TypedValue.COMPLEX_UNIT_DIP);
76 | return this;
77 | }
78 |
79 | public XStaggeredGridBuilder setVLineSpacing(@DimenRes int dimenResId) {
80 | this.mVLineSpacing = Resources.getSystem().getDimensionPixelSize(dimenResId);
81 | return this;
82 | }
83 |
84 |
85 | public int getHLineSpacing() {
86 | return mHLineSpacing;
87 | }
88 |
89 | /**
90 | * 设置水平线间距
91 | *
92 | * @param dpValueHLineSpacing
93 | * @return
94 | */
95 | public XStaggeredGridBuilder setHLineSpacing(float dpValueHLineSpacing) {
96 | this.mHLineSpacing = (int) DividerHelper.applyDimension(dpValueHLineSpacing, TypedValue.COMPLEX_UNIT_DIP);
97 | return this;
98 |
99 | }
100 |
101 | public XStaggeredGridBuilder setHLineSpacing(@DimenRes int dimenResId) {
102 | this.mHLineSpacing = Resources.getSystem().getDimensionPixelSize(dimenResId);
103 | return this;
104 | }
105 |
106 | public boolean isIncludeEdge() {
107 | return mIsIncludeEdge;
108 | }
109 |
110 | /**
111 | * 设置是否包含边界
112 | *
113 | * @param includeEdge
114 | * @return
115 | */
116 | public XStaggeredGridBuilder setIncludeEdge(boolean includeEdge) {
117 | mIsIncludeEdge = includeEdge;
118 | return this;
119 | }
120 |
121 | public boolean isIgnoreFullSpan() {
122 | return mIsIgnoreFullSpan;
123 | }
124 |
125 | /**
126 | * 设置是否忽略fullSpan的情况
127 | *
128 | * @param ignoreFullSpan
129 | * @return
130 | */
131 | public XStaggeredGridBuilder setIgnoreFullSpan(boolean ignoreFullSpan) {
132 | mIsIgnoreFullSpan = ignoreFullSpan;
133 | return this;
134 | }
135 |
136 | }
137 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/littlejerk/rvdivider/decoration/ILDecoration.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.rvdivider.decoration;
2 |
3 | import android.graphics.drawable.Drawable;
4 |
5 | import androidx.annotation.ColorInt;
6 | import androidx.annotation.ColorRes;
7 | import androidx.annotation.DimenRes;
8 | import androidx.annotation.DrawableRes;
9 |
10 | /**
11 | * @Author : HHotHeart
12 | * @Time : 2021/5/31 16:07
13 | * @Description : 接口类
14 | */
15 | public interface ILDecoration {
16 |
17 | ILDecoration setPadding(float dpValuePadding);
18 |
19 | ILDecoration setPadding(@DimenRes int dimenResId);
20 |
21 | ILDecoration setLeftPadding(float dpValuePadding);
22 |
23 | ILDecoration setRightPadding(float dpValuePadding);
24 |
25 | ILDecoration setLeftPadding(@DimenRes int dimenResId);
26 |
27 | ILDecoration setRightPadding(@DimenRes int dimenResId);
28 |
29 | ILDecoration setTopPadding(float dpValuePadding);
30 |
31 | ILDecoration setBottomPadding(float dpValuePadding);
32 |
33 | ILDecoration setTopPadding(@DimenRes int dimenResId);
34 |
35 | ILDecoration setBottomPadding(@DimenRes int dimenResId);
36 |
37 | ILDecoration setColorRes(@ColorRes int colorResId);
38 |
39 | ILDecoration setColor(@ColorInt int color);
40 |
41 | ILDecoration setDrawableRes(@DrawableRes int drawableResId);
42 |
43 | ILDecoration setDrawable(Drawable drawable);
44 |
45 | // int getDividerSpace();
46 |
47 | int getLeftPadding();
48 |
49 | int getRightPadding();
50 |
51 | int getTopPadding();
52 |
53 | int getBottomPadding();
54 |
55 | Drawable getDividerDrawable();
56 |
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/baselib/src/main/java/com/littlejerk/rvdivider/decoration/LDecoration.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.rvdivider.decoration;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.graphics.drawable.ColorDrawable;
6 | import android.graphics.drawable.Drawable;
7 | import android.util.TypedValue;
8 |
9 | import com.littlejerk.rvdivider.DividerHelper;
10 |
11 | import androidx.core.content.ContextCompat;
12 |
13 | /**
14 | * @Author : HHotHeart
15 | * @Time : 2021/5/31 16:07
16 | * @Description : 线性item分割线修饰类
17 | */
18 | public class LDecoration implements ILDecoration {
19 | private Context mContext;
20 | /**
21 | * 分割线左右内边距(垂直)
22 | */
23 | private int mLeftPadding = 0;
24 | private int mRightPadding = 0;
25 | /**
26 | * 分割线上下内边距(水平)
27 | */
28 | private int mTopPadding = 0;
29 | private int mBottomPadding = 0;
30 | /**
31 | * 分割线颜色或背景
32 | */
33 | private int mColor;
34 | private Drawable mDividerDrawable;
35 |
36 | /**
37 | * 默认对边界不处理
38 | */
39 | private Boolean isDrawLeft = null;
40 | private Boolean isDrawTop = null;
41 | private Boolean isDrawRight = null;
42 | private Boolean isDrawBottom = null;
43 |
44 | public LDecoration(Context context) {
45 | mContext = context;
46 | }
47 |
48 | /**
49 | * 设置绘制item左上右下属性
50 | *
51 | * @param isDrawLeft
52 | * @param isDrawTop
53 | * @param isDrawRight
54 | * @param isDrawBottom
55 | * @return
56 | */
57 | public LDecoration setAroundEdge(Boolean isDrawLeft, Boolean isDrawTop, Boolean isDrawRight, Boolean isDrawBottom) {
58 | this.isDrawLeft = isDrawLeft;
59 | this.isDrawTop = isDrawTop;
60 | this.isDrawRight = isDrawRight;
61 | this.isDrawBottom = isDrawBottom;
62 | return this;
63 | }
64 |
65 | public Boolean[] getAroundEdge() {
66 | return new Boolean[]{isDrawLeft, isDrawTop, isDrawRight, isDrawBottom};
67 | }
68 |
69 | @Override
70 | public LDecoration setPadding(float dpValuePadding) {
71 | setLeftPadding(dpValuePadding);
72 | setRightPadding(dpValuePadding);
73 | setTopPadding(dpValuePadding);
74 | setBottomPadding(dpValuePadding);
75 | return this;
76 | }
77 |
78 | @Override
79 | public LDecoration setPadding(int dimenResId) {
80 | setLeftPadding(dimenResId);
81 | setRightPadding(dimenResId);
82 | setTopPadding(dimenResId);
83 | setBottomPadding(dimenResId);
84 | return this;
85 | }
86 |
87 | @Override
88 | public LDecoration setLeftPadding(float dpValuePadding) {
89 | mLeftPadding = (int) DividerHelper.applyDimension(dpValuePadding, TypedValue.COMPLEX_UNIT_DIP);
90 | return this;
91 | }
92 |
93 | @Override
94 | public LDecoration setRightPadding(float dpValuePadding) {
95 | mRightPadding = (int) DividerHelper.applyDimension(dpValuePadding, TypedValue.COMPLEX_UNIT_DIP);
96 | return this;
97 | }
98 |
99 | @Override
100 | public LDecoration setLeftPadding(int dimenResId) {
101 | mLeftPadding = Resources.getSystem().getDimensionPixelSize(dimenResId);
102 | return this;
103 | }
104 |
105 | @Override
106 | public LDecoration setRightPadding(int dimenResId) {
107 | mRightPadding = Resources.getSystem().getDimensionPixelSize(dimenResId);
108 | return this;
109 | }
110 |
111 | @Override
112 | public LDecoration setTopPadding(float dpValuePadding) {
113 | mTopPadding = (int) DividerHelper.applyDimension(dpValuePadding, TypedValue.COMPLEX_UNIT_DIP);
114 | return this;
115 | }
116 |
117 | @Override
118 | public LDecoration setBottomPadding(float dpValuePadding) {
119 | mBottomPadding = (int) DividerHelper.applyDimension(dpValuePadding, TypedValue.COMPLEX_UNIT_DIP);
120 | return this;
121 | }
122 |
123 | @Override
124 | public LDecoration setTopPadding(int dimenResId) {
125 | mTopPadding = Resources.getSystem().getDimensionPixelSize(dimenResId);
126 | return this;
127 | }
128 |
129 | @Override
130 | public LDecoration setBottomPadding(int dimenResId) {
131 | mBottomPadding = Resources.getSystem().getDimensionPixelSize(dimenResId);
132 | return this;
133 | }
134 |
135 | @Override
136 | public LDecoration setColorRes(int colorResId) {
137 | setColor(ContextCompat.getColor(mContext, colorResId));
138 | return this;
139 | }
140 |
141 | @Override
142 | public LDecoration setColor(int color) {
143 | mColor = color;
144 | return this;
145 | }
146 |
147 | @Override
148 | public LDecoration setDrawableRes(int drawableResId) {
149 | setDrawable(ContextCompat.getDrawable(mContext, drawableResId));
150 | return this;
151 | }
152 |
153 | @Override
154 | public LDecoration setDrawable(Drawable drawable) {
155 | mDividerDrawable = drawable;
156 | return this;
157 | }
158 |
159 | @Override
160 | public int getLeftPadding() {
161 | return mLeftPadding;
162 | }
163 |
164 | @Override
165 | public int getRightPadding() {
166 | return mRightPadding;
167 | }
168 |
169 | @Override
170 | public int getTopPadding() {
171 | return mTopPadding;
172 | }
173 |
174 | @Override
175 | public int getBottomPadding() {
176 | return mBottomPadding;
177 | }
178 |
179 | @Override
180 | public Drawable getDividerDrawable() {
181 | //创建Drawable
182 | if (mDividerDrawable == null) {
183 | mDividerDrawable = new ColorDrawable(mColor);
184 | }
185 | return mDividerDrawable;
186 | }
187 |
188 | }
189 |
--------------------------------------------------------------------------------
/baselib/src/test/java/com/littlejerk/rvdivider/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.littlejerk.rvdivider;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 | dependencies {
8 | classpath "com.android.tools.build:gradle:4.2.1"
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | google()
18 | mavenCentral()
19 | jcenter() // Warning: this repository is going to shut down soon
20 | }
21 | }
22 |
23 | task clean(type: Delete) {
24 | delete rootProject.buildDir
25 | }
--------------------------------------------------------------------------------
/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=-Xmx2048m -Dfile.encoding=UTF-8
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 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/huangxiaolianghh/XRecyclerViewDivider/06034c59b03ee8dcda476c8580f2d1d5228a22df/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun May 30 16:55:39 CST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
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 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = "XRecyclerViewDivider"
2 | include ':app'
3 | include ':baselib'
4 |
--------------------------------------------------------------------------------