Skip to content

Commit

Permalink
feat: Update demo for the Slider
Browse files Browse the repository at this point in the history
  • Loading branch information
levinzonr committed Mar 20, 2024
1 parent 0d870bb commit c07d659
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 79 deletions.
210 changes: 138 additions & 72 deletions demo/src/main/java/io/monstarlab/mosaic/features/SliderDemo.kt
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@
package io.monstarlab.mosaic.features

import androidx.compose.animation.animateColor
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import io.monstarlab.mosaic.slider.Slider
Expand All @@ -41,99 +59,147 @@ fun SliderDemo() = Scaffold(modifier = Modifier) {
onValueChange = { materialSliderValue = it },
valueRange = 0f..100f,
)
Text(text = materialSliderValue.toString())

MosaicSliderDemo(
label = "Linear division strategy",
range = 0f..1000f,
valuesDistribution = SliderValueDistribution.Linear,
disabledRange = 0f..500f,
MosaicSliderDemo()
}
}

@Composable
fun MosaicSliderDemo() {
Column {
val colors = SliderColors(
activeTrackColor = Color.Black,
disabledRangeTrackColor = Color.Red,
thumbColor = Color.Yellow,
)
MosaicSliderDemo(
label = "Parabolic",
range = 0f..1000f,
disabledRange = 800f..1000f,
valuesDistribution = SliderValueDistribution.parabolic(
var enabled by remember { mutableStateOf(true) }
var isCustom by remember { mutableStateOf(false) }
var linearDistribution by remember { mutableStateOf(false) }

val modifier = if (isCustom) {
Modifier
.clip(RoundedCornerShape(16.dp))
.height(15.dp)
} else {
Modifier
}

val parabolic: SliderValueDistribution = remember {
SliderValueDistribution.parabolic(
a = (1000 - 100 * 0.1f) / (1000 * 1000),
b = 0.1f,
c = 1f,
),
)
}

val state = rememberSliderState(
value = 500f,
valueDistribution = if (linearDistribution) {
SliderValueDistribution.Linear
} else {
parabolic
},
range = 0f..1000f,
)

Slider(
state = rememberSliderState(value = 0.5f),
colors = SliderColors(Color.Magenta, Color.Red),
modifier = modifier,
enabled = enabled,
state = state,
colors = colors,
thumb = {
if (isCustom) {
val transition = rememberInfiniteTransition(label = "")
val color = transition.animateColor(
initialValue = Color.Red,
targetValue = Color.Green,
animationSpec = infiniteRepeatable(
animation = tween(1000, easing = LinearEasing),
repeatMode = RepeatMode.Reverse,
),
label = "",
)

val rotation = transition.animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(
tween(5000, easing = LinearEasing),
repeatMode = RepeatMode.Restart,
),
label = "",
)

Box(
modifier = Modifier
.rotate(rotation.value)
.size(48.dp)
.background(color.value),
)
} else {
Box(
modifier = Modifier
.size(16.dp)
.background(colors.thumbColor(enabled), CircleShape),
)
}
},

)

Text(
text = "Current value: ${state.value.roundToInt()}",
modifier = Modifier.align(Alignment.CenterHorizontally),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodyLarge,
)

Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier
.fillMaxWidth()
.padding(top = 32.dp),
) {
Box(
modifier = Modifier
.size(32.dp)
.background(Color.Black),
LabeledSwitch(
label = "Slider enabled",
checked = enabled,
onValueChange = { enabled = it },
)
}

Slider(
state = rememberSliderState(value = 0.5f),
colors = SliderColors(Color.Black),
enabled = true,
) {
Box(modifier = Modifier.background(Color.Red, shape = CircleShape).size(32.dp))
LabeledSwitch(
label = "Customise",
checked = isCustom,
onValueChange = { isCustom = it },
)
}

var v by remember { mutableFloatStateOf(0.5f) }
Slider(
value = v,
onValueChange = { v = it },
colors = SliderColors(Color.Black),
enabled = false,
) {
Box(modifier = Modifier.background(Color.Red, shape = CircleShape).size(32.dp))
}
LabeledSwitch(
label = "Use linear distribution or parabolic",
checked = linearDistribution,
onValueChange = { linearDistribution = it },
modifier = Modifier.align(Alignment.CenterHorizontally),
)
}
}

@Composable
fun MosaicSliderDemo(
private fun LabeledSwitch(
label: String,
range: ClosedFloatingPointRange<Float>,
valuesDistribution: SliderValueDistribution,
checked: Boolean,
onValueChange: (Boolean) -> Unit,
modifier: Modifier = Modifier,
disabledRange: ClosedFloatingPointRange<Float> = 0f..0f,
) {
Column(modifier) {
Text(text = label)
Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally,

var value by remember { mutableFloatStateOf(50f) }
Row(
horizontalArrangement = Arrangement.Start,
modifier = Modifier,
) {
Text(
text = range.start.toString(),
modifier = Modifier.weight(0.2f),
)
Slider(
modifier = Modifier.weight(0.8f),
value = value,
onValueChange = { value = it },
colors = SliderColors(Color.Black, disabledRangeTrackColor = Color.Red),
range = range,
valueDistribution = valuesDistribution,
disabledRange = disabledRange,
thumb = {
Box(
modifier = Modifier
.size(32.dp)
.background(Color.Yellow),
) {
Text(text = value.roundToInt().toString())
}
},
)
Text(
text = range.endInclusive.toString(),
modifier = Modifier.weight(0.2f),
)
}
) {
Text(text = label, textAlign = TextAlign.Center)
Spacer(modifier = Modifier.height(3.dp))
Switch(
checked = checked,
onCheckedChange = onValueChange,
)
}
}

Expand Down
12 changes: 6 additions & 6 deletions slider/src/main/java/io/monstarlab/mosaic/slider/Slider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ public fun Slider(
* A composable function that creates a slider UI component.
* @param state of the Slider where the latest slider value is stored
* @param colors the colors used to customize the appearance of the slider
* @param modifier the modifier to be applied to the slider,
* @param modifier the modifier to be applied to the slider overall. Use to manipulate the behaviour in other layouts,
* @param trackModifier - Modifier to be applied to the Track, U
* @param enabled - determines whether the user can interact with the slide or not
* @param interactionSource the interaction source used to handle user input interactions
* @param thumb the composable function used to render the slider thumb
Expand All @@ -90,22 +91,21 @@ public fun Slider(
thumb: @Composable (SliderState) -> Unit,
) {
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
val tap = Modifier.sliderTapModifier(state, enabled, interactionSource)
val drag = Modifier.sliderDragModifier(state, enabled, interactionSource, isRtl)

SliderLayout(
modifier = modifier
modifier = Modifier
.sliderSemantics(state, enabled)
.focusable(enabled, interactionSource)
.then(tap)
.then(drag),
.sliderTapModifier(state, enabled, interactionSource)
.sliderDragModifier(state, enabled, interactionSource, isRtl),
thumb = thumb,
track = {
SliderTrack(
progress = state.valueAsFraction,
colors = colors,
disabledRange = state.disabledRangeAsFractions,
enabled = enabled,
modifier = modifier,
)
},
state = state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class SliderColors(
* Color of the thumb when the Slider is disabled
* Only applied when the default thumb is used
*/
public val disabledThumbColor: Color = disabledRangeTrackColor,
public val disabledThumbColor: Color = inactiveTrackColor,
) {
@Stable
public fun activeTrackColor(enabled: Boolean): Color {
Expand Down

0 comments on commit c07d659

Please sign in to comment.