Skip to content

Commit ee5149e

Browse files
authored
Merge pull request #6 from lriccardo/dev
Release 1.0.5
2 parents 41073df + 2adaa95 commit ee5149e

File tree

11 files changed

+165
-30
lines changed

11 files changed

+165
-30
lines changed

README.md

+33-7
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,16 @@ dependencies {
8787
<td>12dp</td>
8888
</tr>
8989
</tr>
90-
<tr>
90+
<tr>
9191
<td>app:indicator_color</td>
9292
<td>Color</td>
9393
<td>Color.RED</td>
9494
</tr>
95+
<tr>
96+
<td>app:indicator_y_position</td>
97+
<td>Percentage (0.0 - 1.0)</td>
98+
<td>0.5f</td>
99+
</tr>
95100
<tr>
96101
<td>app:checked_indicator_size</td>
97102
<td>Dimension</td>
@@ -160,6 +165,11 @@ recyclerView.addItemDecoration(
160165
<td>Float</td>
161166
<td>24f</td>
162167
</tr>
168+
<tr>
169+
<td>indicatorYPosition</td>
170+
<td>Percentage (0.0f - 1.0f)</td>
171+
<td>0.5f</td>
172+
</tr>
163173
<tr>
164174
<td>checkedIndicatorSize</td>
165175
<td>Float</td>
@@ -175,11 +185,26 @@ recyclerView.addItemDecoration(
175185
<td>Normal (Normal | Dashed)</td>
176186
<td>TimelineView default value</td>
177187
</tr>
188+
<tr>
189+
<td>linePadding</td>
190+
<td>Float</td>
191+
<td>TimelineView default value</td>
192+
</tr>
193+
<tr>
194+
<td>lineDashLength</td>
195+
<td>Float</td>
196+
<td>TimelineView default value</td>
197+
</tr>
198+
<tr>
199+
<td>lineDashGap</td>
200+
<td>Float</td>
201+
<td>TimelineView default value</td>
202+
</tr>
178203
<tr>
179204
<td>lineWidth</td>
180205
<td>Float</td>
181206
<td>TimelineView default value</td>
182-
</tr>
207+
</tr>
183208
<tr>
184209
<td>padding</td>
185210
<td>Float</td>
@@ -209,10 +234,11 @@ recyclerView.addItemDecoration(
209234
Implementing one or all of these methods, allows you to use the `position` argument to return a different customization for some of your items.
210235
```kotlin
211236
interface TimelineAdapter {
212-
fun getTimelineViewType(position: Int): TimelineView.ViewType
213-
fun getIndicatorStyle(position: Int): TimelineView.IndicatorStyle
214-
fun getIndicatorColor(position: Int): Int
215-
fun getLineColor(position: Int): Int
216-
fun getLineStyle(position: Int): TimelineView.LineStyle
237+
fun getTimelineViewType(position: Int): TimelineView.ViewType?
238+
fun getIndicatorStyle(position: Int): TimelineView.IndicatorStyle?
239+
fun getIndicatorColor(position: Int): Int?
240+
fun getLineColor(position: Int): Int?
241+
fun getLineStyle(position: Int): TimelineView.LineStyle?
242+
fun getLinePadding(position: Int): Float?
217243
}
218244
```

TimelineView/src/main/java/com/lriccardo/timelineview/TimelineAdapter.kt

+1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ interface TimelineAdapter {
66
fun getIndicatorColor(position: Int): Int? = null
77
fun getLineColor(position: Int): Int? = null
88
fun getLineStyle(position: Int): TimelineView.LineStyle? = null
9+
fun getLinePadding(position: Int): Float? = null
910
}

TimelineView/src/main/java/com/lriccardo/timelineview/TimelineDecorator.kt

+19-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ import androidx.recyclerview.widget.RecyclerView
1010
class TimelineDecorator(
1111
val indicatorStyle: TimelineView.IndicatorStyle = TimelineView.IndicatorStyle.Filled,
1212
val indicatorSize: Float = 12.toPx().toFloat(),
13+
val indicatorYPosition: Float = 0.5f,
1314
val checkedIndicatorSize: Float? = null,
1415
val checkedIndicatorStrokeWidth: Float = 4.toPx().toFloat(),
1516
val lineStyle: TimelineView.LineStyle? = null,
17+
val linePadding: Float? = null,
18+
val lineDashLength: Float? = null,
19+
val lineDashGap: Float? = null,
1620
val lineWidth: Float? = null,
1721
val padding: Float = 16.toPx().toFloat(),
1822
val position: Position = Position.Left,
@@ -75,17 +79,31 @@ class TimelineDecorator(
7579
(getLineStyle(itemPosition) ?: lineStyle)?.let {
7680
timelineView.lineStyle = it
7781
}
82+
83+
(getLinePadding(itemPosition) ?: linePadding)?.let {
84+
timelineView.linePadding = it
85+
}
7886
}
7987
timelineView.indicatorSize = indicatorSize
8088

89+
timelineView.indicatorYPosition = indicatorYPosition
90+
8191
checkedIndicatorSize?.let {
8292
timelineView.checkedIndicatorSize = it
8393
}
8494

85-
checkedIndicatorStrokeWidth?.let {
95+
checkedIndicatorStrokeWidth.let {
8696
timelineView.checkedIndicatorStrokeWidth = it
8797
}
8898

99+
lineDashLength?.let {
100+
timelineView.lineDashLength = it
101+
}
102+
103+
lineDashGap?.let {
104+
timelineView.lineDashGap = it
105+
}
106+
89107
lineWidth?.let {
90108
timelineView.lineWidth = it
91109
}

TimelineView/src/main/java/com/lriccardo/timelineview/TimelineView.kt

+33-9
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ class TimelineView @JvmOverloads constructor(
5555
initIndicatorPaint()
5656
}
5757

58+
var indicatorYPosition: Float = 0.5f
59+
set(value) {
60+
field = value.coerceIn(0f, 1f)
61+
}
62+
5863
var lineStyle = LineStyle.Normal
5964
set(value) {
6065
field = value
@@ -65,6 +70,12 @@ class TimelineView @JvmOverloads constructor(
6570
field = value
6671
initLinePaint()
6772
}
73+
var linePadding: Float = 0.toPx().toFloat()
74+
set(value) {
75+
field = value
76+
initLinePaint()
77+
}
78+
6879
var lineDashLength: Float = 18.toPx().toFloat()
6980
set(value) {
7081
field = value
@@ -112,11 +123,26 @@ class TimelineView @JvmOverloads constructor(
112123
checkedIndicatorSize.toInt()
113124
).toFloat()
114125

126+
checkedIndicatorStrokeWidth = getDimensionPixelSize(
127+
R.styleable.TimelineView_checked_indicator_stroke_width,
128+
checkedIndicatorStrokeWidth.toInt()
129+
).toFloat()
130+
131+
indicatorYPosition = getFloat(
132+
R.styleable.TimelineView_indicator_y_position,
133+
indicatorYPosition
134+
).coerceIn(0f, 1f)
135+
115136
lineWidth = getDimensionPixelSize(
116137
R.styleable.TimelineView_line_width,
117138
lineWidth.toInt()
118139
).toFloat()
119140

141+
linePadding = getDimensionPixelSize(
142+
R.styleable.TimelineView_line_padding,
143+
linePadding.toInt()
144+
).toFloat()
145+
120146
lineDashLength = getDimensionPixelSize(
121147
R.styleable.TimelineView_line_dash_length,
122148
lineDashLength.toInt()
@@ -132,11 +158,6 @@ class TimelineView @JvmOverloads constructor(
132158

133159
lineColor = getColor(R.styleable.TimelineView_line_color, lineColor)
134160

135-
checkedIndicatorStrokeWidth = getDimensionPixelSize(
136-
R.styleable.TimelineView_checked_indicator_stroke_width,
137-
checkedIndicatorStrokeWidth.toInt()
138-
).toFloat()
139-
140161
indicatorColor = getColor(R.styleable.TimelineView_indicator_color, indicatorColor)
141162
indicatorStyle =
142163
IndicatorStyle.values()[getInteger(R.styleable.TimelineView_indicator_style, indicatorStyle.ordinal)]
@@ -213,7 +234,8 @@ class TimelineView @JvmOverloads constructor(
213234
var bottomLineYEnd: Float
214235

215236
val indicatorCenterX = (width / 2).toFloat()
216-
val indicatorCenterY = (height / 2).toFloat()
237+
val indicatorCenterY =
238+
(height * indicatorYPosition).coerceIn(indicatorSize, height - indicatorSize)
217239

218240
var drawIndicator = true
219241
var drawTopLine = false
@@ -243,14 +265,16 @@ class TimelineView @JvmOverloads constructor(
243265
}
244266

245267
topLineYStart = 0f
246-
if(lineStyle == LineStyle.Dashed)
268+
if (lineStyle == LineStyle.Dashed && (indicatorCenterY - indicatorSize) > lineDashGap)
247269
topLineYStart += lineDashGap
248270

249271

250272
bottomLineYStart = height.toFloat()
251273
if(drawIndicator) {
252-
topLineYEnd = (indicatorCenterY - indicatorSize) + 1f
253-
bottomLineYEnd = (indicatorCenterY + indicatorSize) - 1f
274+
topLineYEnd =
275+
(indicatorCenterY - indicatorSize - linePadding).coerceAtLeast(topLineYStart)
276+
bottomLineYEnd =
277+
(indicatorCenterY + indicatorSize + linePadding).coerceAtMost(bottomLineYStart)
254278
} else {
255279
topLineYEnd = indicatorCenterY
256280
bottomLineYEnd = indicatorCenterY

TimelineView/src/main/res/values/attrs.xml

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
</attr>
1616
<attr name="indicator_size" format="dimension"/>
1717
<attr name="indicator_color" format="color"/>
18+
<attr name="indicator_y_position" format="float"/>
1819

1920
<attr name="checked_indicator_size" format="dimension"/>
2021
<attr name="checked_indicator_stroke_width" format="dimension"/>
@@ -28,5 +29,6 @@
2829

2930
<attr name="line_dash_length" format="dimension"/>
3031
<attr name="line_dash_gap" format="dimension"/>
32+
<attr name="line_padding" format="dimension"/>
3133
</declare-styleable>
3234
</resources>

screens/expand.gif

5.43 MB
Loading

timelineview_example/src/main/java/com/lriccardo/timelineview_example/activities/RecyclerViewDecoratorActivity.kt

+29-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package com.lriccardo.timelineview_example.activities
22

3-
import androidx.appcompat.app.AppCompatActivity
3+
import android.content.res.Resources.Theme
44
import android.os.Bundle
5+
import android.util.TypedValue
6+
import androidx.appcompat.app.AppCompatActivity
57
import androidx.recyclerview.widget.LinearLayoutManager
8+
import androidx.recyclerview.widget.RecyclerView
69
import com.lriccardo.timelineview.TimelineDecorator
10+
import com.lriccardo.timelineview_example.R
711
import com.lriccardo.timelineview_example.adapters.BaseAdapter
812
import com.lriccardo.timelineview_example.databinding.ActivityRecyclerViewDecoratorBinding
913

@@ -18,7 +22,30 @@ class RecyclerViewDecoratorActivity : AppCompatActivity() {
1822
binding.timelineRv.let {
1923
it.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
2024
it.adapter = BaseAdapter((0..10).toList())
21-
it.addItemDecoration(TimelineDecorator())
25+
26+
val colorPrimary = TypedValue()
27+
val theme: Theme = getTheme()
28+
theme.resolveAttribute(R.attr.colorPrimary, colorPrimary, true)
29+
30+
it.addItemDecoration(
31+
TimelineDecorator(
32+
position = TimelineDecorator.Position.Left,
33+
indicatorColor = colorPrimary.data,
34+
lineColor = colorPrimary.data
35+
)
36+
)
37+
38+
it.addOnScrollListener(object : RecyclerView.OnScrollListener() {
39+
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
40+
super.onScrolled(recyclerView, dx, dy)
41+
(it.layoutManager as? LinearLayoutManager)?.let {
42+
if (it.findFirstCompletelyVisibleItemPosition() == 0)
43+
binding.fab.extend()
44+
else
45+
binding.fab.shrink()
46+
}
47+
}
48+
})
2249
}
2350
}
2451
}

timelineview_example/src/main/java/com/lriccardo/timelineview_example/adapters/BaseAdapter.kt

+28-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
package com.lriccardo.timelineview_example.adapters
22

3+
import android.content.res.Resources
4+
import android.util.TypedValue
35
import android.view.LayoutInflater
46
import android.view.ViewGroup
57
import androidx.recyclerview.widget.RecyclerView
8+
import com.lriccardo.timelineview.TimelineAdapter
9+
import com.lriccardo.timelineview.TimelineView
610
import com.lriccardo.timelineview_example.R
711
import com.lriccardo.timelineview_example.viewholders.BaseViewHolder
812

9-
class BaseAdapter(val items: List<Int>): RecyclerView.Adapter<BaseViewHolder>() {
13+
class BaseAdapter(val items: List<Int>) : RecyclerView.Adapter<BaseViewHolder>(), TimelineAdapter {
14+
1015
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
1116
val view = LayoutInflater.from(parent.context)
1217
.inflate(R.layout.base_list_item, parent, false)
@@ -22,4 +27,26 @@ class BaseAdapter(val items: List<Int>): RecyclerView.Adapter<BaseViewHolder>()
2227
}
2328

2429
override fun getItemCount(): Int = items.size
30+
31+
override fun getIndicatorStyle(position: Int): TimelineView.IndicatorStyle? {
32+
if (position <= 1)
33+
return TimelineView.IndicatorStyle.Checked
34+
else return TimelineView.IndicatorStyle.Empty
35+
}
36+
37+
override fun getLineStyle(position: Int): TimelineView.LineStyle? {
38+
if (position > 1)
39+
return TimelineView.LineStyle.Dashed
40+
return super.getLineStyle(position)
41+
}
42+
43+
override fun getLinePadding(position: Int): Float? {
44+
if (position > 1)
45+
return TypedValue.applyDimension(
46+
TypedValue.COMPLEX_UNIT_DIP,
47+
16f,
48+
Resources.getSystem().displayMetrics
49+
)
50+
return super.getLinePadding(position)
51+
}
2552
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<vector android:height="24dp" android:tint="#FFFFFF"
2+
android:viewportHeight="24" android:viewportWidth="24"
3+
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
4+
<path android:fillColor="@android:color/white" android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z"/>
5+
</vector>
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:app="http://schemas.android.com/apk/res-auto"
44
xmlns:tools="http://schemas.android.com/tools"
55
android:layout_width="match_parent"
66
android:layout_height="match_parent"
77
tools:context=".MainActivity">
88

9-
<androidx.recyclerview.widget.RecyclerView
10-
android:id="@+id/timeline_rv"
11-
android:layout_width="0dp"
12-
android:layout_height="0dp"
13-
app:layout_constraintStart_toStartOf="parent"
14-
app:layout_constraintEnd_toEndOf="parent"
15-
app:layout_constraintTop_toTopOf="parent"
16-
app:layout_constraintBottom_toBottomOf="parent"/>
9+
<androidx.recyclerview.widget.RecyclerView
10+
android:id="@+id/timeline_rv"
11+
android:layout_width="match_parent"
12+
android:layout_height="match_parent"/>
1713

18-
</androidx.constraintlayout.widget.ConstraintLayout>
14+
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
15+
android:id="@+id/fab"
16+
android:layout_width="wrap_content"
17+
android:layout_height="wrap_content"
18+
android:layout_margin="16dp"
19+
android:layout_gravity="bottom|end"
20+
android:text="@string/configure"
21+
app:icon="@drawable/ic_settings"/>
22+
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
<resources>
22
<string name="app_name">TimelineView Example</string>
3+
<string name="configure">Configure</string>
34
</resources>

0 commit comments

Comments
 (0)