Skip to content

Instantly share code, notes, and snippets.

@sajjadyousefnia
Created August 30, 2024 16:15
Show Gist options
  • Save sajjadyousefnia/ea6b342a2e6961549b5d617e4364a635 to your computer and use it in GitHub Desktop.
Save sajjadyousefnia/ea6b342a2e6961549b5d617e4364a635 to your computer and use it in GitHub Desktop.
@Composable
public fun DualSwitch(selection: Int) {
CardContainer {
Box {
val scope = rememberCoroutineScope()
val selection = remember {
mutableIntStateOf(selection)
}
val weight = remember {
mutableStateOf(0.5f)
}
Row {
Button(modifier = Modifier
.weight(.5f)
.fillMaxHeight(),
colors = ButtonDefaults.buttonColors(transparent),
shape = RoundedCornerShape(cornerSize),
onClick = {
selection.value = 1
}) {
}
Button(modifier = Modifier
.weight(.5f)
.fillMaxHeight(),
colors = ButtonDefaults.buttonColors(transparent),
shape = RoundedCornerShape(cornerSize),
onClick = {
selection.value = 2
}) {
}
}
Row(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
horizontalArrangement = when (selection.value) {
1 -> Arrangement.Start
2 -> Arrangement.End
else -> Arrangement.Center
}
) {
Card(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(weight.value)
.animatePlacement()
.animateContentSize(
(SpringSpec(stiffness = Spring.StiffnessLow)),
),
shape = RoundedCornerShape(cornerSize),
colors = CardDefaults.cardColors(md_theme_dark_scrim)
) {}
}
}
}
}
@Composable
fun CardContainer(
content: @Composable ColumnScope.() -> Unit
) {
Card(
modifier = Modifier
.fillMaxWidth()
.height(60.dp),
shape = RoundedCornerShape(cornerSize),
content = content,
colors = CardDefaults.cardColors(
contentColor = control_disabled_color,
containerColor = control_disabled_color,
disabledContainerColor = control_disabled_color,
disabledContentColor = control_disabled_color
)
)
}
/**
* notifies and changes the position of the child in the parent layout
* */
fun Modifier.animatePlacement(): Modifier = composed {
val scope = rememberCoroutineScope()
var targetOffset by remember { mutableStateOf(IntOffset.Zero) }
var animatable by remember {
mutableStateOf<Animatable<IntOffset, AnimationVector2D>?>(null)
}
this
// 🔥 onPlaced should be before offset Modifier
.onPlaced {
// Calculate the position in the parent layout
targetOffset = it
.positionInParent()
.round()
}
.offset {
// Animate to the new target offset when alignment changes.
val anim = animatable ?: Animatable(targetOffset, IntOffset.VectorConverter).also {
animatable = it
}
if (anim.targetValue != targetOffset) {
scope.launch {
anim.animateTo(targetOffset, spring(stiffness = Spring.StiffnessMediumLow))
}
}
// Offset the child in the opposite direction to the targetOffset, and slowly catch
// up to zero offset via an animation to achieve an overall animated movement.
animatable?.let { it.value - targetOffset } ?: IntOffset.Zero
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment