improve color picker: better landscape layout and survive orientation change

This commit is contained in:
Helium314 2025-02-27 19:35:07 +01:00
parent 1c955a34b2
commit b65d00e142
3 changed files with 91 additions and 70 deletions

View file

@ -301,8 +301,6 @@ sealed interface KeyData : AbstractKeyData {
// idea: directly create PopupKeySpec, but need to deal with needsToUpcase and popupKeysColumnAndFlags // idea: directly create PopupKeySpec, but need to deal with needsToUpcase and popupKeysColumnAndFlags
fun getPopupLabel(params: KeyboardParams): String { fun getPopupLabel(params: KeyboardParams): String {
val newLabel = processLabel(params) val newLabel = processLabel(params)
if (newLabel == "!")
Log.w("test", "code $code, newCode ${processCode()}")
if (code == KeyCode.UNSPECIFIED) { if (code == KeyCode.UNSPECIFIED) {
if (newLabel == label) return label if (newLabel == label) return label
val newCode = processCode() val newCode = processCode()

View file

@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
@ -15,22 +16,24 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Paint import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.PaintingStyle import androidx.compose.ui.graphics.PaintingStyle
import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.DialogProperties
import com.github.skydoves.colorpicker.compose.AlphaSlider import com.github.skydoves.colorpicker.compose.AlphaSlider
import com.github.skydoves.colorpicker.compose.BrightnessSlider import com.github.skydoves.colorpicker.compose.BrightnessSlider
import com.github.skydoves.colorpicker.compose.HsvColorPicker import com.github.skydoves.colorpicker.compose.HsvColorPicker
import com.github.skydoves.colorpicker.compose.rememberColorPickerController import com.github.skydoves.colorpicker.compose.rememberColorPickerController
// todo: needs different layout in landscape (bars on the side or something like that)
@Composable @Composable
fun ColorPickerDialog( fun ColorPickerDialog(
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
@ -50,12 +53,10 @@ fun ColorPickerDialog(
val initialString = initialColor.toUInt().toString(16) val initialString = initialColor.toUInt().toString(16)
var textValue by remember { mutableStateOf(TextFieldValue(initialString, TextRange(initialString.length))) } var textValue by remember { mutableStateOf(TextFieldValue(initialString, TextRange(initialString.length))) }
var currentColor by remember { mutableStateOf(Color(initialColor)) } var currentColor by remember { mutableStateOf(Color(initialColor)) }
ThreeButtonAlertDialog( val width = LocalConfiguration.current.screenWidthDp
onDismissRequest = onDismissRequest, val height = LocalConfiguration.current.screenHeightDp
onConfirmed = { onConfirmed(controller.selectedColor.value.toArgb()) }, val useWideLayout = height < 500 && width > height
title = { Text(title) }, @Composable fun topBar() {
content = {
Column {
Row { Row {
Surface( Surface(
color = Color(initialColor), color = Color(initialColor),
@ -70,10 +71,11 @@ fun ColorPickerDialog(
.height(barHeight)) .height(barHeight))
{ } { }
} }
}
@Composable fun picker() {
HsvColorPicker( HsvColorPicker(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .size(300.dp)
.height(300.dp)
.padding(10.dp), .padding(10.dp),
controller = controller, controller = controller,
onColorChanged = { onColorChanged = {
@ -83,6 +85,8 @@ fun ColorPickerDialog(
}, },
initialColor = Color(initialColor), initialColor = Color(initialColor),
) )
}
@Composable fun slidersAndTextField() {
AlphaSlider( AlphaSlider(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -103,17 +107,37 @@ fun ColorPickerDialog(
) )
TextField( TextField(
value = textValue, value = textValue,
// KeyboardType.Password is a crappy way of avoiding suggestions... is there really no way in compose? // todo: KeyboardType.Password is a crappy way of avoiding suggestions... is there really no way in compose?
keyboardOptions = KeyboardOptions(autoCorrectEnabled = false, keyboardType = KeyboardType.Password), keyboardOptions = KeyboardOptions(autoCorrectEnabled = false, keyboardType = KeyboardType.Password),
onValueChange = { onValueChange = {
textValue = it textValue = it
val androidColor = kotlin.runCatching { android.graphics.Color.parseColor("#${it.text}") }.getOrNull() val androidColor = runCatching { android.graphics.Color.parseColor("#${it.text}") }.getOrNull()
if (androidColor != null) if (androidColor != null)
controller.selectByColor(Color(androidColor), false) controller.selectByColor(Color(androidColor), false)
} }
) )
} }
ThreeButtonAlertDialog(
onDismissRequest = onDismissRequest,
onConfirmed = { onConfirmed(controller.selectedColor.value.toArgb()) },
title = { Text(title) },
content = {
if (useWideLayout)
Row(verticalAlignment = Alignment.CenterVertically) {
picker()
Column {
topBar()
slidersAndTextField()
} }
}
else
Column {
topBar()
picker()
slidersAndTextField()
}
},
properties = DialogProperties(usePlatformDefaultWidth = !useWideLayout)
) )
} }

View file

@ -31,7 +31,6 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@ -116,7 +115,8 @@ fun ColorsScreen(
else color ?: KeyboardTheme.determineUserColor(userColors, ctx, name, isNight) else color ?: KeyboardTheme.determineUserColor(userColors, ctx, name, isNight)
var newThemeName by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue(themeName)) } var newThemeName by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue(themeName)) }
var chosenColor: ColorSetting? by remember { mutableStateOf(null) } var chosenColorString: String by rememberSaveable { mutableStateOf("") }
val chosenColor = runCatching { Json.decodeFromString<ColorSetting?>(chosenColorString) }.getOrNull()
val saveLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) { val saveLauncher = rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult if (it.resultCode != Activity.RESULT_OK) return@rememberLauncherForActivityResult
val uri = it.data?.data ?: return@rememberLauncherForActivityResult val uri = it.data?.data ?: return@rememberLauncherForActivityResult
@ -174,7 +174,7 @@ fun ColorsScreen(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier modifier = Modifier
.padding(horizontal = 16.dp, vertical = 8.dp) .padding(horizontal = 16.dp, vertical = 8.dp)
.clickable { chosenColor = colorSetting } .clickable { chosenColorString = Json.encodeToString(colorSetting) }
) { ) {
Spacer( Spacer(
modifier = Modifier modifier = Modifier
@ -204,19 +204,18 @@ fun ColorsScreen(
} }
) )
if (chosenColor != null) { if (chosenColor != null) {
val color = chosenColor!!
ColorPickerDialog( ColorPickerDialog(
onDismissRequest = { chosenColor = null }, onDismissRequest = { chosenColorString = "" },
initialColor = color.displayColor(), initialColor = chosenColor.displayColor(),
title = color.displayName, title = chosenColor.displayName,
) { ) {
if (moreColors == 2) { if (moreColors == 2) {
val oldColors = KeyboardTheme.readUserAllColors(prefs, themeName) val oldColors = KeyboardTheme.readUserAllColors(prefs, themeName)
oldColors[ColorType.valueOf(color.name)] = it oldColors[ColorType.valueOf(chosenColor.name)] = it
KeyboardTheme.writeUserAllColors(prefs, themeName, oldColors) KeyboardTheme.writeUserAllColors(prefs, themeName, oldColors)
} else { } else {
val oldUserColors = KeyboardTheme.readUserColors(prefs, themeName) val oldUserColors = KeyboardTheme.readUserColors(prefs, themeName)
val newUserColors = (oldUserColors + ColorSetting(color.name, false, it)) val newUserColors = (oldUserColors + ColorSetting(chosenColor.name, false, it))
.reversed().distinctBy { it.displayName } .reversed().distinctBy { it.displayName }
KeyboardTheme.writeUserColors(prefs, themeName, newUserColors) KeyboardTheme.writeUserColors(prefs, themeName, newUserColors)
} }