mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-04-24 08:36:26 +00:00
allow customizing all colors, fixes #529
This commit is contained in:
parent
eada9bc51c
commit
77f03b0756
8 changed files with 158 additions and 65 deletions
|
@ -133,7 +133,6 @@ __Planned features and improvements:__
|
||||||
* Additional and customizable key swipe functionality
|
* Additional and customizable key swipe functionality
|
||||||
* Some functionality will not be possible when using glide typing
|
* Some functionality will not be possible when using glide typing
|
||||||
* Ability to enter all emojis independent of Android version (optional, #297)
|
* Ability to enter all emojis independent of Android version (optional, #297)
|
||||||
* (limited) support for customizing _all_ internally used colors
|
|
||||||
* Add and enable emoji dictionaries by default (if available for language)
|
* Add and enable emoji dictionaries by default (if available for language)
|
||||||
* Clearer / more intuitive arrangement of settings
|
* Clearer / more intuitive arrangement of settings
|
||||||
* Maybe hide some less used settings by default (similar to color customization)
|
* Maybe hide some less used settings by default (similar to color customization)
|
||||||
|
|
|
@ -12,9 +12,11 @@ import android.os.Build
|
||||||
import android.os.Build.VERSION_CODES
|
import android.os.Build.VERSION_CODES
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import helium314.keyboard.latin.R
|
import helium314.keyboard.latin.R
|
||||||
|
import helium314.keyboard.latin.common.AllColors
|
||||||
import helium314.keyboard.latin.common.Colors
|
import helium314.keyboard.latin.common.Colors
|
||||||
import helium314.keyboard.latin.common.DefaultColors
|
import helium314.keyboard.latin.common.DefaultColors
|
||||||
import helium314.keyboard.latin.common.DynamicColors
|
import helium314.keyboard.latin.common.DynamicColors
|
||||||
|
import helium314.keyboard.latin.common.readAllColorsMap
|
||||||
import helium314.keyboard.latin.settings.Settings
|
import helium314.keyboard.latin.settings.Settings
|
||||||
import helium314.keyboard.latin.utils.DeviceProtectedUtils
|
import helium314.keyboard.latin.utils.DeviceProtectedUtils
|
||||||
import helium314.keyboard.latin.utils.ResourceUtils
|
import helium314.keyboard.latin.utils.ResourceUtils
|
||||||
|
@ -101,10 +103,11 @@ private constructor(val themeId: Int, @JvmField val mStyleId: Int) {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getThemeColors(themeColors: String, themeStyle: String, context: Context, prefs: SharedPreferences): Colors {
|
fun getThemeColors(themeColors: String, themeStyle: String, context: Context, prefs: SharedPreferences): Colors {
|
||||||
val hasBorders = prefs.getBoolean(Settings.PREF_THEME_KEY_BORDERS, false)
|
val hasBorders = prefs.getBoolean(Settings.PREF_THEME_KEY_BORDERS, false)
|
||||||
val useNightImage = Settings.readDayNightPref(prefs, context.resources) && ResourceUtils.isNight(context.resources)
|
val useNightMode = Settings.readDayNightPref(prefs, context.resources) && ResourceUtils.isNight(context.resources)
|
||||||
val backgroundImage = Settings.readUserBackgroundImage(context, useNightImage)
|
val backgroundImage = Settings.readUserBackgroundImage(context, useNightMode)
|
||||||
return when (themeColors) {
|
return when (themeColors) {
|
||||||
THEME_USER -> DefaultColors(
|
THEME_USER -> if (prefs.getInt(Settings.PREF_SHOW_MORE_COLORS, 0) == 2) AllColors(readAllColorsMap(prefs, false), themeStyle, hasBorders, backgroundImage)
|
||||||
|
else DefaultColors(
|
||||||
themeStyle,
|
themeStyle,
|
||||||
hasBorders,
|
hasBorders,
|
||||||
Settings.readUserColor(prefs, context, Settings.PREF_COLOR_ACCENT_SUFFIX, false),
|
Settings.readUserColor(prefs, context, Settings.PREF_COLOR_ACCENT_SUFFIX, false),
|
||||||
|
@ -119,7 +122,8 @@ private constructor(val themeId: Int, @JvmField val mStyleId: Int) {
|
||||||
Settings.readUserColor(prefs, context, Settings.PREF_COLOR_GESTURE_SUFFIX, false),
|
Settings.readUserColor(prefs, context, Settings.PREF_COLOR_GESTURE_SUFFIX, false),
|
||||||
keyboardBackground = backgroundImage
|
keyboardBackground = backgroundImage
|
||||||
)
|
)
|
||||||
THEME_USER_NIGHT -> DefaultColors(
|
THEME_USER_NIGHT -> if (prefs.getInt(Settings.PREF_SHOW_MORE_COLORS, 0) == 2) AllColors(readAllColorsMap(prefs, true), themeStyle, hasBorders, backgroundImage)
|
||||||
|
else DefaultColors(
|
||||||
themeStyle,
|
themeStyle,
|
||||||
hasBorders,
|
hasBorders,
|
||||||
Settings.readUserColor(prefs, context, Settings.PREF_COLOR_ACCENT_SUFFIX, true),
|
Settings.readUserColor(prefs, context, Settings.PREF_COLOR_ACCENT_SUFFIX, true),
|
||||||
|
|
|
@ -27,7 +27,6 @@ import android.view.View;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import helium314.keyboard.keyboard.emoji.EmojiPageKeyboardView;
|
|
||||||
import helium314.keyboard.keyboard.internal.KeyDrawParams;
|
import helium314.keyboard.keyboard.internal.KeyDrawParams;
|
||||||
import helium314.keyboard.keyboard.internal.KeyVisualAttributes;
|
import helium314.keyboard.keyboard.internal.KeyVisualAttributes;
|
||||||
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode;
|
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode;
|
||||||
|
@ -107,8 +106,8 @@ public class KeyboardView extends View {
|
||||||
|
|
||||||
final TypedArray keyboardViewAttr = context.obtainStyledAttributes(attrs,
|
final TypedArray keyboardViewAttr = context.obtainStyledAttributes(attrs,
|
||||||
R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
|
R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
|
||||||
if (this instanceof EmojiPageKeyboardView || this instanceof PopupSuggestionsView)
|
if (this instanceof PopupSuggestionsView)
|
||||||
mKeyBackground = mColors.selectAndColorDrawable(keyboardViewAttr, ColorType.BACKGROUND);
|
mKeyBackground = mColors.selectAndColorDrawable(keyboardViewAttr, ColorType.MORE_SUGGESTIONS_WORD_BACKGROUND);
|
||||||
else if (this instanceof PopupKeysKeyboardView)
|
else if (this instanceof PopupKeysKeyboardView)
|
||||||
mKeyBackground = mColors.selectAndColorDrawable(keyboardViewAttr, ColorType.POPUP_KEYS_BACKGROUND);
|
mKeyBackground = mColors.selectAndColorDrawable(keyboardViewAttr, ColorType.POPUP_KEYS_BACKGROUND);
|
||||||
else
|
else
|
||||||
|
|
|
@ -29,6 +29,7 @@ import helium314.keyboard.keyboard.KeyboardTheme.Companion.STYLE_HOLO
|
||||||
import helium314.keyboard.keyboard.KeyboardTheme.Companion.STYLE_MATERIAL
|
import helium314.keyboard.keyboard.KeyboardTheme.Companion.STYLE_MATERIAL
|
||||||
import helium314.keyboard.latin.common.ColorType.*
|
import helium314.keyboard.latin.common.ColorType.*
|
||||||
import helium314.keyboard.latin.R
|
import helium314.keyboard.latin.R
|
||||||
|
import helium314.keyboard.latin.settings.Settings
|
||||||
import helium314.keyboard.latin.utils.adjustLuminosityAndKeepAlpha
|
import helium314.keyboard.latin.utils.adjustLuminosityAndKeepAlpha
|
||||||
import helium314.keyboard.latin.utils.brighten
|
import helium314.keyboard.latin.utils.brighten
|
||||||
import helium314.keyboard.latin.utils.brightenOrDarken
|
import helium314.keyboard.latin.utils.brightenOrDarken
|
||||||
|
@ -63,7 +64,7 @@ interface Colors {
|
||||||
/** returns a colored drawable selected from [attr], which must contain using R.styleable.KeyboardView_* */
|
/** returns a colored drawable selected from [attr], which must contain using R.styleable.KeyboardView_* */
|
||||||
fun selectAndColorDrawable(attr: TypedArray, color: ColorType): Drawable {
|
fun selectAndColorDrawable(attr: TypedArray, color: ColorType): Drawable {
|
||||||
val drawable = when (color) {
|
val drawable = when (color) {
|
||||||
KEY_BACKGROUND, BACKGROUND, ACTION_KEY_POPUP_KEYS_BACKGROUND, POPUP_KEYS_BACKGROUND ->
|
KEY_BACKGROUND, MORE_SUGGESTIONS_WORD_BACKGROUND, ACTION_KEY_POPUP_KEYS_BACKGROUND, POPUP_KEYS_BACKGROUND ->
|
||||||
attr.getDrawable(R.styleable.KeyboardView_keyBackground)
|
attr.getDrawable(R.styleable.KeyboardView_keyBackground)
|
||||||
FUNCTIONAL_KEY_BACKGROUND -> attr.getDrawable(R.styleable.KeyboardView_functionalKeyBackground)
|
FUNCTIONAL_KEY_BACKGROUND -> attr.getDrawable(R.styleable.KeyboardView_functionalKeyBackground)
|
||||||
SPACE_BAR_BACKGROUND -> {
|
SPACE_BAR_BACKGROUND -> {
|
||||||
|
@ -281,7 +282,7 @@ class DynamicColors(context: Context, override val themeStyle: String, override
|
||||||
SPACE_BAR_TEXT -> spaceBarText
|
SPACE_BAR_TEXT -> spaceBarText
|
||||||
FUNCTIONAL_KEY_BACKGROUND -> functionalKey
|
FUNCTIONAL_KEY_BACKGROUND -> functionalKey
|
||||||
SPACE_BAR_BACKGROUND -> spaceBar
|
SPACE_BAR_BACKGROUND -> spaceBar
|
||||||
BACKGROUND, MAIN_BACKGROUND -> background
|
MORE_SUGGESTIONS_WORD_BACKGROUND, MAIN_BACKGROUND -> background
|
||||||
KEY_BACKGROUND -> keyBackground
|
KEY_BACKGROUND -> keyBackground
|
||||||
ACTION_KEY_POPUP_KEYS_BACKGROUND -> if (themeStyle == STYLE_HOLO) adjustedBackground else accent
|
ACTION_KEY_POPUP_KEYS_BACKGROUND -> if (themeStyle == STYLE_HOLO) adjustedBackground else accent
|
||||||
STRIP_BACKGROUND -> if (!hasKeyBorders && themeStyle == STYLE_MATERIAL) adjustedBackground else background
|
STRIP_BACKGROUND -> if (!hasKeyBorders && themeStyle == STYLE_MATERIAL) adjustedBackground else background
|
||||||
|
@ -292,7 +293,7 @@ class DynamicColors(context: Context, override val themeStyle: String, override
|
||||||
|
|
||||||
override fun setColor(drawable: Drawable, color: ColorType) {
|
override fun setColor(drawable: Drawable, color: ColorType) {
|
||||||
val colorStateList = when (color) {
|
val colorStateList = when (color) {
|
||||||
BACKGROUND -> backgroundStateList
|
MORE_SUGGESTIONS_WORD_BACKGROUND -> backgroundStateList
|
||||||
KEY_BACKGROUND -> keyStateList
|
KEY_BACKGROUND -> keyStateList
|
||||||
FUNCTIONAL_KEY_BACKGROUND -> functionalKeyStateList
|
FUNCTIONAL_KEY_BACKGROUND -> functionalKeyStateList
|
||||||
ACTION_KEY_BACKGROUND -> actionKeyStateList
|
ACTION_KEY_BACKGROUND -> actionKeyStateList
|
||||||
|
@ -334,8 +335,8 @@ class DynamicColors(context: Context, override val themeStyle: String, override
|
||||||
view.setBackgroundColor(Color.WHITE) // set white to make the color filters work
|
view.setBackgroundColor(Color.WHITE) // set white to make the color filters work
|
||||||
when (color) {
|
when (color) {
|
||||||
KEY_PREVIEW -> view.background.colorFilter = adjustedBackgroundFilter
|
KEY_PREVIEW -> view.background.colorFilter = adjustedBackgroundFilter
|
||||||
FUNCTIONAL_KEY_BACKGROUND, KEY_BACKGROUND, BACKGROUND, SPACE_BAR_BACKGROUND, STRIP_BACKGROUND -> setColor(view.background, color)
|
FUNCTIONAL_KEY_BACKGROUND, KEY_BACKGROUND, MORE_SUGGESTIONS_WORD_BACKGROUND, SPACE_BAR_BACKGROUND, STRIP_BACKGROUND -> setColor(view.background, color)
|
||||||
ONE_HANDED_MODE_BUTTON -> setColor(view.background, if (keyboardBackground == null) BACKGROUND else STRIP_BACKGROUND)
|
ONE_HANDED_MODE_BUTTON -> setColor(view.background, if (keyboardBackground == null) MAIN_BACKGROUND else STRIP_BACKGROUND)
|
||||||
MORE_SUGGESTIONS_BACKGROUND -> view.background.colorFilter = backgroundFilter
|
MORE_SUGGESTIONS_BACKGROUND -> view.background.colorFilter = backgroundFilter
|
||||||
POPUP_KEYS_BACKGROUND ->
|
POPUP_KEYS_BACKGROUND ->
|
||||||
if (themeStyle != STYLE_HOLO)
|
if (themeStyle != STYLE_HOLO)
|
||||||
|
@ -473,7 +474,7 @@ class DefaultColors (
|
||||||
SPACE_BAR_TEXT -> spaceBarText
|
SPACE_BAR_TEXT -> spaceBarText
|
||||||
FUNCTIONAL_KEY_BACKGROUND -> functionalKey
|
FUNCTIONAL_KEY_BACKGROUND -> functionalKey
|
||||||
SPACE_BAR_BACKGROUND -> spaceBar
|
SPACE_BAR_BACKGROUND -> spaceBar
|
||||||
BACKGROUND, MAIN_BACKGROUND -> background
|
MORE_SUGGESTIONS_WORD_BACKGROUND, MAIN_BACKGROUND -> background
|
||||||
KEY_BACKGROUND -> keyBackground
|
KEY_BACKGROUND -> keyBackground
|
||||||
ACTION_KEY_POPUP_KEYS_BACKGROUND -> if (themeStyle == STYLE_HOLO) adjustedBackground else accent
|
ACTION_KEY_POPUP_KEYS_BACKGROUND -> if (themeStyle == STYLE_HOLO) adjustedBackground else accent
|
||||||
STRIP_BACKGROUND -> if (!hasKeyBorders && themeStyle == STYLE_MATERIAL) adjustedBackground else background
|
STRIP_BACKGROUND -> if (!hasKeyBorders && themeStyle == STYLE_MATERIAL) adjustedBackground else background
|
||||||
|
@ -485,7 +486,7 @@ class DefaultColors (
|
||||||
|
|
||||||
override fun setColor(drawable: Drawable, color: ColorType) {
|
override fun setColor(drawable: Drawable, color: ColorType) {
|
||||||
val colorStateList = when (color) {
|
val colorStateList = when (color) {
|
||||||
BACKGROUND -> backgroundStateList
|
MORE_SUGGESTIONS_WORD_BACKGROUND -> backgroundStateList
|
||||||
KEY_BACKGROUND -> keyStateList
|
KEY_BACKGROUND -> keyStateList
|
||||||
FUNCTIONAL_KEY_BACKGROUND -> functionalKeyStateList
|
FUNCTIONAL_KEY_BACKGROUND -> functionalKeyStateList
|
||||||
ACTION_KEY_BACKGROUND -> actionKeyStateList
|
ACTION_KEY_BACKGROUND -> actionKeyStateList
|
||||||
|
@ -518,8 +519,8 @@ class DefaultColors (
|
||||||
view.setBackgroundColor(Color.WHITE) // set white to make the color filters work
|
view.setBackgroundColor(Color.WHITE) // set white to make the color filters work
|
||||||
when (color) {
|
when (color) {
|
||||||
KEY_PREVIEW, POPUP_KEYS_BACKGROUND -> view.background.colorFilter = adjustedBackgroundFilter
|
KEY_PREVIEW, POPUP_KEYS_BACKGROUND -> view.background.colorFilter = adjustedBackgroundFilter
|
||||||
FUNCTIONAL_KEY_BACKGROUND, KEY_BACKGROUND, BACKGROUND, SPACE_BAR_BACKGROUND, STRIP_BACKGROUND -> setColor(view.background, color)
|
FUNCTIONAL_KEY_BACKGROUND, KEY_BACKGROUND, MORE_SUGGESTIONS_WORD_BACKGROUND, SPACE_BAR_BACKGROUND, STRIP_BACKGROUND -> setColor(view.background, color)
|
||||||
ONE_HANDED_MODE_BUTTON -> setColor(view.background, if (keyboardBackground == null) BACKGROUND else STRIP_BACKGROUND)
|
ONE_HANDED_MODE_BUTTON -> setColor(view.background, if (keyboardBackground == null) MAIN_BACKGROUND else STRIP_BACKGROUND)
|
||||||
MORE_SUGGESTIONS_BACKGROUND -> view.background.colorFilter = backgroundFilter
|
MORE_SUGGESTIONS_BACKGROUND -> view.background.colorFilter = backgroundFilter
|
||||||
MAIN_BACKGROUND -> {
|
MAIN_BACKGROUND -> {
|
||||||
if (keyboardBackground != null) {
|
if (keyboardBackground != null) {
|
||||||
|
@ -546,17 +547,12 @@ class DefaultColors (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: allow users to use this class
|
class AllColors(private val colorMap: EnumMap<ColorType, Int>, override val themeStyle: String, override val hasKeyBorders: Boolean, backgroundImage: Drawable?) : Colors {
|
||||||
// the colorMap should be stored in settings
|
private var keyboardBackground: Drawable? = backgroundImage
|
||||||
// settings read and write untested
|
|
||||||
// color settings should add another menu option for "all colors"
|
|
||||||
// just show all ColorTypes with current value read from the map (default to black, same as in get)
|
|
||||||
// no string name, as it is not stable
|
|
||||||
class AllColors(private val colorMap: EnumMap<ColorType, Int>, override val themeStyle: String, override val hasKeyBorders: Boolean) : Colors {
|
|
||||||
private var keyboardBackground: Drawable? = null
|
|
||||||
private val stateListMap = EnumMap<ColorType, ColorStateList>(ColorType::class.java)
|
private val stateListMap = EnumMap<ColorType, ColorStateList>(ColorType::class.java)
|
||||||
private var backgroundSetupDone = false
|
private var backgroundSetupDone = false
|
||||||
override fun get(color: ColorType): Int = colorMap[color] ?: Color.BLACK
|
private val colorFilters = hashMapOf<ColorType, ColorFilter>()
|
||||||
|
override fun get(color: ColorType): Int = colorMap[color] ?: Color.GRAY
|
||||||
|
|
||||||
override fun setColor(drawable: Drawable, color: ColorType) {
|
override fun setColor(drawable: Drawable, color: ColorType) {
|
||||||
val colorStateList = stateListMap.getOrPut(color) { stateList(brightenOrDarken(get(color), true), get(color)) }
|
val colorStateList = stateListMap.getOrPut(color) { stateList(brightenOrDarken(get(color), true), get(color)) }
|
||||||
|
@ -565,14 +561,18 @@ class AllColors(private val colorMap: EnumMap<ColorType, Int>, override val them
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setColor(view: ImageView, color: ColorType) {
|
override fun setColor(view: ImageView, color: ColorType) {
|
||||||
|
if (color == TOOL_BAR_KEY) {
|
||||||
setColor(view.drawable, color)
|
setColor(view.drawable, color)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
view.colorFilter = getColorFilter(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setBackground(view: View, color: ColorType) {
|
override fun setBackground(view: View, color: ColorType) {
|
||||||
if (view.background == null)
|
if (view.background == null)
|
||||||
view.setBackgroundColor(Color.WHITE) // set white to make the color filters work
|
view.setBackgroundColor(Color.WHITE) // set white to make the color filters work
|
||||||
when (color) {
|
when (color) {
|
||||||
ONE_HANDED_MODE_BUTTON -> setColor(view.background, BACKGROUND) // button has no separate background color
|
ONE_HANDED_MODE_BUTTON -> setColor(view.background, MAIN_BACKGROUND) // button has no separate background color
|
||||||
MAIN_BACKGROUND -> {
|
MAIN_BACKGROUND -> {
|
||||||
if (keyboardBackground != null) {
|
if (keyboardBackground != null) {
|
||||||
if (!backgroundSetupDone) {
|
if (!backgroundSetupDone) {
|
||||||
|
@ -587,25 +587,32 @@ class AllColors(private val colorMap: EnumMap<ColorType, Int>, override val them
|
||||||
else -> setColor(view.background, color)
|
else -> setColor(view.background, color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getColorFilter(color: ColorType) = colorFilters.getOrPut(color) { colorFilter(get(color)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readAllColorsMap(prefs: SharedPreferences): EnumMap<ColorType, Int> {
|
fun readAllColorsMap(prefs: SharedPreferences, isNight: Boolean): EnumMap<ColorType, Int> {
|
||||||
val s = prefs.getString("all_colors", "") ?: ""
|
val prefPrefix = if (isNight) Settings.PREF_THEME_USER_COLOR_NIGHT_PREFIX else Settings.PREF_THEME_USER_COLOR_PREFIX
|
||||||
val c = EnumMap<ColorType, Int>(ColorType::class.java)
|
val colorsString = prefs.getString(prefPrefix + Settings.PREF_ALL_COLORS_SUFFIX, "") ?: ""
|
||||||
s.split(";").forEach {
|
val colorMap = EnumMap<ColorType, Int>(ColorType::class.java)
|
||||||
|
colorsString.split(";").forEach {
|
||||||
val ct = try {
|
val ct = try {
|
||||||
ColorType.valueOf(it.substringBefore(",").uppercase())
|
ColorType.valueOf(it.substringBefore(",").uppercase())
|
||||||
} catch (_: Exception) { // todo: which one?
|
} catch (_: Exception) { // todo: which one?
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
val i = it.substringAfter(",").toIntOrNull() ?: return@forEach
|
val i = it.substringAfter(",").toIntOrNull() ?: return@forEach
|
||||||
c[ct] = i
|
colorMap[ct] = i
|
||||||
}
|
}
|
||||||
return c
|
return colorMap
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeAllColorsMap(c: EnumMap<ColorType, Int>, prefs: SharedPreferences) {
|
fun writeAllColorsMap(colorMap: EnumMap<ColorType, Int>, prefs: SharedPreferences, isNight: Boolean) {
|
||||||
prefs.edit { putString("all_colors", c.map { "${it.key},${it.value}" }.joinToString(";")) }
|
val prefPrefix = if (isNight) Settings.PREF_THEME_USER_COLOR_NIGHT_PREFIX else Settings.PREF_THEME_USER_COLOR_PREFIX
|
||||||
|
prefs.edit { putString(
|
||||||
|
prefPrefix + Settings.PREF_ALL_COLORS_SUFFIX,
|
||||||
|
colorMap.map { "${it.key},${it.value}" }.joinToString(";")
|
||||||
|
) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun colorFilter(color: Int, mode: BlendModeCompat = BlendModeCompat.MODULATE): ColorFilter {
|
private fun colorFilter(color: Int, mode: BlendModeCompat = BlendModeCompat.MODULATE): ColorFilter {
|
||||||
|
@ -628,7 +635,6 @@ enum class ColorType {
|
||||||
ACTION_KEY_BACKGROUND,
|
ACTION_KEY_BACKGROUND,
|
||||||
ACTION_KEY_POPUP_KEYS_BACKGROUND,
|
ACTION_KEY_POPUP_KEYS_BACKGROUND,
|
||||||
AUTOFILL_BACKGROUND_CHIP,
|
AUTOFILL_BACKGROUND_CHIP,
|
||||||
BACKGROUND,
|
|
||||||
CLIPBOARD_PIN,
|
CLIPBOARD_PIN,
|
||||||
EMOJI_CATEGORY,
|
EMOJI_CATEGORY,
|
||||||
EMOJI_CATEGORY_SELECTED,
|
EMOJI_CATEGORY_SELECTED,
|
||||||
|
@ -643,6 +649,7 @@ enum class ColorType {
|
||||||
KEY_PREVIEW,
|
KEY_PREVIEW,
|
||||||
MORE_SUGGESTIONS_HINT,
|
MORE_SUGGESTIONS_HINT,
|
||||||
MORE_SUGGESTIONS_BACKGROUND,
|
MORE_SUGGESTIONS_BACKGROUND,
|
||||||
|
MORE_SUGGESTIONS_WORD_BACKGROUND,
|
||||||
POPUP_KEYS_BACKGROUND,
|
POPUP_KEYS_BACKGROUND,
|
||||||
NAVIGATION_BAR,
|
NAVIGATION_BAR,
|
||||||
SHIFT_KEY_ICON,
|
SHIFT_KEY_ICON,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
package helium314.keyboard.latin.settings
|
package helium314.keyboard.latin.settings
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
|
@ -15,12 +16,15 @@ import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.core.view.MenuProvider
|
import androidx.core.view.MenuProvider
|
||||||
import androidx.core.view.forEach
|
import androidx.core.view.forEach
|
||||||
import androidx.core.view.get
|
import androidx.core.view.isGone
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.rarepebble.colorpicker.ColorPickerView
|
import com.rarepebble.colorpicker.ColorPickerView
|
||||||
import helium314.keyboard.keyboard.KeyboardSwitcher
|
import helium314.keyboard.keyboard.KeyboardSwitcher
|
||||||
import helium314.keyboard.latin.R
|
import helium314.keyboard.latin.R
|
||||||
import helium314.keyboard.latin.RichInputMethodManager
|
import helium314.keyboard.latin.RichInputMethodManager
|
||||||
|
import helium314.keyboard.latin.common.ColorType
|
||||||
|
import helium314.keyboard.latin.common.readAllColorsMap
|
||||||
|
import helium314.keyboard.latin.common.writeAllColorsMap
|
||||||
import helium314.keyboard.latin.databinding.ColorSettingBinding
|
import helium314.keyboard.latin.databinding.ColorSettingBinding
|
||||||
import helium314.keyboard.latin.databinding.ColorSettingsBinding
|
import helium314.keyboard.latin.databinding.ColorSettingsBinding
|
||||||
import helium314.keyboard.latin.utils.DeviceProtectedUtils
|
import helium314.keyboard.latin.utils.DeviceProtectedUtils
|
||||||
|
@ -32,9 +36,14 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi
|
||||||
private val binding by viewBinding(ColorSettingsBinding::bind)
|
private val binding by viewBinding(ColorSettingsBinding::bind)
|
||||||
open val isNight = false
|
open val isNight = false
|
||||||
open val titleResId = R.string.select_user_colors
|
open val titleResId = R.string.select_user_colors
|
||||||
private var moreColors: Boolean
|
|
||||||
get() = prefs.getBoolean(Settings.PREF_SHOW_ALL_COLORS, false)
|
// 0 for default
|
||||||
set(value) { prefs.edit().putBoolean(Settings.PREF_SHOW_ALL_COLORS, value).apply() }
|
// 1 for more colors
|
||||||
|
// 2 for all colors
|
||||||
|
private var moreColors: Int
|
||||||
|
get() = prefs.getInt(Settings.PREF_SHOW_MORE_COLORS, 0)
|
||||||
|
set(value) { prefs.edit().putInt(Settings.PREF_SHOW_MORE_COLORS, value).apply() }
|
||||||
|
|
||||||
private val prefs by lazy { DeviceProtectedUtils.getSharedPreferences(requireContext()) }
|
private val prefs by lazy { DeviceProtectedUtils.getSharedPreferences(requireContext()) }
|
||||||
|
|
||||||
private val colorPrefsAndNames by lazy {
|
private val colorPrefsAndNames by lazy {
|
||||||
|
@ -83,24 +92,28 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
if (menu.size() == 1) menu[0].setTitle(getMenuTitle())
|
menu.add(Menu.NONE, 0, Menu.NONE, R.string.main_colors)
|
||||||
else menu.add(Menu.NONE, 1, Menu.NONE, getMenuTitle())
|
menu.add(Menu.NONE, 1, Menu.NONE, R.string.more_colors)
|
||||||
|
menu.add(Menu.NONE, 2, Menu.NONE, R.string.all_colors)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
|
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
|
||||||
// necessary, even though we only have a single menu item
|
// necessary, even though we only have a single menu item
|
||||||
// because the back arrow on top absurdly is implemented as a menu item
|
// because the back arrow on top absurdly is implemented as a menu item
|
||||||
if (menuItem.itemId == 1) {
|
if (menuItem.itemId in 0..2) {
|
||||||
moreColors = !moreColors
|
if (moreColors == menuItem.itemId) return true
|
||||||
menuItem.setTitle(getMenuTitle())
|
if (moreColors == 2 || menuItem.itemId == 2) {
|
||||||
|
RichInputMethodManager.getInstance().inputMethodManager.hideSoftInputFromWindow(binding.dummyText.windowToken, 0)
|
||||||
|
reloadKeyboard(false)
|
||||||
|
}
|
||||||
|
moreColors = menuItem.itemId
|
||||||
|
binding.info.isGone = menuItem.itemId != 2
|
||||||
updateColorPrefs()
|
updateColorPrefs()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getMenuTitle() = if (moreColors) R.string.main_colors else R.string.all_colors
|
|
||||||
|
|
||||||
override fun onViewStateRestored(savedInstanceState: Bundle?) {
|
override fun onViewStateRestored(savedInstanceState: Bundle?) {
|
||||||
super.onViewStateRestored(savedInstanceState)
|
super.onViewStateRestored(savedInstanceState)
|
||||||
// updateColorPrefs must be called after super.onViewStateRestored because for some reason Android
|
// updateColorPrefs must be called after super.onViewStateRestored because for some reason Android
|
||||||
|
@ -110,10 +123,61 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi
|
||||||
|
|
||||||
private fun updateColorPrefs() {
|
private fun updateColorPrefs() {
|
||||||
binding.colorSettingsContainer.removeAllViews()
|
binding.colorSettingsContainer.removeAllViews()
|
||||||
|
if (moreColors == 2) showAllColors()
|
||||||
|
else showMainColors()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showAllColors() {
|
||||||
|
val colors = readAllColorsMap(prefs, isNight)
|
||||||
|
ColorType.entries.forEach { type ->
|
||||||
|
val color = colors[type] ?: Color.GRAY
|
||||||
|
val csb = ColorSettingBinding.inflate(layoutInflater, binding.colorSettingsContainer, true)
|
||||||
|
csb.root.tag = type
|
||||||
|
csb.colorSwitch.isGone = true
|
||||||
|
csb.colorPreview.setColorFilter(color)
|
||||||
|
csb.colorText.text = type.name
|
||||||
|
|
||||||
|
val clickListener = View.OnClickListener {
|
||||||
|
val hidden = RichInputMethodManager.getInstance().inputMethodManager.hideSoftInputFromWindow(binding.dummyText.windowToken, 0)
|
||||||
|
val picker = ColorPickerView(requireContext())
|
||||||
|
picker.showAlpha(type != ColorType.MAIN_BACKGROUND) // background behind background looks broken and sometimes is dark, sometimes light
|
||||||
|
picker.showHex(true)
|
||||||
|
picker.showPreview(true)
|
||||||
|
picker.color = color
|
||||||
|
val builder = AlertDialog.Builder(requireContext())
|
||||||
|
builder
|
||||||
|
.setTitle(type.name)
|
||||||
|
.setView(picker)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
|
val colorMap = readAllColorsMap(prefs, isNight) // better re-read it
|
||||||
|
colorMap[type] = picker.color
|
||||||
|
writeAllColorsMap(colorMap, prefs, isNight)
|
||||||
|
updateAllColorPreviews()
|
||||||
|
reloadKeyboard(hidden)
|
||||||
|
}
|
||||||
|
val dialog = builder.create()
|
||||||
|
dialog.show()
|
||||||
|
// Reduce the size of the dialog in portrait mode
|
||||||
|
val wrapContent = WindowManager.LayoutParams.WRAP_CONTENT
|
||||||
|
val widthPortrait = (resources.displayMetrics.widthPixels * 0.80f).toInt()
|
||||||
|
val orientation = (resources.configuration.orientation)
|
||||||
|
if (orientation == Configuration.ORIENTATION_LANDSCAPE)
|
||||||
|
dialog.window?.setLayout(wrapContent, wrapContent)
|
||||||
|
else
|
||||||
|
dialog.window?.setLayout(widthPortrait, wrapContent)
|
||||||
|
}
|
||||||
|
csb.colorTextContainer.setOnClickListener(clickListener)
|
||||||
|
csb.colorPreview.setOnClickListener(clickListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showMainColors() {
|
||||||
val prefPrefix = if (isNight) Settings.PREF_THEME_USER_COLOR_NIGHT_PREFIX else Settings.PREF_THEME_USER_COLOR_PREFIX
|
val prefPrefix = if (isNight) Settings.PREF_THEME_USER_COLOR_NIGHT_PREFIX else Settings.PREF_THEME_USER_COLOR_PREFIX
|
||||||
colorPrefsAndNames.forEachIndexed { index, (colorPref, colorPrefName) ->
|
colorPrefsAndNames.forEachIndexed { index, (colorPref, colorPrefName) ->
|
||||||
val autoColor = prefs.getBoolean(prefPrefix + colorPref + Settings.PREF_AUTO_USER_COLOR_SUFFIX, true)
|
val autoColor = prefs.getBoolean(prefPrefix + colorPref + Settings.PREF_AUTO_USER_COLOR_SUFFIX, true)
|
||||||
if (!moreColors && colorPref in colorPrefsToHideInitially && autoColor)
|
if (moreColors == 0 && colorPref in colorPrefsToHideInitially && autoColor)
|
||||||
return@forEachIndexed
|
return@forEachIndexed
|
||||||
val csb = ColorSettingBinding.inflate(layoutInflater, binding.colorSettingsContainer, true)
|
val csb = ColorSettingBinding.inflate(layoutInflater, binding.colorSettingsContainer, true)
|
||||||
csb.root.tag = index
|
csb.root.tag = index
|
||||||
|
@ -129,7 +193,7 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi
|
||||||
if (b) csb.colorSummary.text = ""
|
if (b) csb.colorSummary.text = ""
|
||||||
else csb.colorSummary.setText(R.string.auto_user_color)
|
else csb.colorSummary.setText(R.string.auto_user_color)
|
||||||
reloadKeyboard(hidden)
|
reloadKeyboard(hidden)
|
||||||
updateColorPreviews()
|
updateMainColorPreviews()
|
||||||
}
|
}
|
||||||
csb.colorSwitch.setOnCheckedChangeListener(switchListener)
|
csb.colorSwitch.setOnCheckedChangeListener(switchListener)
|
||||||
|
|
||||||
|
@ -160,6 +224,7 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi
|
||||||
builder
|
builder
|
||||||
.setTitle(colorPrefName)
|
.setTitle(colorPrefName)
|
||||||
.setView(picker)
|
.setView(picker)
|
||||||
|
.setCancelable(false)
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
prefs.edit { putInt(prefPrefix + colorPref, picker.color) }
|
prefs.edit { putInt(prefPrefix + colorPref, picker.color) }
|
||||||
|
@ -169,9 +234,9 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi
|
||||||
csb.colorSwitch.isChecked = true
|
csb.colorSwitch.isChecked = true
|
||||||
csb.colorSummary.text = ""
|
csb.colorSummary.text = ""
|
||||||
csb.colorSwitch.setOnCheckedChangeListener(switchListener)
|
csb.colorSwitch.setOnCheckedChangeListener(switchListener)
|
||||||
updateColorPreviews()
|
updateMainColorPreviews()
|
||||||
} else {
|
} else {
|
||||||
updateColorPreviews()
|
updateMainColorPreviews()
|
||||||
}
|
}
|
||||||
reloadKeyboard(hidden)
|
reloadKeyboard(hidden)
|
||||||
}
|
}
|
||||||
|
@ -199,14 +264,23 @@ open class ColorsSettingsFragment : Fragment(R.layout.color_settings), MenuProvi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateColorPreviews() {
|
private fun updateMainColorPreviews() {
|
||||||
binding.colorSettingsContainer.forEach { view ->
|
binding.colorSettingsContainer.forEach { view ->
|
||||||
val index = view.tag as Int
|
val index = view.tag as? Int ?: return@forEach
|
||||||
val color = Settings.readUserColor(prefs, requireContext(), colorPrefsAndNames[index].first, isNight)
|
val color = Settings.readUserColor(prefs, requireContext(), colorPrefsAndNames[index].first, isNight)
|
||||||
view.findViewById<ImageView>(R.id.color_preview)?.setColorFilter(color)
|
view.findViewById<ImageView>(R.id.color_preview)?.setColorFilter(color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateAllColorPreviews() {
|
||||||
|
val colorMap = readAllColorsMap(prefs, isNight)
|
||||||
|
binding.colorSettingsContainer.forEach { view ->
|
||||||
|
val type = view.tag as? ColorType ?: return@forEach
|
||||||
|
val color = colorMap[type] ?: Color.GRAY
|
||||||
|
view.findViewById<ImageView>(R.id.color_preview)?.setColorFilter(color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun reloadKeyboard(show: Boolean) {
|
private fun reloadKeyboard(show: Boolean) {
|
||||||
ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute {
|
ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute {
|
||||||
KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext())
|
KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext())
|
||||||
|
|
|
@ -79,6 +79,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
public static final String PREF_COLOR_HINT_TEXT_SUFFIX = "hint_text";
|
public static final String PREF_COLOR_HINT_TEXT_SUFFIX = "hint_text";
|
||||||
public static final String PREF_COLOR_BACKGROUND_SUFFIX = "background";
|
public static final String PREF_COLOR_BACKGROUND_SUFFIX = "background";
|
||||||
public static final String PREF_AUTO_USER_COLOR_SUFFIX = "_auto";
|
public static final String PREF_AUTO_USER_COLOR_SUFFIX = "_auto";
|
||||||
|
public static final String PREF_ALL_COLORS_SUFFIX = "all_colors";
|
||||||
|
|
||||||
public static final String PREF_AUTO_CAP = "auto_cap";
|
public static final String PREF_AUTO_CAP = "auto_cap";
|
||||||
public static final String PREF_VIBRATE_ON = "vibrate_on";
|
public static final String PREF_VIBRATE_ON = "vibrate_on";
|
||||||
|
@ -158,7 +159,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
|
|
||||||
public static final String PREF_PINNED_CLIPS = "pinned_clips";
|
public static final String PREF_PINNED_CLIPS = "pinned_clips";
|
||||||
public static final String PREF_VERSION_CODE = "version_code";
|
public static final String PREF_VERSION_CODE = "version_code";
|
||||||
public static final String PREF_SHOW_ALL_COLORS = "show_all_colors";
|
public static final String PREF_SHOW_MORE_COLORS = "show_more_colors";
|
||||||
public static final String PREF_LIBRARY_CHECKSUM = "lib_checksum";
|
public static final String PREF_LIBRARY_CHECKSUM = "lib_checksum";
|
||||||
|
|
||||||
private static final float UNDEFINED_PREFERENCE_VALUE_FLOAT = -1.0f;
|
private static final float UNDEFINED_PREFERENCE_VALUE_FLOAT = -1.0f;
|
||||||
|
@ -182,7 +183,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
add(PREF_LAST_SHOWN_EMOJI_CATEGORY_ID);
|
add(PREF_LAST_SHOWN_EMOJI_CATEGORY_ID);
|
||||||
add(PREF_EMOJI_RECENT_KEYS);
|
add(PREF_EMOJI_RECENT_KEYS);
|
||||||
add(PREF_DONT_SHOW_MISSING_DICTIONARY_DIALOG);
|
add(PREF_DONT_SHOW_MISSING_DICTIONARY_DIALOG);
|
||||||
add(PREF_SHOW_ALL_COLORS);
|
add(PREF_SHOW_MORE_COLORS);
|
||||||
add(PREF_SELECTED_SUBTYPE);
|
add(PREF_SELECTED_SUBTYPE);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|
|
@ -5,22 +5,27 @@
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/info"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:text="@string/all_colors_warning"
|
||||||
|
style="?android:attr/textAppearanceSmall" />
|
||||||
<ScrollView
|
<ScrollView
|
||||||
|
android:id="@+id/colors_scroller"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_below="@id/info"
|
||||||
android:layout_above="@id/dummy_text">
|
android:layout_above="@id/dummy_text">
|
||||||
<LinearLayout
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingTop="6dp"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/color_settings_container"
|
android:id="@+id/color_settings_container"
|
||||||
|
android:paddingTop="6dp"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical" />
|
android:orientation="vertical" />
|
||||||
</LinearLayout>
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<EditText
|
<EditText
|
||||||
android:id="@+id/dummy_text"
|
android:id="@+id/dummy_text"
|
||||||
|
|
|
@ -694,8 +694,12 @@ New dictionary:
|
||||||
<string name="auto_user_color">Choose color automatically</string>
|
<string name="auto_user_color">Choose color automatically</string>
|
||||||
<!-- Menu item for showing fewer colors -->
|
<!-- Menu item for showing fewer colors -->
|
||||||
<string name="main_colors">Show main colors only</string>
|
<string name="main_colors">Show main colors only</string>
|
||||||
|
<!-- Menu item for showing more colors -->
|
||||||
|
<string name="more_colors">Show more colors</string>
|
||||||
<!-- Menu item for showing all colors -->
|
<!-- Menu item for showing all colors -->
|
||||||
<string name="all_colors">Show all colors</string>
|
<string name="all_colors">Show all colors</string>
|
||||||
|
<!-- Warning message displayed when showing all colors -->
|
||||||
|
<string name="all_colors_warning">This setting exposes all colors that are used internally. The list of colors may change at any time. There is no default color, and the names will not be translated.</string>
|
||||||
<!-- Hint for text field just to show keyboard (in color settings) -->
|
<!-- Hint for text field just to show keyboard (in color settings) -->
|
||||||
<string name="hint_show_keyboard">Click for preview</string>
|
<string name="hint_show_keyboard">Click for preview</string>
|
||||||
<!-- Description for selection of user-defined colors. -->
|
<!-- Description for selection of user-defined colors. -->
|
||||||
|
|
Loading…
Add table
Reference in a new issue