Instantly share code, notes, and snippets.
Last active
April 9, 2025 19:53
-
Star
1
(1)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save anitaa1990/b687344c083275c78ae9f022cc2c2341 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@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) } | |
/** | |
* ---------------------------------------- | |
* ✨ Step 5: Calculate drag progress percentage (0f to 1f) | |
* ---------------------------------------- | |
*/ | |
val dragProgress = remember(sliderPositionPx, boxWidthPx) { | |
if (boxWidthPx > 0) { | |
(sliderPositionPx / (boxWidthPx - sliderButtonWidthPx)).coerceIn(0f, 1f) | |
} else { | |
0f | |
} | |
} | |
/** | |
* ---------------------------------------- | |
* ✨ Step 6: Alpha value for the button label — 1 when untouched, fades to 0 as drag progresses | |
* ---------------------------------------- | |
*/ | |
val textAlpha = 1f - dragProgress | |
// 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) | |
/** | |
* ---------------------------------------- | |
* ✨ Step 7: Apply the dynamic transparency to the label | |
* ---------------------------------------- | |
*/ | |
.alpha(textAlpha) | |
) | |
} | |
// 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 = { } | |
), | |
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