Skip to content

Commit

Permalink
Merge pull request #116 from Trendyol/MCHECKOUT-900/addShadowAndIndex…
Browse files Browse the repository at this point in the history
…TextToPoints

add shadow and index text to points and fit to screen
  • Loading branch information
edaersu authored Jul 27, 2023
2 parents c2eee44 + b23262f commit 98f1eb7
Show file tree
Hide file tree
Showing 15 changed files with 413 additions and 15 deletions.
53 changes: 44 additions & 9 deletions libraries/timeline-view-compose/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
|:-----------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------:|
| **Horizontal Simple** | **Horizontal Animated** | **Vertical Simple** | **Vertical Animated** |

timelineViewComposeVersion = **timeline-view-compose-1.0** [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
timelineViewComposeVersion = **timeline-view-compose-1.2.0** [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

# TimelineView

TimelineView creates a timeline and shows actions over time.

# HorizontalTimelineWithIndexText

HorizontalTimelineWithIndexText creates a timeline with points at their midpoints displaying their respective indexes.
The line width is automatically calculated and centered horizontally to fit the screen. It can contain any number of steps.

# Installation

- To implement **TimelineView** to your Android project via Gradle, you need to add JitPack repository to your root build.gradle.
Expand All @@ -30,7 +35,7 @@ dependencies {

# Usage

To start using TimelineView, `TimelineView` composable can be used like this
➡️ To start using TimelineView, `TimelineView` composable can be used like this

*To customize each item, you can modify pointConfig and lineConfig.*

Expand Down Expand Up @@ -97,6 +102,15 @@ val timelineItems = listOf(
)
```

➡️ To start using HorizontalTimelineWithIndexText, `HorizontalTimelineWithIndexText` composable can be used like this

```kotlin
HorizontalTimelineWithIndexTextView(
modifier = Modifier.padding(horizontal = 16.dp),
items = createHorizontalWithIndexTimelineItems(),
)
```

# Paremeters

#### Models
Expand Down Expand Up @@ -151,19 +165,28 @@ val timelineItems = listOf(
| size | Dp | To set size |
| animation | PointAnimation | To set animation |

###### PointShadowConfig

| Parameter Name | Type | Description |
|----------------|-------|------------------------|
| elevation | Int | To set elevation |
| color | Color | To set color |
| alpha | Float | To set alpha of shadow |

#### Item Types

---

###### TimelineItem.Point

| Parameter Name | Type | Description |
|----------------|-------------|----------------------|
| text | String | To set text |
| textStyle | TextStyle | To set textStyle |
| pointConfig | PointConfig | To set pointConfig |
| contentMargin | Dp | To set contentMargin |
| lineConfig | LineConfig | To set lineConfig |
| Parameter Name | Type | Description |
|-------------------|-------------------|----------------------|
| text | String | To set text |
| textStyle | TextStyle | To set textStyle |
| pointConfig | PointConfig | To set pointConfig |
| contentMargin | Dp | To set contentMargin |
| lineConfig | LineConfig | To set lineConfig |
| pointShadowConfig | PointShadowConfig | To set shadow |

###### TimelineItem.Image

Expand All @@ -175,6 +198,18 @@ val timelineItems = listOf(
| imageConfig | ImageConfig | To set imageConfig |
| lineConfig | LineConfig | To set lineConfig |

###### TimelineItem.PointWithIndex

| Parameter Name | Type | Description |
|-------------------|-------------------|----------------------|
| text | String | To set text |
| textStyle | TextStyle | To set textStyle |
| pointConfig | PointConfig | To set pointConfig |
| contentMargin | Dp | To set contentMargin |
| lineConfig | LineConfig | To set lineConfig |
| pointShadowConfig | PointShadowConfig | To set shadow |
| indexTextStyle | TextStyle | To set index style |

# Contributors

This library is maintained mainly by Trendyol Android Team members but also other Android lovers contributes.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.trendyol.uicomponents.timelineviewcompose

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.trendyol.uicomponents.timelineviewcompose.item.HorizontalTimelineWithIndexTextItem
import com.trendyol.uicomponents.timelineviewcompose.model.FakeTimelineItemProvider
import com.trendyol.uicomponents.timelineviewcompose.model.TimelineItem

/***
* The line sizes are automatically calculated and set to fit the screen.
* It accepts 'PointWithIndex' as an item.
*/
@Composable
fun HorizontalTimelineWithIndexTextView(
items: List<TimelineItem.PointWithIndex>,
modifier: Modifier = Modifier,
onClick: (TimelineItem) -> Unit = {},
) {

var availableWidth by remember { mutableStateOf(0) }
val availableWidthPx = with(LocalDensity.current) { availableWidth.toDp() }

Row(
horizontalArrangement = Arrangement.Center,
modifier = modifier
.fillMaxWidth()
.onGloballyPositioned { availableWidth = it.size.width }) {
items.forEachIndexed { index, item ->
val lineWidthDp =
((availableWidthPx - (item.pointConfig.getSizeWithBorder() * items.size)) / (items.size - 1))
val itemWidth = item.pointConfig.getSizeWithBorder() + lineWidthDp

HorizontalTimelineWithIndexTextItem(
item = item,
itemIndex = index,
isLastItem = items.isLastItem(index),
onClick = { onClick(items[index]) },
itemIndexTextStyle = item.indexTextStyle,
customLineWidth = itemWidth
)
}
}
}

private fun List<TimelineItem>.isLastItem(index: Int): Boolean {
return index == size - 1
}

@Composable
@Preview(showBackground = true)
private fun TimelineViewVerticalPreview() {
HorizontalTimelineWithIndexTextView(
modifier = Modifier.padding(horizontal = 16.dp),
items = FakeTimelineItemProvider.provideTimelineItemWithTextList()
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import com.trendyol.uicomponents.timelineviewcompose.model.LineConfig
Expand All @@ -27,6 +28,7 @@ internal fun Line(
itemIndex: Int,
modifier: Modifier = Modifier,
orientation: TimelineOrientation = TimelineOrientation.HORIZONTAL,
customLineWidth: Dp? = null
) {
val pathEffect = when (config.lineType) {
is LineType.Dashed -> PathEffect.dashPathEffect(
Expand All @@ -39,7 +41,7 @@ internal fun Line(

val itemSize = when (orientation) {
TimelineOrientation.HORIZONTAL -> DpSize(
width = config.size,
width = customLineWidth ?: config.size,
height = config.thickness
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,39 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.trendyol.uicomponents.timelineviewcompose.model.PointConfig
import com.trendyol.uicomponents.timelineviewcompose.model.PointShadowConfig

@Composable
internal fun TimelinePoint(
modifier: Modifier = Modifier,
config: PointConfig,
pointShadowConfig: PointShadowConfig? = null,
onClick: () -> Unit = {},
) {

val shadowModifier = if (pointShadowConfig != null) {
Modifier
.shadow(
elevation = pointShadowConfig.elevation.dp,
shape = CircleShape,
ambientColor = pointShadowConfig.color.copy(alpha = pointShadowConfig.alpha),
)
} else {
Modifier
}

val borderAlpha = pointShadowConfig?.alpha ?: 0.2f

Canvas(
modifier = modifier
.then(shadowModifier)
.size(config.size + config.borderWidth)
.graphicsLayer { alpha = 0.99f }
.scaleAnimation(config.animation)
Expand All @@ -46,16 +63,16 @@ internal fun TimelinePoint(
blendMode = BlendMode.DstOver
)

// shadow
// border
drawCircle(
color = config.insideColor.copy(alpha = 0.2f),
color = config.insideColor.copy(alpha = borderAlpha),
radius = radiusPx + config.borderWidth.div(2).toPx(),
blendMode = BlendMode.DstOver,
)
}
}

@Preview
@Preview(showBackground = true)
@Composable
private fun TimelinePointPreview() {
TimelinePoint(
Expand All @@ -64,6 +81,11 @@ private fun TimelinePointPreview() {
borderWidth = 2.dp,
insideColor = Color.Green,
outSideColor = Color.White
),
pointShadowConfig = PointShadowConfig(
elevation = 7,
color = Color.Black,
alpha = 0.6f,
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ private fun VerticalTimelineView(
onClick = { onClick(items[index]) },
)
}
else -> {}
}
}
}
Expand Down Expand Up @@ -97,6 +98,7 @@ private fun HorizontalTimelineView(
onClick = { onClick(items[index]) },
)
}
else -> {}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ internal fun HorizontalTimelineImageItem(
itemIndex = itemIndex,
orientation = TimelineOrientation.HORIZONTAL,
modifier = Modifier.layoutId(LineLayoutId),
customLineWidth = item.lineConfig.size
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ internal fun HorizontalTimelineItem(
config = item.pointConfig,
modifier = Modifier.layoutId(PointLayoutId),
onClick = onClick,
pointShadowConfig = item.pointShadowConfig
)
Text(
text = item.text,
Expand All @@ -65,7 +66,8 @@ internal fun HorizontalTimelineItem(
itemIndex = itemIndex,
config = item.lineConfig,
orientation = TimelineOrientation.HORIZONTAL,
modifier = Modifier.layoutId(LineLayoutId)
modifier = Modifier.layoutId(LineLayoutId),
customLineWidth = item.lineConfig.size,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.trendyol.uicomponents.timelineviewcompose.item

import androidx.compose.foundation.layout.width
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import com.trendyol.uicomponents.timelineviewcompose.Line
import com.trendyol.uicomponents.timelineviewcompose.TimelinePoint
import com.trendyol.uicomponents.timelineviewcompose.model.FakeTimelineItemProvider
import com.trendyol.uicomponents.timelineviewcompose.model.IndexTextLayoutId
import com.trendyol.uicomponents.timelineviewcompose.model.LineLayoutId
import com.trendyol.uicomponents.timelineviewcompose.model.PointLayoutId
import com.trendyol.uicomponents.timelineviewcompose.model.TextLayoutId
import com.trendyol.uicomponents.timelineviewcompose.model.TimelineItem
import com.trendyol.uicomponents.timelineviewcompose.model.TimelineOrientation
import com.trendyol.uicomponents.timelineviewcompose.model.getHorizontalWithIndexConstraintSet

@Composable
internal fun HorizontalTimelineWithIndexTextItem(
modifier: Modifier = Modifier,
item: TimelineItem.PointWithIndex,
isLastItem: Boolean = false,
itemIndex: Int,
itemIndexTextStyle: TextStyle,
customLineWidth : Dp = 0.dp,
onClick: () -> Unit = {},
) {

val itemWidth =item.pointConfig.getSizeWithBorder() + customLineWidth

ConstraintLayout(
constraintSet = getHorizontalWithIndexConstraintSet(item.contentMargin, itemWidth),
modifier = modifier
.width(customLineWidth)
) {
TimelinePoint(
config = item.pointConfig,
modifier = Modifier.layoutId(PointLayoutId),
onClick = onClick,
pointShadowConfig = item.pointShadowConfig
)
Text(
text = item.text,
style = item.textStyle,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center,
maxLines = 2,
modifier = Modifier
.width(itemWidth)
.layoutId(TextLayoutId)
)
Text(
text = (itemIndex + 1).toString(),
modifier = Modifier.layoutId(IndexTextLayoutId),
style = itemIndexTextStyle,
)
if (!isLastItem) {
Line(
itemIndex = itemIndex,
config = item.lineConfig,
orientation = TimelineOrientation.HORIZONTAL,
modifier = Modifier.layoutId(LineLayoutId),
customLineWidth = customLineWidth - item.pointConfig.borderWidth
)
}
}
}

@Composable
@Preview(showBackground = true)
private fun HorizontalWithIndexTimelineItemPreview() {
HorizontalTimelineWithIndexTextItem(
item = FakeTimelineItemProvider.provideTimelineItemWithText(text = "Siparişiniz hazırlanıyor"),
isLastItem = false,
itemIndex = 0,
itemIndexTextStyle = TextStyle(color = Color.White),
)
}
Loading

0 comments on commit 98f1eb7

Please sign in to comment.