@@ -21,17 +21,16 @@ import androidx.compose.foundation.background
2121import androidx.compose.foundation.border
2222import androidx.compose.foundation.layout.Box
2323import androidx.compose.foundation.layout.BoxScope
24+ import androidx.compose.foundation.layout.BoxWithConstraints
2425import androidx.compose.foundation.layout.fillMaxSize
2526import androidx.compose.foundation.layout.fillMaxWidth
2627import androidx.compose.foundation.layout.height
2728import androidx.compose.foundation.layout.offset
2829import androidx.compose.foundation.layout.size
29- import androidx.compose.foundation.layout.width
3030import androidx.compose.foundation.progressSemantics
3131import androidx.compose.foundation.shape.CircleShape
3232import androidx.compose.runtime.Composable
3333import androidx.compose.runtime.getValue
34- import androidx.compose.runtime.mutableFloatStateOf
3534import androidx.compose.runtime.mutableStateOf
3635import androidx.compose.runtime.remember
3736import androidx.compose.runtime.rememberUpdatedState
@@ -41,9 +40,7 @@ import androidx.compose.ui.Modifier
4140import androidx.compose.ui.geometry.CornerRadius
4241import androidx.compose.ui.geometry.Offset
4342import androidx.compose.ui.geometry.Size
44- import androidx.compose.ui.graphics.Color
4543import androidx.compose.ui.graphics.graphicsLayer
46- import androidx.compose.ui.layout.onSizeChanged
4744import androidx.compose.ui.platform.LocalDensity
4845import androidx.compose.ui.platform.LocalLayoutDirection
4946import 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,25 +173,24 @@ 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 ) }
185180 Canvas (
186181 modifier = modifier.graphicsLayer { scaleX = if (isRtl) - 1f else 1f },
187182 ) {
183+ if (totalBars <= 0 ) return @Canvas
184+
188185 val canvasW = size.width
189186 val canvasH = size.height
190187 val spaceWidth = canvasW * BarSpacingRatio
191188 val barsWidth = canvasW - spaceWidth
192189 val totalSpaces = totalBars - 1
193190 val barWidth = barsWidth / totalBars
194- val barSpacing = spaceWidth / totalSpaces
191+ val barSpacing = if (totalSpaces > 0 ) spaceWidth / totalSpaces else 0f
195192
196- val thresholdX = canvasW * finalProgress * visibleBars / visibleBarLimit
193+ val thresholdX = canvasW * finalProgress * visibleBars / totalBars
197194 val halfHeight = canvasH / 2
198195 if (barCornerRadius.x != barWidth || barCornerRadius.y != barWidth) {
199196 barCornerRadius = CornerRadius (barWidth, barWidth)
@@ -227,60 +224,62 @@ internal fun WaveformTrack(
227224 }
228225}
229226
230- @Preview(showBackground = true )
227+ @Preview(showBackground = true , widthDp = 250 )
231228@Composable
232- internal fun WaveformSeekBarPreview () {
233- val rand = Random ( 50 )
234- val waveform = List ( 50 ) { rand.nextFloat() }
229+ private fun StaticWaveformSliderAtStartPreview () {
230+ ChatPreviewTheme { StaticWaveformSliderSample (progress = 0f , isPlaying = true ) }
231+ }
235232
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- }
233+ @Preview(showBackground = true , widthDp = 250 )
234+ @Composable
235+ private fun StaticWaveformSliderMidwayPreview () {
236+ ChatPreviewTheme { StaticWaveformSliderSample (progress = 0.5f , isPlaying = true ) }
237+ }
238+
239+ @Preview(showBackground = true , widthDp = 250 )
240+ @Composable
241+ private fun StaticWaveformSliderPausedPreview () {
242+ ChatPreviewTheme { StaticWaveformSliderSample (progress = 0.3f , isPlaying = false ) }
254243}
255244
256- @Preview(showBackground = true )
245+ @Preview(showBackground = true , widthDp = 250 )
257246@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())
247+ private fun StaticWaveformSliderWithoutThumbPreview () {
248+ ChatPreviewTheme { StaticWaveformSliderSample (progress = 0.7f , isPlaying = true , isThumbVisible = false ) }
249+ }
250+
251+ @Composable
252+ private fun StaticWaveformSliderSample (progress : Float , isPlaying : Boolean , isThumbVisible : Boolean = true) {
253+ val previewWaveform = remember {
254+ val rand = Random (50 )
255+ List (50 ) { rand.nextFloat() }
263256 }
264257
258+ StaticWaveformSlider (
259+ modifier = Modifier
260+ .fillMaxWidth()
261+ .height(36 .dp),
262+ waveformData = previewWaveform,
263+ progress = progress,
264+ isPlaying = isPlaying,
265+ isThumbVisible = isThumbVisible,
266+ )
267+ }
268+
269+ @Preview(showBackground = true , widthDp = 250 )
270+ @Composable
271+ private fun FullWaveformTrackPreview () {
265272 ChatPreviewTheme {
266- Box (
273+ val waveform = List (100 ) { (it + 1 ) / 100f }
274+ WaveformTrack (
267275 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- }
276+ .fillMaxWidth()
277+ .height(60 .dp),
278+ waveformData = waveform,
279+ progress = 1f ,
280+ adjustBarWidthToLimit = true ,
281+ visibleBarLimit = 100 ,
282+ )
284283 }
285284}
286285
0 commit comments