Skip to content

Instantly share code, notes, and snippets.

@MansuriYamin
Created July 16, 2023 14:38
Show Gist options
  • Save MansuriYamin/aa8628fb0d48b12a0b267bf7c573f4b5 to your computer and use it in GitHub Desktop.
Save MansuriYamin/aa8628fb0d48b12a0b267bf7c573f4b5 to your computer and use it in GitHub Desktop.
private fun customSliderMeasurePolicy(
itemCount: Int,
gap: Int,
value: Float,
startValue: Float
) = MeasurePolicy { measurables, constraints ->
// Measure the thumb component and calculate its radius.
val thumbPlaceable = measurables.first {
it.layoutId == CustomSliderComponents.THUMB
}.measure(constraints)
val thumbRadius = (thumbPlaceable.width / 2).toFloat()
val indicatorPlaceables = measurables.filter {
it.layoutId == CustomSliderComponents.INDICATOR
}.map { measurable ->
measurable.measure(constraints)
}
val indicatorHeight = indicatorPlaceables.maxByOrNull { it.height }?.height ?: 0
val sliderPlaceable = measurables.first {
it.layoutId == CustomSliderComponents.SLIDER
}.measure(constraints)
val sliderHeight = sliderPlaceable.height
val labelPlaceable = measurables.find {
it.layoutId == CustomSliderComponents.LABEL
}?.measure(constraints)
val labelHeight = labelPlaceable?.height ?: 0
// Calculate the total width and height of the custom slider layout
val width = sliderPlaceable.width
val height = labelHeight + sliderHeight + indicatorHeight
// Calculate the available width for the track (excluding thumb radius on both sides).
val trackWidth = width - (2 * thumbRadius)
// Calculate the width of each section in the track.
val sectionWidth = trackWidth / itemCount
// Calculate the horizontal spacing between indicators.
val indicatorSpacing = sectionWidth * gap
// To calculate offset of the label, first we will calculate the progress of the slider
// by subtracting startValue from the current value.
// After that we will multiply this progress by the sectionWidth.
// Add thumb radius to this resulting value.
val labelOffset = (sectionWidth * (value - startValue)) + thumbRadius
layout(width = width, height = height) {
var indicatorOffsetX = thumbRadius
// Place label at top.
// We have to subtract the half width of the label from the labelOffset,
// to place our label at the center.
labelPlaceable?.placeRelative(
x = (labelOffset - (labelPlaceable.width / 2)).roundToInt(),
y = 0
)
// Place slider placeable below the label.
sliderPlaceable.placeRelative(x = 0, y = labelHeight)
// Place indicators below the slider.
indicatorPlaceables.forEach { placeable ->
// We have to subtract the half width of the each indicator from the indicatorOffset,
// to place our indicators at the center.
placeable.placeRelative(
x = (indicatorOffsetX - (placeable.width / 2)).roundToInt(),
y = labelHeight + sliderHeight
)
indicatorOffsetX += indicatorSpacing
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment