Optimize midi control space & modernize volume slider

This commit is contained in:
hasinarak3@gmail.com 2026-02-03 16:06:30 +03:00
parent 337f1d9912
commit da1d130085
2 changed files with 177 additions and 121 deletions

View file

@ -46,6 +46,8 @@ import androidx.compose.material.icons.filled.Tonality
import androidx.compose.material.icons.filled.Tune
import androidx.compose.material.icons.automirrored.filled.VolumeUp
import androidx.compose.material.icons.automirrored.filled.VolumeOff
import androidx.compose.material.icons.filled.MoreHoriz
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
@ -80,7 +82,9 @@ import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.delay
import mg.dot.feufaro.getPlatform
import mg.dot.feufaro.midi.MediaPlayer
import org.koin.core.component.getScopeId
import javax.swing.Icon
@OptIn(ExperimentalMaterial3Api::class)
@ -120,7 +124,7 @@ fun MidiControlPanel(
var showInstruTools by remember { mutableStateOf(false) }
var showSATBTools by remember { mutableStateOf(false) }
var showVolumeTools by remember { mutableStateOf(false) }
var expandedCtl by remember { mutableStateOf(false) }
LaunchedEffect(tempo) {
currentBpm = mediaPlayer.getCurrentBPM()
}
@ -130,6 +134,9 @@ fun MidiControlPanel(
.padding(16.dp)
.background(color = Color.Gray.copy(alpha = 0.5f), shape = RoundedCornerShape(size = 5.dp)),
horizontalAlignment = Alignment.CenterHorizontally
) {
AnimatedVisibility(
visible = !expandedCtl
) {
Row(
verticalAlignment = Alignment.CenterVertically,
@ -168,27 +175,8 @@ fun MidiControlPanel(
)
Text("${momo / 1000}s", color = Color.White)
}
Row(
verticalAlignment = Alignment.CenterVertically
){
IconButton(
onClick = onPlayPauseClick,
modifier = Modifier.size(48.dp)
) {
Icon(
imageVector = if (isPause) Icons.Filled.PlayArrow else Icons.Filled.Pause,
contentDescription = "Pla",
tint = MaterialTheme.colorScheme.primary
)
}
}
AnimatedVisibility(
visible = showSATBTools,
enter = fadeIn() + scaleIn() + slideInVertically { it / 2 },
@ -302,10 +290,22 @@ fun MidiControlPanel(
}
}
}
Row(
verticalAlignment = Alignment.CenterVertically
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround
){
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Box(contentAlignment = Alignment.CenterStart) {
IconButton(
onClick = {
showBPMTools = !showBPMTools
}
) {
Icon(imageVector = Icons.Default.AvTimer, contentDescription = "Tempo")
}
}
Box( contentAlignment = Alignment.CenterStart) {
val isAtStart = loopState.first == -1L
val isWaitingForB = loopState.first != -1L && !loopState.third
val isLooping = loopState.third
@ -326,8 +326,15 @@ fun MidiControlPanel(
else -> Color.LightGray
}
),
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 0.dp),
shape = RoundedCornerShape(5.dp) ,
modifier = Modifier.padding(2.dp)
modifier = Modifier
.height(34.dp)
.padding(horizontal = 4.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(
text = "A",
@ -351,78 +358,54 @@ fun MidiControlPanel(
)
}
}
Column(horizontalAlignment = Alignment.CenterHorizontally) {
IconButton(
onClick = {
showBPMTools = !showBPMTools
}) {
Icon(imageVector = Icons.Default.AvTimer, contentDescription = "Tempo")
}
AnimatedVisibility(visible = showBPMTools){
Box(
modifier = Modifier
.width(20.dp)
.height(3.dp)
.background(MaterialTheme.colorScheme.primary, RoundedCornerShape(2.dp))
)}
}
Column(horizontalAlignment = Alignment.CenterHorizontally) {
IconButton(
onClick = {
showInstruTools = !showInstruTools
}) {
Icon(imageVector = Icons.Default.Tune, contentDescription = "Instru")
}
AnimatedVisibility(visible = showInstruTools){
Box(
modifier = Modifier
.width(20.dp)
.height(3.dp)
.background(MaterialTheme.colorScheme.primary, RoundedCornerShape(2.dp))
)}
}
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Box(contentAlignment = Alignment.Center) {
IconButton(
onClick = {
showSATBTools = !showSATBTools
}) {
Icon(imageVector = Icons.Default.SettingsVoice, contentDescription = "SATB")
}
AnimatedVisibility(visible = showSATBTools){
Box(
modifier = Modifier
.width(20.dp)
.height(3.dp)
.background(MaterialTheme.colorScheme.primary, RoundedCornerShape(2.dp))
)}
}
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Box(contentAlignment = Alignment.Center) {
IconButton(
onClick = onPlayPauseClick,
modifier = Modifier.size(48.dp)
) {
Icon(
imageVector = if (volume > 0) Icons.AutoMirrored.Filled.VolumeUp else Icons.AutoMirrored.Filled.VolumeOff,
contentDescription = null,
modifier = Modifier.size(20.dp)
imageVector = if (isPause) Icons.Filled.PlayArrow else Icons.Filled.Pause,
contentDescription = "Pla",
tint = MaterialTheme.colorScheme.primary
)
}
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Slider(
value = volume,
onValueChange = onVolumeChange,
valueRange = 0f..1f,
modifier = Modifier.width(100.dp),
thumb = {
Box(
modifier = Modifier.size(15.dp).background(Color.Blue, CircleShape)
}
Box(contentAlignment = Alignment.CenterEnd) {
IconButton(
onClick = {
showInstruTools = !showInstruTools
}
) {
Icon(imageVector = Icons.Default.Tune, contentDescription = "Instru")
}
}
val platform = getPlatform()
if (platform.name.startsWith("Java")) {
ModernVolumeSlider(
volume, onVolumeChange = onVolumeChange
)
},
track = { sliderState ->
SliderDefaults.Track(
sliderState = sliderState, modifier = Modifier.height(5.dp)
}
Row(
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically
) {
Spacer(modifier = Modifier.width(8.dp))
IconButton(onClick = { expandedCtl = !expandedCtl }) {
Icon(
imageVector = if (expandedCtl) Icons.Default.MoreHoriz else Icons.Default.MoreVert,
contentDescription = "More",
tint = Color.White
)
})
}
}
}
}

View file

@ -0,0 +1,73 @@
package mg.dot.feufaro.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.VolumeDown
import androidx.compose.material.icons.automirrored.filled.VolumeOff
import androidx.compose.material.icons.automirrored.filled.VolumeUp
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalViewConfiguration
import androidx.compose.ui.unit.dp
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ModernVolumeSlider(
volume: Float,
onVolumeChange: (Float) -> Unit
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.height(42.dp)
.background(Color.White.copy(alpha = 0.1f), CircleShape)
.padding(horizontal = 12.dp, vertical = 4.dp)
) {
Icon(
imageVector = when {
volume == 0f -> Icons.AutoMirrored.Filled.VolumeOff
volume < 0.5f -> Icons.AutoMirrored.Filled.VolumeDown
else -> Icons.AutoMirrored.Filled.VolumeUp
},
contentDescription = null,
tint = if (volume > 0) Color.Black else Color.Gray,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(4.dp))
Slider(
value = volume,
onValueChange = onVolumeChange,
modifier = Modifier.fillMaxWidth(0.30f),
colors = SliderDefaults.colors(
activeTrackColor = Color(0xFFF59E0B),
inactiveTrackColor = Color.White.copy(alpha = 0.2f),
thumbColor = Color.Transparent
),
track = { sliderState ->
SliderDefaults.Track(
sliderState = sliderState,
modifier = Modifier.height(15.dp),
thumbTrackGapSize = 0.dp
)
},
thumb = {
Box(Modifier.size(0.dp))
}
)
}
}