|
@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 |
|
) |
|
} |
|
} |
|
} |
|
} |