A simple yet highly customizable UI library to show a timeline view in Compose Multiplatform.
Basic | Dashed | Dynamic |
---|---|---|
Custom | Extended | |
Android | iOS | Desktop | Web |
---|---|---|---|
In build.gradle
of shared module, include the following dependency
dependencies {
implementation("io.github.pushpalroy:jetlime:3.0.1")
}
Use the JetLimeColumn
val items = remember { mutableListOf(Item1, Item2, Item3) } // Any type of items
JetLimeColumn(
modifier = Modifier.padding(16.dp),
itemsList = ItemsList(items),
key = { _, item -> item.id },
) { index, item, position ->
JetLimeEvent(
style = JetLimeEventDefaults.eventStyle(
position = position
),
) {
// Content here
}
}
Use the JetLimeRow
val items = remember { mutableListOf(Item1, Item2, Item3) } // Any type of items
JetLimeRow(
modifier = Modifier.padding(16.dp),
itemsList = ItemsList(items),
key = { _, item -> item.id },
) { index, item, position ->
JetLimeEvent(
style = JetLimeEventDefaults.eventStyle(
position = position
),
) {
// Content here
}
}
Pass the key
to define factory of stable and unique keys representing the item. Using the same key for multiple items in the list is not allowed.
This key will be used by a LazyColumn or LazyRow internally.
If we want to add items dynamically from a data source, we should use mutableStateListOf
, so that our list can be observed as a state:
val items = remember { mutableStateListOf<MyItem>() }
Use the JetLimeExtendedEvent with a JetLimeColumn Using this we can pass an additional content to draw on the left side of the timeline.
val items = remember { mutableListOf(Item1, Item2, Item3) } // Any type of items
JetLimeColumn(
modifier = Modifier.padding(16.dp),
itemsList = ItemsList(items),
key = { _, item -> item.id },
style = JetLimeDefaults.columnStyle(contentDistance = 24.dp),
) { index, item, position ->
JetLimeExtendedEvent(
style = JetLimeEventDefaults.eventStyle(
position = position
),
additionalContent = {
// Additional content here
}
) {
// Content here
}
}
Use the JetLimeDefaults.columnStyle()
JetLimeColumn(
style = JetLimeDefaults.columnStyle(
contentDistance = 32.dp,
itemSpacing = 16.dp,
lineThickness = 2.dp,
lineBrush = JetLimeDefaults.lineSolidBrush(color = Color(0xFF2196F3)),
lineVerticalAlignment = RIGHT,
),
) {
// Code to add events
}
Use the JetLimeDefaults.rowStyle()
JetLimeRow(
style = JetLimeDefaults.rowStyle(
contentDistance = 32.dp,
itemSpacing = 16.dp,
lineThickness = 2.dp,
lineBrush = JetLimeDefaults.lineSolidBrush(color = Color(0xFF2196F3)),
lineHorizontalAlignment = BOTTOM,
),
) {
// Code to add events
}
Use the JetLimeEventDefaults.eventStyle()
JetLimeEvent(
style = JetLimeEventDefaults.eventStyle(
position = position,
pointColor = Color(0xFF2889D6),
pointFillColor = Color(0xFFD5F2FF),
pointRadius = 14.dp,
pointAnimation = JetLimeEventDefaults.pointAnimation(),
pointType = EventPointType.filled(0.8f),
pointStrokeWidth = 2.dp,
pointStrokeColor = MaterialTheme.colorScheme.onBackground,
),
) {
// Code to add event content
}
The timeline line and point circles can be set to either side.
For a JetLimeColumn
the alignment can be set to LEFT or RIGHT
lineVerticalAlignment = LEFT or RIGHT // Default is LEFT
For a JetLimeRow
the alignment can be set to TOP or BOTTOM
lineHorizontalAlignment = TOP or BOTTOM // Default is TOP
The line can be drawn by passing a Brush
object to lineBrush in a columnStyle
or rowStyle
.
Default values can also be used from JetLimeDefaults and colors can be modified for quick setup:
lineBrush = JetLimeDefaults.lineGradientBrush()
or
lineBrush = JetLimeDefaults.solidBrush()
A dashed/dotted line can also be drawn using the pathEffect
property by passing a PathEffect
to a columnStyle
or rowStyle
.
style = JetLimeDefaults.columnStyle(
pathEffect = PathEffect.dashPathEffect(
intervals = floatArrayOf(30f, 30f),
phase = 0f,
)
)
The contentDistance in Dp
specifies how far the timeline line should be from the timeline content.
The itemSpacing in Dp
specifies the gap between the event items.
The lineThickness in Dp
the thickness of the timeline line.
We always need to pass the position to the eventStyle that will be received in the JetLimeColumn lambda.
This is needed so that JetLimeColumn can calculate the position of an event in the list at any time.
Based on the calculation it will assign either of the three EventPosition: START
, MIDDLE
or END
.
This classification is needed to render correct lines for start and end items.
JetLimeColumn(
itemsList = ItemsList(items),
key = { _, item -> item.id },
) { index, item, position ->
JetLimeEvent(
style = JetLimeEventDefaults.eventStyle(
position = position
),
) {
// Content here
}
}
The pointType
of type EventPointType specifies the style of the point circle.
It can be any of the three types: EMPTY
, FILLED
or CUSTOM
.
For using EMPTY
pointType = EventPointType.EMPTY
For using FILLED
, the filled() function has to be used which takes an optional fillPercent
pointType = EventPointType.filled(0.8f)
For using CUSTOM
, the custom() function has to be used which takes an icon
of Painter
.
This can be used to use a custom icon instead of the default types defined. An optional tint
can also be applied on the icon.
pointType = EventPointType.custom(icon = painterResource(id = R.drawable.icon_check), tint = Color.Green)
The pointAnimation
of type EventPointAnimation specifies the animation of the point circle.
To enable the default animation
pointAnimation = JetLimeEventDefaults.pointAnimation()
To use a custom animation initialValue
, targetValue
and animationSpec
can be passed to pointAnimation()
.
animationSpec
should be of the type InfiniteRepeatableSpec<Float>
.
The pointColor
is the color of the event point circle background.
The pointFillColor
is the fill color of the event point circle which is drawn over the pointColor
.
The pointRadius
in Dp
is the radius of the point circle.
The pointStrokeWidth
in Dp
is the width of the circle border.
The pointStrokeColor
is the color of the circle border.
The full API documentation is available here: JetLime Documentation
- Timeline-View by Vipul Asri
- This amazing blog by Vita Sokolova on Timeline component with Jetpack Compose
Would love to receive contributions! Read contribution guidelines for more information regarding contribution.
Have any questions, doubts or want to present your opinions, views? You're always welcome. You can start discussions.
MIT License
Copyright (c) 2024 Pushpal Roy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.