Optimize midi control space & modernize volume slider
This commit is contained in:
parent
337f1d9912
commit
da1d130085
2 changed files with 177 additions and 121 deletions
|
|
@ -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()
|
||||
}
|
||||
|
|
@ -131,64 +135,48 @@ fun MidiControlPanel(
|
|||
.background(color = Color.Gray.copy(alpha = 0.5f), shape = RoundedCornerShape(size = 5.dp)),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Row (
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
AnimatedVisibility(
|
||||
visible = !expandedCtl
|
||||
) {
|
||||
Text("${currentPos.toInt() / 1000}s", color = Color.White)
|
||||
Slider(
|
||||
value = currentPos,
|
||||
onValueChange = onSeek,
|
||||
valueRange = 0f..(if (duration > 0) duration else 1f),
|
||||
modifier = Modifier.weight(1f),
|
||||
colors = SliderDefaults.colors(
|
||||
thumbColor = Color.Red,
|
||||
activeTrackColor = Color.Green,
|
||||
inactiveTrackColor = Color.Gray,
|
||||
inactiveTickColor = Color(0xffb0BEC5),
|
||||
disabledThumbColor = Color(0xff78909C),
|
||||
disabledActiveTickColor = Color(0xff757575),
|
||||
disabledActiveTrackColor = Color(0xffBDBDBD),
|
||||
disabledInactiveTickColor = Color(0xff616161),
|
||||
disabledInactiveTrackColor = Color(0xffBCAAA4),
|
||||
),
|
||||
thumb = {
|
||||
Box (
|
||||
modifier = Modifier
|
||||
.size(15.dp)
|
||||
.background(Color.Gray, CircleShape)
|
||||
)
|
||||
},
|
||||
track = { sliderState ->
|
||||
SliderDefaults.Track(
|
||||
sliderState = sliderState,
|
||||
modifier = Modifier.height(5.dp)
|
||||
)
|
||||
}
|
||||
)
|
||||
Text("${momo / 1000}s", color = Color.White)
|
||||
}
|
||||
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
){
|
||||
|
||||
|
||||
|
||||
|
||||
IconButton(
|
||||
onClick = onPlayPauseClick,
|
||||
modifier = Modifier.size(48.dp)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (isPause) Icons.Filled.PlayArrow else Icons.Filled.Pause,
|
||||
contentDescription = "Pla",
|
||||
tint = MaterialTheme.colorScheme.primary
|
||||
Text("${currentPos.toInt() / 1000}s", color = Color.White)
|
||||
Slider(
|
||||
value = currentPos,
|
||||
onValueChange = onSeek,
|
||||
valueRange = 0f..(if (duration > 0) duration else 1f),
|
||||
modifier = Modifier.weight(1f),
|
||||
colors = SliderDefaults.colors(
|
||||
thumbColor = Color.Red,
|
||||
activeTrackColor = Color.Green,
|
||||
inactiveTrackColor = Color.Gray,
|
||||
inactiveTickColor = Color(0xffb0BEC5),
|
||||
disabledThumbColor = Color(0xff78909C),
|
||||
disabledActiveTickColor = Color(0xff757575),
|
||||
disabledActiveTrackColor = Color(0xffBDBDBD),
|
||||
disabledInactiveTickColor = Color(0xff616161),
|
||||
disabledInactiveTrackColor = Color(0xffBCAAA4),
|
||||
),
|
||||
thumb = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(15.dp)
|
||||
.background(Color.Gray, CircleShape)
|
||||
)
|
||||
},
|
||||
track = { sliderState ->
|
||||
SliderDefaults.Track(
|
||||
sliderState = sliderState,
|
||||
modifier = Modifier.height(5.dp)
|
||||
)
|
||||
}
|
||||
)
|
||||
Text("${momo / 1000}s", color = Color.White)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
),
|
||||
shape = RoundedCornerShape(5.dp) ,
|
||||
modifier = Modifier.padding(2.dp)
|
||||
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 0.dp),
|
||||
shape = RoundedCornerShape(5.dp) ,
|
||||
modifier = Modifier
|
||||
.height(34.dp)
|
||||
.padding(horizontal = 4.dp)
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "A",
|
||||
|
|
@ -349,80 +356,56 @@ fun MidiControlPanel(
|
|||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 18.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
Icon(
|
||||
imageVector = if (volume > 0) Icons.AutoMirrored.Filled.VolumeUp else Icons.AutoMirrored.Filled.VolumeOff,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(20.dp)
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
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
|
||||
)
|
||||
}
|
||||
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)
|
||||
)
|
||||
},
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue