Skip to content

Commit ec37e63

Browse files
committed
Fix WaveformSlider thumb and progress fill misalignment
1 parent 75cafde commit ec37e63

1 file changed

Lines changed: 84 additions & 87 deletions

File tree

  • stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/audio

stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/audio/WaveformSlider.kt

Lines changed: 84 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,16 @@ import androidx.compose.foundation.background
2121
import androidx.compose.foundation.border
2222
import androidx.compose.foundation.layout.Box
2323
import androidx.compose.foundation.layout.BoxScope
24+
import androidx.compose.foundation.layout.BoxWithConstraints
2425
import androidx.compose.foundation.layout.fillMaxSize
2526
import androidx.compose.foundation.layout.fillMaxWidth
2627
import androidx.compose.foundation.layout.height
2728
import androidx.compose.foundation.layout.offset
2829
import androidx.compose.foundation.layout.size
29-
import androidx.compose.foundation.layout.width
3030
import androidx.compose.foundation.progressSemantics
3131
import androidx.compose.foundation.shape.CircleShape
3232
import androidx.compose.runtime.Composable
3333
import androidx.compose.runtime.getValue
34-
import androidx.compose.runtime.mutableFloatStateOf
3534
import androidx.compose.runtime.mutableStateOf
3635
import androidx.compose.runtime.remember
3736
import androidx.compose.runtime.rememberUpdatedState
@@ -41,9 +40,7 @@ import androidx.compose.ui.Modifier
4140
import androidx.compose.ui.geometry.CornerRadius
4241
import androidx.compose.ui.geometry.Offset
4342
import androidx.compose.ui.geometry.Size
44-
import androidx.compose.ui.graphics.Color
4543
import androidx.compose.ui.graphics.graphicsLayer
46-
import androidx.compose.ui.layout.onSizeChanged
4744
import androidx.compose.ui.platform.LocalDensity
4845
import androidx.compose.ui.platform.LocalLayoutDirection
4946
import androidx.compose.ui.tooling.preview.Preview
@@ -60,7 +57,6 @@ import kotlin.random.Random
6057
*
6158
* @param modifier Modifier for styling.
6259
* @param waveformData The waveform data to display.
63-
* @param style The style for the waveform slider.
6460
* @param visibleBarLimit The number of bars to display at once.
6561
* @param adjustBarWidthToLimit Whether to adjust the bar width to fit the visible bar limit.
6662
* @param progress The current progress of the waveform.
@@ -84,43 +80,45 @@ public fun StaticWaveformSlider(
8480
) {
8581
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
8682
val currentProgress by rememberUpdatedState(progress)
87-
var widthPx by remember { mutableFloatStateOf(0f) }
88-
Box(
83+
BoxWithConstraints(
8984
modifier = modifier
9085
.fillMaxSize()
91-
.progressSemantics(value = progress)
92-
.onSizeChanged { size ->
93-
widthPx = size.width.toFloat()
94-
}
95-
.dragPointerInput(
96-
enabled = isThumbVisible,
97-
onDragStart = {
98-
onDragStart(it.toHorizontalProgress(widthPx, isRtl))
99-
},
100-
onDrag = {
101-
onDrag(it.toHorizontalProgress(widthPx, isRtl))
102-
},
103-
onDragStop = {
104-
onDragStop(it?.toHorizontalProgress(widthPx, isRtl) ?: currentProgress)
105-
},
106-
),
86+
.progressSemantics(value = progress),
10787
) {
108-
// Draw the waveform
109-
WaveformTrack(
110-
modifier = Modifier.fillMaxSize(),
111-
waveformData = waveformData,
112-
visibleBarLimit = visibleBarLimit,
113-
adjustBarWidthToLimit = adjustBarWidthToLimit,
114-
progress = progress,
115-
)
116-
117-
// Draw the thumb
118-
if (isThumbVisible) {
119-
WaveformHandle(
120-
isPlaying = isPlaying,
88+
val widthPx = constraints.maxWidth.toFloat()
89+
Box(
90+
modifier = Modifier
91+
.fillMaxSize()
92+
.dragPointerInput(
93+
enabled = isThumbVisible,
94+
onDragStart = {
95+
onDragStart(it.toHorizontalProgress(widthPx, isRtl))
96+
},
97+
onDrag = {
98+
onDrag(it.toHorizontalProgress(widthPx, isRtl))
99+
},
100+
onDragStop = {
101+
onDragStop(it?.toHorizontalProgress(widthPx, isRtl) ?: currentProgress)
102+
},
103+
),
104+
) {
105+
// Draw the waveform
106+
WaveformTrack(
107+
modifier = Modifier.fillMaxSize(),
108+
waveformData = waveformData,
109+
visibleBarLimit = visibleBarLimit,
110+
adjustBarWidthToLimit = adjustBarWidthToLimit,
121111
progress = progress,
122-
parentWidthPx = widthPx,
123112
)
113+
114+
// Draw the thumb
115+
if (isThumbVisible) {
116+
WaveformHandle(
117+
isPlaying = isPlaying,
118+
progress = progress,
119+
parentWidthPx = widthPx,
120+
)
121+
}
124122
}
125123
}
126124
}
@@ -175,10 +173,7 @@ internal fun WaveformTrack(
175173

176174
val totalBars = when (adjustBarWidthToLimit) {
177175
true -> visibleBarLimit
178-
else -> when (waveformData.size > visibleBarLimit) {
179-
true -> visibleBarLimit
180-
else -> waveformData.size
181-
}
176+
else -> minOf(waveformData.size, visibleBarLimit)
182177
}
183178
val visibleBars = minOf(visibleBarLimit, waveformData.size)
184179
var barCornerRadius by remember(totalBars) { mutableStateOf(CornerRadius.Zero) }
@@ -193,7 +188,7 @@ internal fun WaveformTrack(
193188
val barWidth = barsWidth / totalBars
194189
val barSpacing = spaceWidth / totalSpaces
195190

196-
val thresholdX = canvasW * finalProgress * visibleBars / visibleBarLimit
191+
val thresholdX = if (totalBars > 0) canvasW * finalProgress * visibleBars / totalBars else 0f
197192
val halfHeight = canvasH / 2
198193
if (barCornerRadius.x != barWidth || barCornerRadius.y != barWidth) {
199194
barCornerRadius = CornerRadius(barWidth, barWidth)
@@ -227,60 +222,62 @@ internal fun WaveformTrack(
227222
}
228223
}
229224

230-
@Preview(showBackground = true)
225+
@Preview(showBackground = true, widthDp = 250)
231226
@Composable
232-
internal fun WaveformSeekBarPreview() {
233-
val rand = Random(50)
234-
val waveform = List(50) { rand.nextFloat() }
227+
private fun StaticWaveformSliderAtStartPreview() {
228+
ChatPreviewTheme { StaticWaveformSliderSample(progress = 0f, isPlaying = true) }
229+
}
235230

236-
ChatPreviewTheme {
237-
Box(
238-
modifier = Modifier
239-
.width(250.dp)
240-
.height(60.dp)
241-
.background(Color.Cyan),
242-
contentAlignment = Alignment.Center,
243-
) {
244-
StaticWaveformSlider(
245-
modifier = Modifier
246-
.fillMaxWidth()
247-
.height(36.dp),
248-
waveformData = waveform,
249-
progress = 0.0f,
250-
isPlaying = true,
251-
)
252-
}
253-
}
231+
@Preview(showBackground = true, widthDp = 250)
232+
@Composable
233+
private fun StaticWaveformSliderMidwayPreview() {
234+
ChatPreviewTheme { StaticWaveformSliderSample(progress = 0.5f, isPlaying = true) }
235+
}
236+
237+
@Preview(showBackground = true, widthDp = 250)
238+
@Composable
239+
private fun StaticWaveformSliderPausedPreview() {
240+
ChatPreviewTheme { StaticWaveformSliderSample(progress = 0.3f, isPlaying = false) }
241+
}
242+
243+
@Preview(showBackground = true, widthDp = 250)
244+
@Composable
245+
private fun StaticWaveformSliderWithoutThumbPreview() {
246+
ChatPreviewTheme { StaticWaveformSliderSample(progress = 0.7f, isPlaying = true, isThumbVisible = false) }
254247
}
255248

256-
@Preview(showBackground = true)
257249
@Composable
258-
internal fun WaveformTrackPreview() {
259-
val waveform = mutableListOf<Float>()
260-
val barCount = 100
261-
for (i in 0 until barCount) {
262-
waveform.add((i + 1) / barCount.toFloat())
250+
private fun StaticWaveformSliderSample(progress: Float, isPlaying: Boolean, isThumbVisible: Boolean = true) {
251+
val previewWaveform = remember {
252+
val rand = Random(50)
253+
List(50) { rand.nextFloat() }
263254
}
264255

256+
StaticWaveformSlider(
257+
modifier = Modifier
258+
.fillMaxWidth()
259+
.height(36.dp),
260+
waveformData = previewWaveform,
261+
progress = progress,
262+
isPlaying = isPlaying,
263+
isThumbVisible = isThumbVisible,
264+
)
265+
}
266+
267+
@Preview(showBackground = true, widthDp = 250)
268+
@Composable
269+
private fun FullWaveformTrackPreview() {
265270
ChatPreviewTheme {
266-
Box(
271+
val waveform = List(100) { (it + 1) / 100f }
272+
WaveformTrack(
267273
modifier = Modifier
268-
.width(250.dp)
269-
.height(80.dp)
270-
.background(Color.Black),
271-
contentAlignment = Alignment.Center,
272-
) {
273-
WaveformTrack(
274-
modifier = Modifier
275-
.background(Color.Red)
276-
.fillMaxWidth()
277-
.height(60.dp),
278-
waveformData = waveform,
279-
progress = 0f,
280-
adjustBarWidthToLimit = true,
281-
visibleBarLimit = 100,
282-
)
283-
}
274+
.fillMaxWidth()
275+
.height(60.dp),
276+
waveformData = waveform,
277+
progress = 1f,
278+
adjustBarWidthToLimit = true,
279+
visibleBarLimit = 100,
280+
)
284281
}
285282
}
286283

0 commit comments

Comments
 (0)