mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Add options for keyboard height and bottom offset
This commit is contained in:
parent
0e1a338f0d
commit
937ece0b34
@ -213,8 +213,10 @@ public class KeyboardView extends View {
|
||||
public void setKeyboard(@Nonnull final Keyboard keyboard) {
|
||||
mKeyboard = keyboard;
|
||||
final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap;
|
||||
mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
|
||||
mKeyDrawParams.updateParams(keyHeight, keyboard.mKeyVisualAttributes);
|
||||
final int keyWidth = keyboard.mMostCommonKeyWidth;
|
||||
|
||||
mKeyDrawParams.updateParams(Math.min(keyWidth, keyHeight), mKeyVisualAttributes);
|
||||
mKeyDrawParams.updateParams(Math.min(keyWidth, keyHeight), keyboard.mKeyVisualAttributes);
|
||||
invalidateAllKeys();
|
||||
requestLayout();
|
||||
}
|
||||
@ -239,7 +241,8 @@ public class KeyboardView extends View {
|
||||
}
|
||||
|
||||
protected void updateKeyDrawParams(final int keyHeight) {
|
||||
mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
|
||||
final int keyWidth = mKeyboard.mMostCommonKeyWidth;
|
||||
mKeyDrawParams.updateParams(Math.min(keyWidth, keyHeight), mKeyVisualAttributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -354,7 +357,7 @@ public class KeyboardView extends View {
|
||||
canvas.translate(keyDrawX, keyDrawY);
|
||||
|
||||
final KeyVisualAttributes attr = key.getVisualAttributes();
|
||||
final KeyDrawParams params = mKeyDrawParams.mayCloneAndUpdateParams(key.getHeight(), attr);
|
||||
final KeyDrawParams params = mKeyDrawParams.mayCloneAndUpdateParams(Math.min(key.getHeight(), key.getWidth()), attr);
|
||||
params.mAnimAlpha = Constants.Color.ALPHA_OPAQUE;
|
||||
|
||||
if (!key.isSpacer()) {
|
||||
|
@ -255,14 +255,18 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
|
||||
final TypedArray keyAttr = mResources.obtainAttributes(attr, R.styleable.Keyboard_Key);
|
||||
try {
|
||||
final KeyboardParams params = mParams;
|
||||
final int height = params.mId.mHeight;
|
||||
|
||||
final int offset = (int)mProvider.getKeyboardBottomOffset();
|
||||
final int height = (int) (params.mId.mHeight * mProvider.getKeyboardHeightMultiplier() + offset);
|
||||
final int width = params.mId.mWidth;
|
||||
params.mOccupiedHeight = height;
|
||||
params.mOccupiedWidth = width;
|
||||
params.mTopPadding = (int)keyboardAttr.getFraction(
|
||||
R.styleable.Keyboard_keyboardTopPadding, height, height, 0);
|
||||
params.mBottomPadding = (int)keyboardAttr.getFraction(
|
||||
R.styleable.Keyboard_keyboardBottomPadding, height, height, 0);
|
||||
params.mBottomPadding = (int)(keyboardAttr.getFraction(
|
||||
R.styleable.Keyboard_keyboardBottomPadding, height, height, 0)
|
||||
+ mProvider.getKeyboardBottomOffset()
|
||||
);
|
||||
params.mLeftPadding = (int)keyboardAttr.getFraction(
|
||||
R.styleable.Keyboard_keyboardLeftPadding, width, width, 0);
|
||||
params.mRightPadding = (int)keyboardAttr.getFraction(
|
||||
@ -279,7 +283,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
|
||||
// rows are determined based on the entire keyboard height including top and bottom
|
||||
// paddings.
|
||||
params.mVerticalGap = (int)keyboardAttr.getFraction(
|
||||
R.styleable.Keyboard_verticalGap, height, height, 0);
|
||||
R.styleable.Keyboard_verticalGap, height - offset, height - offset, 0);
|
||||
final int baseHeight = params.mOccupiedHeight - params.mTopPadding
|
||||
- params.mBottomPadding + params.mVerticalGap;
|
||||
params.mBaseHeight = baseHeight;
|
||||
|
@ -257,11 +257,7 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save
|
||||
dataStore.data.collect {
|
||||
drawableProvider?.let { provider ->
|
||||
if(provider is BasicThemeProvider) {
|
||||
if ((it[HiddenKeysSetting] ?: provider.expertMode) != provider.expertMode
|
||||
|| (it[KeyBordersSetting] ?: provider.keyBorders) != provider.keyBorders
|
||||
|| (it[KeyHintsSetting] ?: provider.showKeyHints) != provider.showKeyHints
|
||||
) {
|
||||
Log.w("LatinIME", "One of HiddenKeysSetting, KeyBordersSetting or KeyHintsSetting has changed")
|
||||
if (provider.hasUpdated(it)) {
|
||||
activeThemeOption?.obtainColors?.let { f ->
|
||||
updateDrawableProvider(f(this@LatinIME))
|
||||
if (!uixManager.isMainKeyboardHidden) {
|
||||
|
@ -18,15 +18,20 @@ import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import androidx.datastore.preferences.core.floatPreferencesKey
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import org.futo.inputmethod.latin.R
|
||||
import org.futo.inputmethod.latin.uix.theme.DarkColorScheme
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
val KeyBordersSetting = booleanPreferencesKey("keyBorders")
|
||||
val HiddenKeysSetting = booleanPreferencesKey("hiddenKeys")
|
||||
val KeyHintsSetting = booleanPreferencesKey("keyHints")
|
||||
val KeyBordersSetting = SettingsKey(booleanPreferencesKey("keyBorders"), true)
|
||||
val HiddenKeysSetting = SettingsKey(booleanPreferencesKey("hiddenKeys"), false)
|
||||
val KeyHintsSetting = SettingsKey(booleanPreferencesKey("keyHints"), false)
|
||||
|
||||
val KeyboardHeightMultiplierSetting = SettingsKey(floatPreferencesKey("keyboardHeightMultiplier"), 1.0f)
|
||||
val KeyboardBottomOffsetSetting = SettingsKey(floatPreferencesKey("keyboardOffset"), 0.0f)
|
||||
|
||||
fun adjustColorBrightnessForContrast(bgColor: Int, fgColor: Int, desiredContrast: Float, adjustSaturation: Boolean = false): Int {
|
||||
// Convert RGB colors to HSL
|
||||
@ -76,6 +81,14 @@ class BasicThemeProvider(val context: Context, val overrideColorScheme: ColorSch
|
||||
return drawables[i]
|
||||
}
|
||||
|
||||
override fun getKeyboardHeightMultiplier(): Float {
|
||||
return keyboardHeight
|
||||
}
|
||||
|
||||
override fun getKeyboardBottomOffset(): Float {
|
||||
return dp(keyboardBottomOffsetValue.dp)
|
||||
}
|
||||
|
||||
private fun dp(dp: Dp): Float {
|
||||
return TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
@ -122,6 +135,22 @@ class BasicThemeProvider(val context: Context, val overrideColorScheme: ColorSch
|
||||
val keyBorders: Boolean
|
||||
val showKeyHints: Boolean
|
||||
|
||||
val keyboardHeight: Float
|
||||
val keyboardBottomOffsetValue: Float
|
||||
|
||||
fun hasUpdated(newPreferences: Preferences): Boolean {
|
||||
return when {
|
||||
newPreferences[HiddenKeysSetting.key] != expertMode -> true
|
||||
newPreferences[KeyBordersSetting.key] != keyBorders -> true
|
||||
newPreferences[KeyHintsSetting.key] != showKeyHints -> true
|
||||
|
||||
newPreferences[KeyboardHeightMultiplierSetting.key] != keyboardHeight -> true
|
||||
newPreferences[KeyboardBottomOffsetSetting.key] != keyboardBottomOffsetValue -> true
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
val colorScheme = if(overrideColorScheme != null) {
|
||||
overrideColorScheme
|
||||
@ -133,9 +162,12 @@ class BasicThemeProvider(val context: Context, val overrideColorScheme: ColorSch
|
||||
dynamicLightColorScheme(dCtx)
|
||||
}
|
||||
|
||||
expertMode = context.getSettingBlocking(HiddenKeysSetting, false)
|
||||
keyBorders = context.getSettingBlocking(KeyBordersSetting, false)
|
||||
showKeyHints = context.getSettingBlocking(KeyHintsSetting, false)
|
||||
expertMode = context.getSettingBlocking(HiddenKeysSetting)
|
||||
keyBorders = context.getSettingBlocking(KeyBordersSetting)
|
||||
showKeyHints = context.getSettingBlocking(KeyHintsSetting)
|
||||
|
||||
keyboardHeight = context.getSettingBlocking(KeyboardHeightMultiplierSetting.key, KeyboardHeightMultiplierSetting.default)
|
||||
keyboardBottomOffsetValue = context.getSettingBlocking(KeyboardBottomOffsetSetting.key, KeyboardBottomOffsetSetting.default)
|
||||
|
||||
val primary = colorScheme.primary.toArgb()
|
||||
val secondary = colorScheme.secondary.toArgb()
|
||||
|
@ -22,6 +22,9 @@ interface DynamicThemeProvider {
|
||||
|
||||
fun getDrawable(i: Int): Drawable?
|
||||
|
||||
fun getKeyboardHeightMultiplier(): Float
|
||||
fun getKeyboardBottomOffset(): Float
|
||||
|
||||
companion object {
|
||||
@ColorInt
|
||||
fun getColorOrDefault(i: Int, @ColorInt default: Int, keyAttr: TypedArray, provider: DynamicThemeProvider?): Int {
|
||||
|
@ -49,6 +49,10 @@ fun <T> Context.getSettingBlocking(key: Preferences.Key<T>, default: T): T {
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> Context.getSettingBlocking(key: SettingsKey<T>): T {
|
||||
return getSettingBlocking(key.key, key.default)
|
||||
}
|
||||
|
||||
fun <T> Context.setSettingBlocking(key: Preferences.Key<T>, value: T) {
|
||||
val context = this
|
||||
runBlocking {
|
||||
|
@ -304,71 +304,73 @@ fun<T: Number> SettingSlider(
|
||||
if(isTextFieldVisible) focusRequester.requestFocus()
|
||||
}
|
||||
|
||||
ScreenTitle(title, showBack = false)
|
||||
if(subtitle != null) {
|
||||
Text(subtitle, style = Typography.bodyMedium, modifier = Modifier.padding(12.dp, 0.dp))
|
||||
}
|
||||
Row(modifier = Modifier.padding(16.dp, 0.dp)) {
|
||||
if (isTextFieldVisible) {
|
||||
val apply = {
|
||||
if(isTextFieldVisible) {
|
||||
val number = textFieldValue.text.trim().toFloatOrNull()
|
||||
val newValue = if (number != null) {
|
||||
transform(number.coerceIn(hardRange))
|
||||
} else {
|
||||
setting.default
|
||||
Column {
|
||||
ScreenTitle(title, showBack = false)
|
||||
if(subtitle != null) {
|
||||
Text(subtitle, style = Typography.bodyMedium, modifier = Modifier.padding(12.dp, 0.dp))
|
||||
}
|
||||
Row(modifier = Modifier.padding(16.dp, 0.dp)) {
|
||||
if (isTextFieldVisible) {
|
||||
val apply = {
|
||||
if(isTextFieldVisible) {
|
||||
val number = textFieldValue.text.trim().toFloatOrNull()
|
||||
val newValue = if (number != null) {
|
||||
transform(number.coerceIn(hardRange))
|
||||
} else {
|
||||
setting.default
|
||||
}
|
||||
|
||||
setValue(newValue)
|
||||
virtualValue = newValue.toFloat().pow(1.0f / power)
|
||||
|
||||
isTextFieldVisible = false
|
||||
textFieldValue = TextFieldValue()
|
||||
}
|
||||
|
||||
setValue(newValue)
|
||||
virtualValue = newValue.toFloat().pow(1.0f / power)
|
||||
|
||||
isTextFieldVisible = false
|
||||
textFieldValue = TextFieldValue()
|
||||
}
|
||||
}
|
||||
BasicTextField(
|
||||
value = textFieldValue,
|
||||
onValueChange = { textFieldValue = it },
|
||||
modifier = Modifier
|
||||
.weight(0.33f)
|
||||
.align(Alignment.CenterVertically)
|
||||
.focusRequester(focusRequester)
|
||||
.onFocusChanged {
|
||||
if(it.isFocused) hasTextFieldFocusedYet = true
|
||||
else if(!it.isFocused && hasTextFieldFocusedYet) apply()
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = {
|
||||
apply()
|
||||
}
|
||||
),
|
||||
singleLine = true,
|
||||
textStyle = Typography.labelMedium
|
||||
)
|
||||
BasicTextField(
|
||||
value = textFieldValue,
|
||||
onValueChange = { textFieldValue = it },
|
||||
modifier = Modifier
|
||||
.weight(0.33f)
|
||||
.align(Alignment.CenterVertically)
|
||||
.focusRequester(focusRequester)
|
||||
.onFocusChanged {
|
||||
if (it.isFocused) hasTextFieldFocusedYet = true
|
||||
else if (!it.isFocused && hasTextFieldFocusedYet) apply()
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = {
|
||||
apply()
|
||||
}
|
||||
),
|
||||
singleLine = true,
|
||||
textStyle = Typography.labelMedium
|
||||
)
|
||||
|
||||
} else {
|
||||
Text(
|
||||
text = indicator(value),
|
||||
modifier = Modifier
|
||||
.weight(0.33f)
|
||||
.align(Alignment.CenterVertically)
|
||||
.clickable {
|
||||
hasTextFieldFocusedYet = false
|
||||
isTextFieldVisible = true
|
||||
},
|
||||
style = Typography.labelMedium
|
||||
} else {
|
||||
Text(
|
||||
text = indicator(value),
|
||||
modifier = Modifier
|
||||
.weight(0.33f)
|
||||
.align(Alignment.CenterVertically)
|
||||
.clickable {
|
||||
hasTextFieldFocusedYet = false
|
||||
isTextFieldVisible = true
|
||||
},
|
||||
style = Typography.labelMedium
|
||||
)
|
||||
}
|
||||
Slider(
|
||||
value = virtualValue,
|
||||
onValueChange = {
|
||||
virtualValue = it
|
||||
setValue(transform(it.pow(power))) },
|
||||
valueRange = range.start.pow(1.0f / power) .. range.endInclusive.pow(1.0f / power),
|
||||
enabled = !isTextFieldVisible,
|
||||
modifier = Modifier.weight(1.0f)
|
||||
)
|
||||
}
|
||||
Slider(
|
||||
value = virtualValue,
|
||||
onValueChange = {
|
||||
virtualValue = it
|
||||
setValue(transform(it.pow(power))) },
|
||||
valueRange = range.start.pow(1.0f / power) .. range.endInclusive.pow(1.0f / power),
|
||||
enabled = !isTextFieldVisible,
|
||||
modifier = Modifier.weight(1.0f)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ fun DeveloperScreen(navController: NavHostController = rememberNavController())
|
||||
SettingToggleDataStore(
|
||||
title = "Touch typing mode",
|
||||
subtitle = "Hides all keys. Touch typists only! Recommended to disable emoji key and enable key borders",
|
||||
setting = SettingsKey(HiddenKeysSetting, false)
|
||||
setting = HiddenKeysSetting
|
||||
)
|
||||
|
||||
NavigationItem(
|
||||
|
@ -33,11 +33,12 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.futo.inputmethod.latin.uix.HiddenKeysSetting
|
||||
import org.futo.inputmethod.latin.uix.KeyBordersSetting
|
||||
import org.futo.inputmethod.latin.uix.KeyHintsSetting
|
||||
import org.futo.inputmethod.latin.uix.SettingsKey
|
||||
import org.futo.inputmethod.latin.uix.KeyboardBottomOffsetSetting
|
||||
import org.futo.inputmethod.latin.uix.KeyboardHeightMultiplierSetting
|
||||
import org.futo.inputmethod.latin.uix.THEME_KEY
|
||||
import org.futo.inputmethod.latin.uix.settings.SettingSlider
|
||||
import org.futo.inputmethod.latin.uix.settings.SettingToggleDataStore
|
||||
import org.futo.inputmethod.latin.uix.settings.useDataStore
|
||||
import org.futo.inputmethod.latin.uix.theme.ThemeOption
|
||||
@ -48,6 +49,7 @@ import org.futo.inputmethod.latin.uix.theme.UixThemeWrapper
|
||||
import org.futo.inputmethod.latin.uix.theme.presets.AMOLEDDarkPurple
|
||||
import org.futo.inputmethod.latin.uix.theme.presets.ClassicMaterialDark
|
||||
import org.futo.inputmethod.latin.uix.theme.presets.VoiceInputTheme
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
// TODO: For Dynamic System we need to show the user that it switches between light/dark
|
||||
@Composable
|
||||
@ -185,18 +187,6 @@ fun ThemePicker(onSelected: (ThemeOption) -> Unit) {
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
columns = GridCells.Adaptive(minSize = 172.dp)
|
||||
) {
|
||||
item(span = { GridItemSpan(maxCurrentLineSpan) }) {
|
||||
SettingToggleDataStore(
|
||||
title = "Key borders",
|
||||
setting = SettingsKey(KeyBordersSetting, false)
|
||||
)
|
||||
}
|
||||
item(span = { GridItemSpan(maxCurrentLineSpan) }) {
|
||||
SettingToggleDataStore(
|
||||
title = "Show symbol hints",
|
||||
setting = SettingsKey(KeyHintsSetting, false)
|
||||
)
|
||||
}
|
||||
items(availableThemeOptions.count()) {
|
||||
val themeOption = availableThemeOptions[it].second
|
||||
|
||||
@ -216,6 +206,38 @@ fun ThemePicker(onSelected: (ThemeOption) -> Unit) {
|
||||
toast.show()
|
||||
}
|
||||
}
|
||||
|
||||
item(span = { GridItemSpan(maxCurrentLineSpan) }) { }
|
||||
|
||||
item(span = { GridItemSpan(maxCurrentLineSpan) }) {
|
||||
SettingToggleDataStore(
|
||||
title = "Key borders",
|
||||
setting = KeyBordersSetting
|
||||
)
|
||||
}
|
||||
item(span = { GridItemSpan(maxCurrentLineSpan) }) {
|
||||
SettingToggleDataStore(
|
||||
title = "Show symbol hints",
|
||||
setting = KeyHintsSetting
|
||||
)
|
||||
}
|
||||
|
||||
item(span = { GridItemSpan(maxCurrentLineSpan) }) {
|
||||
SettingSlider(
|
||||
title = "Keyboard Height",
|
||||
setting = KeyboardHeightMultiplierSetting,
|
||||
range = 0.1f .. 2.0f, transform = { it },
|
||||
indicator = { "${(it * 100.0f).roundToInt()}%" }
|
||||
)
|
||||
}
|
||||
item(span = { GridItemSpan(maxCurrentLineSpan) }) {
|
||||
SettingSlider(
|
||||
title = "Keyboard Offset",
|
||||
setting = KeyboardBottomOffsetSetting,
|
||||
range = 0.0f .. 128.0f, transform = { it },
|
||||
indicator = { "${String.format("%.1f", it)} dp" }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user