Skip to content

Commit 004e7ed

Browse files
committed
fix
1 parent b8f0eca commit 004e7ed

File tree

10 files changed

+185
-57
lines changed

10 files changed

+185
-57
lines changed

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ dependencies {
3030
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
3131
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta04'
3232
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta04'
33+
implementation "org.jetbrains.anko:anko:0.10.8"
3334

3435
testImplementation 'junit:junit:4.12'
3536
androidTestImplementation 'androidx.test:runner:1.2.0'

app/src/main/java/xyz/sangcomz/indicatordecoratorsample/MainActivity.kt

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ package xyz.sangcomz.indicatordecoratorsample
22

33
import android.os.Bundle
44
import androidx.appcompat.app.AppCompatActivity
5+
import androidx.core.content.ContextCompat
56
import androidx.recyclerview.widget.PagerSnapHelper
67
import kotlinx.android.synthetic.main.activity_main.*
78
import xyz.sangcomz.indicatordecorator.IndicatorItemDecoration
8-
import xyz.sangcomz.indicatordecorator.LinePagerIndicatorDecoration
9+
import xyz.sangcomz.indicatordecorator.shape.DrawableIndicator
910

1011
class MainActivity : AppCompatActivity() {
1112

@@ -27,12 +28,22 @@ class MainActivity : AppCompatActivity() {
2728
setContentView(R.layout.activity_main)
2829

2930
viewPager.adapter = adapter
30-
viewPager.addItemDecoration(IndicatorItemDecoration())
31+
viewPager.addItemDecoration(IndicatorItemDecoration().apply {
32+
})
3133
// viewPager.addItemDecoration(LinePagerIndicatorDecoration())
3234

3335
recyclerView.adapter = adapter
3436
PagerSnapHelper().attachToRecyclerView(recyclerView)
35-
// recyclerView.addItemDecoration(IndicatorItemDecoration())
36-
recyclerView.addItemDecoration(LinePagerIndicatorDecoration())
37+
recyclerView.addItemDecoration(IndicatorItemDecoration().apply {
38+
indicatorShape = DrawableIndicator(
39+
ContextCompat.getDrawable(
40+
this@MainActivity,
41+
R.drawable.ic_grade_red_24dp
42+
)!!,
43+
ContextCompat.getDrawable(this@MainActivity, R.drawable.ic_grade_black_24dp)!!
44+
)
45+
})
46+
47+
3748
}
3849
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24.0"
5+
android:viewportHeight="24.0">
6+
<path
7+
android:fillColor="#FF000000"
8+
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
9+
</vector>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24.0"
5+
android:viewportHeight="24.0">
6+
<path
7+
android:fillColor="#EB3351"
8+
android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z" />
9+
</vector>

indicatordecorator/src/main/java/xyz/sangcomz/indicatordecorator/IndicatorItemDecoration.kt

Lines changed: 42 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,58 @@ package xyz.sangcomz.indicatordecorator
22

33
import android.content.res.Resources
44
import android.graphics.Canvas
5-
import android.graphics.Color
6-
import android.graphics.Paint
75
import android.graphics.Rect
86
import android.view.View
9-
107
import androidx.recyclerview.widget.LinearLayoutManager
118
import androidx.recyclerview.widget.RecyclerView
9+
import xyz.sangcomz.indicatordecorator.shape.CircleIndicator
10+
import xyz.sangcomz.indicatordecorator.shape.IndicatorShape
11+
import kotlin.math.max
1212

1313
class IndicatorItemDecoration : RecyclerView.ItemDecoration() {
1414

15-
private val colorActive = Color.BLACK
16-
private val colorInactive = Color.GRAY
17-
private val radius = (DP * 3.5).toFloat()
18-
private val offset = (DP * 8).toInt()
19-
20-
private var selectedPage = 0
21-
22-
/**
23-
* Indicator width.
24-
*/
25-
private val mIndicatorItemLength = radius * 2
15+
var topOffset = (DP * 4).toInt()
16+
var bottomOffset = (DP * 4).toInt()
2617
/**
2718
* Padding between indicators.
2819
*/
29-
private val mIndicatorItemPadding = DP * 4
20+
var indicatorItemPadding = DP * 8
3021

31-
private val mPaint = Paint()
32-
33-
init {
34-
mPaint.strokeCap = Paint.Cap.ROUND
35-
mPaint.isAntiAlias = true
36-
}
22+
var indicatorShape: IndicatorShape = CircleIndicator().apply { radius = DP * 4 }
3723

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

4127
val adapter = parent.adapter ?: return
28+
val layoutManager: LinearLayoutManager =
29+
parent.layoutManager as? LinearLayoutManager ?: return
4230

4331
val itemCount = adapter.itemCount
4432

45-
val totalLength = mIndicatorItemLength * itemCount
46-
val paddingBetweenItems = Math.max(0, itemCount - 1) * mIndicatorItemPadding
33+
val totalLength = indicatorShape.getIndicatorWidth() * itemCount
34+
35+
val paddingBetweenItems = max(0, itemCount - 1) * indicatorItemPadding
4736
val indicatorTotalWidth = totalLength + paddingBetweenItems
4837
val indicatorStartX = (parent.width - indicatorTotalWidth) / 2f
4938

50-
val indicatorPosY = parent.height - radius
39+
val indicatorPosY = parent.height - (indicatorShape.getIndicatorWidth() / 2) - bottomOffset
5140

5241
drawInactiveIndicators(c, indicatorStartX, indicatorPosY, itemCount)
5342

54-
val layoutManager = parent.layoutManager as? LinearLayoutManager
55-
val activePosition = layoutManager?.findFirstVisibleItemPosition()
43+
44+
val activePosition = layoutManager.findFirstVisibleItemPosition()
5645
if (activePosition == RecyclerView.NO_POSITION) {
5746
return
5847
}
5948

60-
val view = layoutManager?.findViewByPosition(activePosition!!)!!
61-
println("activeView width, left:::: ${view.width}, ${view.left}")
62-
println("activeView width + left:::: ${view.width + view.left}")
49+
val view = layoutManager.findViewByPosition(activePosition)!!
6350

64-
selectedPage = activePosition ?: 0 + if (view.width / 2 > view.width + view.left) 1 else 0
65-
66-
println("selectedPage :::: $selectedPage")
67-
68-
// if (layoutManager?.findLastVisibleItemPosition() != RecyclerView.NO_POSITION) {
69-
// selectedPage = layoutManager?.findLastVisibleItemPosition() ?: 0
70-
// }
71-
72-
drawSelectedIndicators(c, indicatorStartX, indicatorPosY)
51+
drawSelectedIndicators(
52+
c,
53+
activePosition + if (view.width / 2f > view.width + view.left) 1 else 0,
54+
indicatorStartX,
55+
indicatorPosY
56+
)
7357
}
7458

7559
private fun drawInactiveIndicators(
@@ -78,22 +62,32 @@ class IndicatorItemDecoration : RecyclerView.ItemDecoration() {
7862
indicatorPosY: Float,
7963
itemCount: Int
8064
) {
81-
mPaint.color = colorInactive
82-
83-
val itemWidth = mIndicatorItemLength + mIndicatorItemPadding
65+
val itemWidth = indicatorShape.getIndicatorWidth() + indicatorItemPadding
8466

8567
var start = indicatorStartX
8668
for (i in 0 until itemCount) {
87-
c.drawCircle(start + radius, indicatorPosY, radius, mPaint)
69+
indicatorShape.inactiveIndicatorDraw(
70+
c, start + indicatorShape.getIndicatorWidth() / 2,
71+
indicatorPosY
72+
)
8873
start += itemWidth
8974
}
9075
}
9176

92-
private fun drawSelectedIndicators(c: Canvas, indicatorStartX: Float, indicatorPosY: Float) {
93-
mPaint.color = colorActive
94-
val itemWidth = mIndicatorItemLength + mIndicatorItemPadding
95-
val start = indicatorStartX + itemWidth * selectedPage
96-
c.drawCircle(start + radius, indicatorPosY, radius, mPaint)
77+
private fun drawSelectedIndicators(
78+
c: Canvas,
79+
selectedPosition: Int,
80+
indicatorStartX: Float,
81+
indicatorPosY: Float
82+
) {
83+
val itemWidth = indicatorShape.getIndicatorWidth() + indicatorItemPadding
84+
val start = indicatorStartX + itemWidth * selectedPosition
85+
86+
indicatorShape.activeIndicatorDraw(
87+
c,
88+
start + indicatorShape.getIndicatorWidth() / 2,
89+
indicatorPosY
90+
)
9791
}
9892

9993
override fun getItemOffsets(
@@ -103,11 +97,10 @@ class IndicatorItemDecoration : RecyclerView.ItemDecoration() {
10397
state: RecyclerView.State
10498
) {
10599
super.getItemOffsets(outRect, view, parent, state)
106-
outRect.bottom = (offset + radius).toInt()
100+
outRect.bottom = (topOffset + bottomOffset + indicatorShape.getIndicatorWidth()).toInt()
107101
}
108102

109103
companion object {
110-
111104
private val DP = Resources.getSystem().displayMetrics.density
112105
}
113106
}

indicatordecorator/src/main/java/xyz/sangcomz/indicatordecorator/LinePagerIndicatorDecoration.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class LinePagerIndicatorDecoration : RecyclerView.ItemDecoration() {
9898

9999
var start = indicatorStartX
100100
for (i in 0 until itemCount) {
101-
// draw the line for every item
101+
// inactiveIndicatorDraw the line for every item
102102
c.drawLine(start, indicatorPosY, start + mIndicatorItemLength, indicatorPosY, mPaint)
103103
start += itemWidth
104104
}
@@ -114,7 +114,7 @@ class LinePagerIndicatorDecoration : RecyclerView.ItemDecoration() {
114114
val itemWidth = mIndicatorItemLength + mIndicatorItemPadding
115115

116116
if (progress == 0f) {
117-
// no swipe, draw a normal indicator
117+
// no swipe, inactiveIndicatorDraw a normal indicator
118118
val highlightStart = indicatorStartX + itemWidth * highlightPosition
119119
c.drawLine(
120120
highlightStart, indicatorPosY,
@@ -125,13 +125,13 @@ class LinePagerIndicatorDecoration : RecyclerView.ItemDecoration() {
125125
// calculate partial highlight
126126
val partialLength = mIndicatorItemLength * progress
127127

128-
// draw the cut off highlight
128+
// inactiveIndicatorDraw the cut off highlight
129129
c.drawLine(
130130
highlightStart + partialLength, indicatorPosY,
131131
highlightStart + mIndicatorItemLength, indicatorPosY, mPaint
132132
)
133133

134-
// draw the highlight overlapping to the next item as well
134+
// inactiveIndicatorDraw the highlight overlapping to the next item as well
135135
if (highlightPosition < itemCount - 1) {
136136
highlightStart += itemWidth
137137
c.drawLine(
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package xyz.sangcomz.indicatordecorator.shape
2+
3+
import android.graphics.Canvas
4+
import android.graphics.Color
5+
import android.graphics.Paint
6+
7+
class CircleIndicator : IndicatorShape {
8+
private val paint = Paint().apply { isAntiAlias = true }
9+
var colorActive: Int = Color.YELLOW
10+
var colorInactive: Int = Color.GRAY
11+
var radius: Float = 1f
12+
13+
override var scaleFactor: Float = 1.2f
14+
15+
override fun getIndicatorWidth() = radius * 2
16+
17+
override fun inactiveIndicatorDraw(c: Canvas, x: Float, y: Float) {
18+
paint.color = colorInactive
19+
c.drawCircle(x, y, radius, paint)
20+
}
21+
22+
override fun activeIndicatorDraw(c: Canvas, x: Float, y: Float) {
23+
paint.color = colorActive
24+
c.drawCircle(x, y, radius * scaleFactor, paint)
25+
}
26+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package xyz.sangcomz.indicatordecorator.shape
2+
3+
import android.graphics.Canvas
4+
import android.graphics.drawable.Drawable
5+
6+
7+
class DrawableIndicator(
8+
drawableActive: Drawable,
9+
drawableInActive: Drawable
10+
) : IndicatorShape {
11+
override var scaleFactor: Float = 1f
12+
var width: Float = drawableActive.intrinsicWidth.toFloat()
13+
var drawableActive = drawableActive
14+
var drawableInActive = drawableInActive
15+
16+
override fun inactiveIndicatorDraw(c: Canvas, x: Float, y: Float) {
17+
drawableInActive.setBounds(
18+
x.toInt(),
19+
(y - width / 2).toInt(),
20+
(x + width).toInt(),
21+
(y + width / 2).toInt()
22+
)
23+
drawableInActive.draw(c)
24+
}
25+
26+
override fun activeIndicatorDraw(c: Canvas, x: Float, y: Float) {
27+
val scale = ((width * scaleFactor) - width) / 2
28+
drawableActive.setBounds(
29+
(x - scale).toInt(),
30+
(y - width / 2).toInt(),
31+
(x + width + scale).toInt(),
32+
(y + width / 2).toInt()
33+
)
34+
drawableActive.draw(c)
35+
}
36+
37+
override fun getIndicatorWidth() = width
38+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package xyz.sangcomz.indicatordecorator.shape
2+
3+
import android.graphics.Canvas
4+
5+
interface IndicatorShape {
6+
var scaleFactor: Float
7+
fun inactiveIndicatorDraw(c: Canvas, x: Float, y: Float)
8+
fun activeIndicatorDraw(c: Canvas, x: Float, y: Float)
9+
fun getIndicatorWidth(): Float
10+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package xyz.sangcomz.indicatordecorator.shape
2+
3+
import android.graphics.Canvas
4+
import android.graphics.Color
5+
import android.graphics.Paint
6+
7+
class SquareIndicator : IndicatorShape {
8+
private val paint = Paint().apply { isAntiAlias = true }
9+
var colorActive: Int = Color.RED
10+
var colorInactive: Int = Color.GRAY
11+
var width = 20f
12+
override var scaleFactor = 1.5f
13+
override fun inactiveIndicatorDraw(c: Canvas, x: Float, y: Float) {
14+
paint.color = colorInactive
15+
c.drawRect(x, y - width / 2, x + width, y + width / 2, paint)
16+
}
17+
18+
override fun activeIndicatorDraw(c: Canvas, x: Float, y: Float) {
19+
paint.color = colorActive
20+
val scale = ((width * scaleFactor) - width) / 2
21+
c.drawRect(
22+
x - scale,
23+
y - (width * scaleFactor) / 2,
24+
x + width + scale,
25+
y + (width * scaleFactor) / 2,
26+
paint
27+
)
28+
}
29+
30+
override fun getIndicatorWidth() = width
31+
}

0 commit comments

Comments
 (0)