Skip to content

Instantly share code, notes, and snippets.

@anitaa1990
Last active April 8, 2025 09:24
Show Gist options
  • Save anitaa1990/92e80882d23ed8c47ca52a29544de50c to your computer and use it in GitHub Desktop.
Save anitaa1990/92e80882d23ed8c47ca52a29544de50c to your computer and use it in GitHub Desktop.
@Composable
fun SlideToBookButton(
btnText: String,
btnTextStyle: TextStyle,
outerBtnBackgroundColor: Color,
sliderBtnBackgroundColor: Color,
@DrawableRes sliderBtnIcon: Int,
onBtnSwipe: () -> Unit
) {
// Slider button width
val sliderButtonWidthDp = 70.dp
/**
* ----------------------------------------
* ✨ Step 1:
* • Convert slider button width into pixels so we can use it in math
* • Define a variable to compute the current horizontal position of the slider button (in pixels)
* • Define a variable to capture the total width of the outer button in pixels
* ----------------------------------------
*/
val density = LocalDensity.current
val sliderButtonWidthPx = with(density) { sliderButtonWidthDp.toPx() }
var sliderPositionPx by remember { mutableFloatStateOf(0f) }
var boxWidthPx by remember { mutableIntStateOf(0) }
// The root layout for the button — stretches full width and has fixed height
Box(
modifier = Modifier
.fillMaxWidth()
.height(55.dp)
/**
* ----------------------------------------
* ✨ Step 2: Capture the full width of the button once it's laid out
* ----------------------------------------
*/
.onSizeChanged { size ->
boxWidthPx = size.width
}
) {
// Outer track — acts as the base of the button
Box(
modifier = Modifier
.matchParentSize()
.background(
color = outerBtnBackgroundColor,
shape = RoundedCornerShape(12.dp)
)
) {
// The center-aligned button label
Text(
text = btnText,
style = btnTextStyle,
modifier = Modifier.align(Alignment.Center)
)
}
// Slider thumb container, positioned at the left edge of the button
Row(
modifier = Modifier
.align(Alignment.CenterStart)
.padding(1.dp)
/**
* ----------------------------------------
* ✨ Step 3: Shift the slider button based on drag position (px to dp conversion)
* ----------------------------------------
*/
.offset(x = with(density) { sliderPositionPx.toDp() })
/**
* ----------------------------------------
* ✨ Step 4: Handle horizontal drag gestures
* ----------------------------------------
*/
.draggable(
orientation = Orientation.Horizontal,
state = rememberDraggableState { delta ->
// Calculate new potential position
val newPosition = sliderPositionPx + delta
// Clamp it within 0 to (totalWidth - slider button width)
val maxPosition = boxWidthPx - sliderButtonWidthPx
sliderPositionPx = newPosition.coerceIn(0f, maxPosition)
},
onDragStarted = { /* Optional: add feedback or animation here */ },
onDragStopped = {
// TODO: In next step, we’ll trigger onBtnSwipe if drag passes threshold
}
),
verticalAlignment = Alignment.CenterVertically
) {
Box(
modifier = Modifier
) {
// The draggable thumb itself
SliderButton(
sliderBtnWidth = sliderButtonWidthDp,
sliderBtnBackgroundColor = sliderBtnBackgroundColor,
sliderBtnIcon = sliderBtnIcon
)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment