mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-18 07:53:07 +00:00
add a separate fragment for setting user-defined colors
issues: when using day/night mode, active keyboard is shown in preview, not the acually modified varian reloading / updating the preview is either slow or will not show the keyboard again
This commit is contained in:
parent
d33650586b
commit
b18b7dc820
20 changed files with 383 additions and 206 deletions
|
@ -141,23 +141,22 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
|
|||
return KEYBOARD_THEMES[DEFAULT_THEME_ID];
|
||||
}
|
||||
|
||||
// todo (later): material you, system accent, ...
|
||||
public static Colors getThemeColors(final String themeColors, final String themeStyle, final Context context, final SharedPreferences prefs) {
|
||||
final boolean hasBorders = prefs.getBoolean(Settings.PREF_THEME_KEY_BORDERS, false);
|
||||
switch (themeColors) {
|
||||
case THEME_USER:
|
||||
final int accent = prefs.getInt(Settings.PREF_THEME_USER_COLOR_ACCENT, Color.BLUE);
|
||||
final int keyBgColor = prefs.getInt(Settings.PREF_THEME_USER_COLOR_KEYS, Color.LTGRAY);
|
||||
final int keyTextColor = prefs.getInt(Settings.PREF_THEME_USER_COLOR_TEXT, Color.WHITE);
|
||||
final int hintTextColor = prefs.getInt(Settings.PREF_THEME_USER_COLOR_HINT_TEXT, Color.WHITE);
|
||||
final int background = prefs.getInt(Settings.PREF_THEME_USER_COLOR_BACKGROUND, Color.DKGRAY);
|
||||
final int accent = Settings.readUserColor(prefs, context, Settings.PREF_COLOR_ACCENT_SUFFIX, false);
|
||||
final int keyBgColor = Settings.readUserColor(prefs, context, Settings.PREF_COLOR_KEYS_SUFFIX, false);
|
||||
final int keyTextColor = Settings.readUserColor(prefs, context, Settings.PREF_COLOR_TEXT_SUFFIX, false);
|
||||
final int hintTextColor = Settings.readUserColor(prefs, context, Settings.PREF_COLOR_HINT_TEXT_SUFFIX, false);
|
||||
final int background = Settings.readUserColor(prefs, context, Settings.PREF_COLOR_BACKGROUND_SUFFIX, false);
|
||||
return new Colors(themeStyle, hasBorders, accent, background, keyBgColor, ColorUtilKt.brightenOrDarken(keyBgColor, true), keyBgColor, keyTextColor, hintTextColor);
|
||||
case THEME_USER_NIGHT:
|
||||
final int accent2 = prefs.getInt(Settings.PREF_THEME_USER_DARK_COLOR_ACCENT, Color.BLUE);
|
||||
final int keyBgColor2 = prefs.getInt(Settings.PREF_THEME_USER_DARK_COLOR_KEYS, Color.LTGRAY);
|
||||
final int keyTextColor2 = prefs.getInt(Settings.PREF_THEME_USER_DARK_COLOR_TEXT, Color.WHITE);
|
||||
final int hintTextColor2 = prefs.getInt(Settings.PREF_THEME_USER_DARK_COLOR_HINT_TEXT, Color.WHITE);
|
||||
final int background2 = prefs.getInt(Settings.PREF_THEME_USER_DARK_COLOR_BACKGROUND, Color.DKGRAY);
|
||||
final int accent2 = Settings.readUserColor(prefs, context, Settings.PREF_COLOR_ACCENT_SUFFIX, true);
|
||||
final int keyBgColor2 = Settings.readUserColor(prefs, context, Settings.PREF_COLOR_KEYS_SUFFIX, true);
|
||||
final int keyTextColor2 = Settings.readUserColor(prefs, context, Settings.PREF_COLOR_TEXT_SUFFIX, true);
|
||||
final int hintTextColor2 = Settings.readUserColor(prefs, context, Settings.PREF_COLOR_HINT_TEXT_SUFFIX, true);
|
||||
final int background2 = Settings.readUserColor(prefs, context, Settings.PREF_COLOR_BACKGROUND_SUFFIX, true);
|
||||
return new Colors(themeStyle, hasBorders, accent2, background2, keyBgColor2, ColorUtilKt.brightenOrDarken(keyBgColor2, true), keyBgColor2, keyTextColor2, hintTextColor2);
|
||||
case THEME_DARK:
|
||||
return new Colors(
|
||||
|
|
|
@ -2,10 +2,8 @@ package org.dslul.openboard.inputmethod.latin.settings
|
|||
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.TwoStatePreference
|
||||
|
@ -137,65 +135,7 @@ class AppearanceSettingsFragment : SubScreenFragment() {
|
|||
}
|
||||
themeVariantNightPref?.isVisible = dayNightPref?.isChecked == true
|
||||
userColorsPref.isVisible = themeVariantPref.value == KeyboardTheme.THEME_USER
|
||||
userColorsPref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
adjustColors(false)
|
||||
true
|
||||
}
|
||||
userColorsPrefNight?.isVisible = dayNightPref?.isChecked == true && themeVariantNightPref?.value == KeyboardTheme.THEME_USER_NIGHT
|
||||
userColorsPrefNight?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
adjustColors(true)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
// todo: improve color selection, should at very least show a preview of the color
|
||||
// but maybe a separate fragment would be better
|
||||
// idea:
|
||||
// left: which color (background, key, text,...)
|
||||
// right: color preview (always the correct one, even if determined automatically)
|
||||
// maybe copy parts from simple keyboard, see e.g. screenshot 4 in https://github.com/SimpleMobileTools/Simple-Keyboard/tree/main/fastlane/metadata/android/en-US/images/phoneScreenshots
|
||||
// below (for some colors, with indent):
|
||||
// enable user-defining (most colors, but definitely not background)
|
||||
// use system accent (for accent and text colors)
|
||||
// on click: color selector
|
||||
// maybe copy parts from simple keyboard, see e.g. screenshot 4 in https://github.com/SimpleMobileTools/Simple-Keyboard/tree/main/fastlane/metadata/android/en-US/images/phoneScreenshots
|
||||
// but full range would be preferable
|
||||
// use some color picker library? would likely allow nicer tuning
|
||||
private fun adjustColors(dark: Boolean) {
|
||||
val items = listOf(
|
||||
R.string.select_color_background,
|
||||
R.string.select_color_key_background,
|
||||
R.string.select_color_key,
|
||||
R.string.select_color_key_hint,
|
||||
R.string.select_color_accent,
|
||||
).map { requireContext().getString(it) }
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setTitle(R.string.select_color_to_adjust)
|
||||
.setItems(items.toTypedArray()) { _, i ->
|
||||
val (pref, default) =
|
||||
if (dark)
|
||||
when (i) {
|
||||
0 -> Settings.PREF_THEME_USER_DARK_COLOR_BACKGROUND to Color.DKGRAY
|
||||
1 -> Settings.PREF_THEME_USER_DARK_COLOR_KEYS to Color.LTGRAY
|
||||
2 -> Settings.PREF_THEME_USER_DARK_COLOR_TEXT to Color.WHITE
|
||||
3 -> Settings.PREF_THEME_USER_DARK_COLOR_HINT_TEXT to Color.WHITE
|
||||
4 -> Settings.PREF_THEME_USER_DARK_COLOR_ACCENT to Color.BLUE
|
||||
else -> return@setItems
|
||||
}
|
||||
else
|
||||
when (i) {
|
||||
0 -> Settings.PREF_THEME_USER_COLOR_BACKGROUND to Color.DKGRAY
|
||||
1 -> Settings.PREF_THEME_USER_COLOR_KEYS to Color.LTGRAY
|
||||
2 -> Settings.PREF_THEME_USER_COLOR_TEXT to Color.WHITE
|
||||
3 -> Settings.PREF_THEME_USER_COLOR_HINT_TEXT to Color.WHITE
|
||||
4 -> Settings.PREF_THEME_USER_COLOR_ACCENT to Color.BLUE
|
||||
else -> return@setItems
|
||||
}
|
||||
val d = ColorPickerDialog(requireContext(), items[i], sharedPreferences, pref, default)
|
||||
d.show()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun setupKeyboardHeight(prefKey: String, defaultValue: Float) {
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// adapted from https://github.com/rkkr/simple-keyboard/blob/master/app/src/main/java/rkr/simplekeyboard/inputmethod/latin/settings/ColorDialogPreference.java
|
||||
package org.dslul.openboard.inputmethod.latin.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.view.View;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import org.dslul.openboard.inputmethod.latin.R;
|
||||
|
||||
public class ColorPickerDialog extends AlertDialog implements SeekBar.OnSeekBarChangeListener {
|
||||
protected ColorPickerDialog(final Context context, final String title, final SharedPreferences prefs,
|
||||
final String colorPref, final int defaultColor) {
|
||||
super(context);
|
||||
setTitle(title);
|
||||
View view = getLayoutInflater().inflate(R.layout.color_dialog, null);
|
||||
mSeekBarRed = (SeekBar)view.findViewById(R.id.seek_bar_dialog_bar_red);
|
||||
mSeekBarRed.setMax(255);
|
||||
mSeekBarRed.setOnSeekBarChangeListener(this);
|
||||
mSeekBarRed.getProgressDrawable().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
|
||||
mSeekBarRed.getThumb().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
|
||||
mSeekBarGreen = (SeekBar)view.findViewById(R.id.seek_bar_dialog_bar_green);
|
||||
mSeekBarGreen.setMax(255);
|
||||
mSeekBarGreen.setOnSeekBarChangeListener(this);
|
||||
mSeekBarGreen.getThumb().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN);
|
||||
mSeekBarGreen.getProgressDrawable().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN);
|
||||
mSeekBarBlue = (SeekBar)view.findViewById(R.id.seek_bar_dialog_bar_blue);
|
||||
mSeekBarBlue.setMax(255);
|
||||
mSeekBarBlue.setOnSeekBarChangeListener(this);
|
||||
mSeekBarBlue.getThumb().setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN);
|
||||
mSeekBarBlue.getProgressDrawable().setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN);
|
||||
mValueView = (TextView)view.findViewById(R.id.seek_bar_dialog_value);
|
||||
setView(view);
|
||||
|
||||
// init with correct values
|
||||
// using onShowListener?
|
||||
setOnShowListener(dialogInterface -> {
|
||||
int color = prefs.getInt(colorPref, defaultColor);
|
||||
mSeekBarRed.setProgress(Color.red(color));
|
||||
mSeekBarGreen.setProgress(Color.green(color));
|
||||
mSeekBarBlue.setProgress(Color.blue(color));
|
||||
setHeaderText(color);
|
||||
});
|
||||
|
||||
// set on ok and on cancel listeners
|
||||
setButton(BUTTON_NEGATIVE, context.getText(android.R.string.cancel), (dialogInterface, i) -> dismiss());
|
||||
setButton(BUTTON_POSITIVE, context.getText(android.R.string.ok), (dialogInterface, i) -> {
|
||||
final int value = Color.rgb(
|
||||
mSeekBarRed.getProgress(),
|
||||
mSeekBarGreen.getProgress(),
|
||||
mSeekBarBlue.getProgress());
|
||||
prefs.edit().putInt(colorPref, value).apply();
|
||||
dismiss();
|
||||
});
|
||||
}
|
||||
|
||||
private final TextView mValueView;
|
||||
private final SeekBar mSeekBarRed;
|
||||
private final SeekBar mSeekBarGreen;
|
||||
private final SeekBar mSeekBarBlue;
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) {
|
||||
int color = Color.rgb(
|
||||
mSeekBarRed.getProgress(),
|
||||
mSeekBarGreen.getProgress(),
|
||||
mSeekBarBlue.getProgress());
|
||||
setHeaderText(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
private void setHeaderText(int color) {
|
||||
mValueView.setText(getValueText(color));
|
||||
boolean bright = Color.red(color) + Color.green(color) + Color.blue(color) > 128 * 3;
|
||||
mValueView.setTextColor(bright ? Color.BLACK : Color.WHITE);
|
||||
mValueView.setBackgroundColor(color);
|
||||
}
|
||||
|
||||
private String getValueText(final int value) {
|
||||
String temp = Integer.toHexString(value);
|
||||
for (; temp.length() < 8; temp = "0" + temp);
|
||||
return temp.substring(2).toUpperCase();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
package org.dslul.openboard.inputmethod.latin.settings
|
||||
|
||||
import android.app.Activity
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.CompoundButton
|
||||
import android.widget.ImageView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.edit
|
||||
import androidx.core.view.forEachIndexed
|
||||
import androidx.core.view.setPadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.skydoves.colorpickerview.ColorPickerDialog
|
||||
import com.skydoves.colorpickerview.flag.BubbleFlag
|
||||
import com.skydoves.colorpickerview.flag.FlagMode
|
||||
import com.skydoves.colorpickerview.listeners.ColorEnvelopeListener
|
||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardSwitcher
|
||||
import org.dslul.openboard.inputmethod.latin.R
|
||||
import org.dslul.openboard.inputmethod.latin.RichInputMethodManager
|
||||
import org.dslul.openboard.inputmethod.latin.databinding.ColorSettingBinding
|
||||
import org.dslul.openboard.inputmethod.latin.databinding.ColorSettingsBinding
|
||||
import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils
|
||||
import org.dslul.openboard.inputmethod.latin.utils.ExecutorUtils
|
||||
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils
|
||||
|
||||
open class ColorsSettingsFragment : Fragment(R.layout.color_settings) {
|
||||
|
||||
private val binding by viewBinding(ColorSettingsBinding::bind)
|
||||
open val isNight = false
|
||||
open val titleResId = R.string.select_user_colors
|
||||
private val prefs by lazy { DeviceProtectedUtils.getSharedPreferences(requireContext()) }
|
||||
private val colorPrefs = listOf(
|
||||
Settings.PREF_COLOR_BACKGROUND_SUFFIX,
|
||||
Settings.PREF_COLOR_KEYS_SUFFIX,
|
||||
Settings.PREF_COLOR_TEXT_SUFFIX,
|
||||
Settings.PREF_COLOR_HINT_TEXT_SUFFIX,
|
||||
Settings.PREF_COLOR_ACCENT_SUFFIX,
|
||||
)
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
val activity: Activity? = activity
|
||||
if (activity is AppCompatActivity) {
|
||||
val actionBar = activity.supportActionBar ?: return
|
||||
actionBar.setTitle(titleResId)
|
||||
}
|
||||
if (isNight != ResourceUtils.isNight(requireContext().resources))
|
||||
// reload to get the right configuration
|
||||
// todo: this does not work, keyboard also reloading with some other context
|
||||
reloadKeyboard(false)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
if (isNight != ResourceUtils.isNight(requireContext().resources))
|
||||
// reload again so the correct configuration is applied
|
||||
// todo: this does not work, keyboard also reloading with some other context
|
||||
KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext())
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val colorPrefNames = listOf(
|
||||
R.string.select_color_background,
|
||||
R.string.select_color_key_background,
|
||||
R.string.select_color_key,
|
||||
R.string.select_color_key_hint,
|
||||
R.string.select_color_accent,
|
||||
).map { requireContext().getString(it) }
|
||||
val prefPrefix = if (isNight) Settings.PREF_THEME_USER_COLOR_NIGHT_PREFIX else Settings.PREF_THEME_USER_COLOR_PREFIX
|
||||
colorPrefs.forEachIndexed { index, colorPref ->
|
||||
val csb = ColorSettingBinding.inflate(layoutInflater, binding.colorSettingsContainer, true)
|
||||
csb.colorSwitch.isChecked = !prefs.getBoolean(prefPrefix + colorPref + Settings.PREF_AUTO_USER_COLOR_SUFFIX, true)
|
||||
csb.colorPreview.setColorFilter(Settings.readUserColor(prefs, requireContext(), colorPrefs[index], isNight))
|
||||
csb.colorText.text = colorPrefNames[index]
|
||||
if (!csb.colorSwitch.isChecked) {
|
||||
csb.colorSummary.setText(R.string.auto_user_color)
|
||||
}
|
||||
val switchListener = CompoundButton.OnCheckedChangeListener { _, b ->
|
||||
val hidden = RichInputMethodManager.getInstance().inputMethodManager.hideSoftInputFromWindow(binding.dummyText.windowToken, 0)
|
||||
prefs.edit { putBoolean(prefPrefix + colorPref + Settings.PREF_AUTO_USER_COLOR_SUFFIX, !b) }
|
||||
if (b) csb.colorSummary.text = ""
|
||||
else csb.colorSummary.setText(R.string.auto_user_color)
|
||||
reloadKeyboard(hidden)
|
||||
updateColorPreviews()
|
||||
}
|
||||
csb.colorSwitch.setOnCheckedChangeListener(switchListener)
|
||||
|
||||
val clickListener = View.OnClickListener {
|
||||
val hidden = RichInputMethodManager.getInstance().inputMethodManager.hideSoftInputFromWindow(binding.dummyText.windowToken, 0)
|
||||
val b = ColorPickerDialog.Builder(requireContext())
|
||||
.setTitle(colorPrefNames[index])
|
||||
// todo: later it should be activated, but currently setting alpha leads to glitches,
|
||||
// e.g. when setting alpha on key text it's not applied for key icons, but for emojis
|
||||
.attachAlphaSlideBar(false)
|
||||
.setPositiveButton(android.R.string.ok, ColorEnvelopeListener { envelope, _ ->
|
||||
prefs.edit { putInt(prefPrefix + colorPrefs[index], envelope.color) }
|
||||
if (!csb.colorSwitch.isChecked) {
|
||||
prefs.edit { putBoolean(prefPrefix + colorPref + Settings.PREF_AUTO_USER_COLOR_SUFFIX, false) }
|
||||
csb.colorSwitch.setOnCheckedChangeListener(null)
|
||||
csb.colorSwitch.isChecked = true
|
||||
csb.colorSummary.text = ""
|
||||
csb.colorSwitch.setOnCheckedChangeListener(switchListener)
|
||||
reloadKeyboard(hidden)
|
||||
updateColorPreviews()
|
||||
return@ColorEnvelopeListener
|
||||
}
|
||||
reloadKeyboard(hidden)
|
||||
updateColorPreviews()
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ ->
|
||||
if (hidden)
|
||||
RichInputMethodManager.getInstance().inputMethodManager.showSoftInput(binding.dummyText, 0)
|
||||
}
|
||||
val initialColor = if (prefs.contains(prefPrefix + colorPref))
|
||||
prefs.getInt(prefPrefix + colorPref, Color.GRAY)
|
||||
else
|
||||
Settings.readUserColor(prefs, requireContext(), colorPrefs[index], isNight)
|
||||
b.colorPickerView.setInitialColor(initialColor)
|
||||
b.colorPickerView.setPadding(15)
|
||||
// set better color drawable? neither the white circle nor the plus is nice
|
||||
b.colorPickerView.setSelectorDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_plus))
|
||||
b.colorPickerView.flagView = BubbleFlag(requireContext()).apply { flagMode = FlagMode.ALWAYS }
|
||||
b.show()
|
||||
}
|
||||
csb.colorTextContainer.setOnClickListener(clickListener)
|
||||
csb.colorPreview.setOnClickListener(clickListener)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateColorPreviews() {
|
||||
binding.colorSettingsContainer.forEachIndexed { index, view ->
|
||||
val color = Settings.readUserColor(prefs, requireContext(), colorPrefs[index], isNight)
|
||||
view.findViewById<ImageView>(R.id.color_preview)?.setColorFilter(color)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reloadKeyboard(show: Boolean) {
|
||||
// todo: any way to make some kind of "light update" to keyboard?
|
||||
// only reloading main keyboard view is necessary...
|
||||
// or get an actual (live) preview instead of the full keyboard?
|
||||
// or accelerate keyboard inflate, a big here issue is emojiCategory creating many keyboards
|
||||
KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext())
|
||||
// todo: this does not work, keyboard also reloading with some other context
|
||||
// KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(Settings.getDayNightContext(requireContext(), isNight))
|
||||
if (!show) return
|
||||
Thread.sleep(100) // some pause is necessary to avoid visual glitches
|
||||
RichInputMethodManager.getInstance().inputMethodManager.showSoftInput(binding.dummyText, 0)
|
||||
return
|
||||
// for some reason showing again does not work when running with executor
|
||||
// but when running without it's noticeably slow, and sometimes produces glitches
|
||||
// todo: decider whether to just hide, or have some slowdown and show again
|
||||
ExecutorUtils.getBackgroundExecutor(ExecutorUtils.KEYBOARD).execute {
|
||||
KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext())
|
||||
if (!show) return@execute
|
||||
Thread.sleep(100)
|
||||
RichInputMethodManager.getInstance().inputMethodManager.showSoftInput(binding.dummyText, 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class ColorsNightSettingsFragment : ColorsSettingsFragment() {
|
||||
override val isNight = true
|
||||
override val titleResId = R.string.select_user_colors_night
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package org.dslul.openboard.inputmethod.latin.settings
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
// taken from StreetComplete, ViewBinder.kt
|
||||
inline fun <reified T : ViewBinding> Fragment.viewBinding(
|
||||
noinline viewBinder: (View) -> T,
|
||||
rootViewId: Int? = null
|
||||
) = FragmentViewBindingPropertyDelegate(this, viewBinder, rootViewId)
|
||||
|
||||
class FragmentViewBindingPropertyDelegate<T : ViewBinding>(
|
||||
private val fragment: Fragment,
|
||||
private val viewBinder: (View) -> T,
|
||||
private val rootViewId: Int? = null
|
||||
) : ReadOnlyProperty<Fragment, T>, LifecycleEventObserver {
|
||||
|
||||
private var binding: T? = null
|
||||
|
||||
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
|
||||
if (event == Lifecycle.Event.ON_DESTROY) {
|
||||
binding = null
|
||||
source.lifecycle.removeObserver(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
|
||||
if (binding == null) {
|
||||
val rootView = if (rootViewId != null) {
|
||||
thisRef.requireView().findViewById<ViewGroup>(rootViewId)!!.getChildAt(0)
|
||||
} else {
|
||||
thisRef.requireView()
|
||||
}
|
||||
binding = viewBinder(rootView)
|
||||
fragment.viewLifecycleOwner.lifecycle.addObserver(this)
|
||||
}
|
||||
return binding!!
|
||||
}
|
||||
}
|
|
@ -22,12 +22,16 @@ import android.content.SharedPreferences;
|
|||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import android.util.TypedValue;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.Gravity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.dslul.openboard.inputmethod.keyboard.KeyboardTheme;
|
||||
import org.dslul.openboard.inputmethod.latin.AudioAndHapticFeedbackManager;
|
||||
|
@ -37,6 +41,7 @@ import org.dslul.openboard.inputmethod.latin.common.Colors;
|
|||
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.common.StringUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.AdditionalSubtypeUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.ColorUtilKt;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.JniUtils;
|
||||
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
|
||||
|
@ -66,16 +71,14 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
|||
public static final String PREF_THEME_VARIANT_NIGHT = "theme_variant_night";
|
||||
public static final String PREF_THEME_KEY_BORDERS = "theme_key_borders";
|
||||
public static final String PREF_THEME_DAY_NIGHT = "theme_auto_day_night";
|
||||
public static final String PREF_THEME_USER_COLOR_TEXT = "theme_color_text";
|
||||
public static final String PREF_THEME_USER_COLOR_HINT_TEXT = "theme_color_hint_text";
|
||||
public static final String PREF_THEME_USER_COLOR_BACKGROUND = "theme_color_background";
|
||||
public static final String PREF_THEME_USER_COLOR_KEYS = "theme_color_keys";
|
||||
public static final String PREF_THEME_USER_COLOR_ACCENT = "theme_color_accent";
|
||||
public static final String PREF_THEME_USER_DARK_COLOR_TEXT = "theme_dark_color_text";
|
||||
public static final String PREF_THEME_USER_DARK_COLOR_HINT_TEXT = "theme_dark_color_hint_text";
|
||||
public static final String PREF_THEME_USER_DARK_COLOR_BACKGROUND = "theme_dark_color_background";
|
||||
public static final String PREF_THEME_USER_DARK_COLOR_KEYS = "theme_dark_color_keys";
|
||||
public static final String PREF_THEME_USER_DARK_COLOR_ACCENT = "theme_dark_color_accent";
|
||||
public static final String PREF_THEME_USER_COLOR_PREFIX = "theme_color_";
|
||||
public static final String PREF_THEME_USER_COLOR_NIGHT_PREFIX = "theme_dark_color_";
|
||||
public static final String PREF_COLOR_KEYS_SUFFIX = "keys";
|
||||
public static final String PREF_COLOR_ACCENT_SUFFIX = "accent";
|
||||
public static final String PREF_COLOR_TEXT_SUFFIX = "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_AUTO_USER_COLOR_SUFFIX = "_auto";
|
||||
public static final String PREF_VOICE_INPUT_KEY = "pref_voice_input_key";
|
||||
public static final String PREF_EDIT_PERSONAL_DICTIONARY = "edit_personal_dictionary";
|
||||
public static final String PREF_AUTO_CORRECTION = "pref_key_auto_correction";
|
||||
|
@ -532,9 +535,8 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
|||
}
|
||||
|
||||
public static Colors getColorsForCurrentTheme(final Context context, final SharedPreferences prefs) {
|
||||
// todo: night mode can be unspecified -> maybe need to adjust for correct behavior on some devices?
|
||||
final boolean isNight = (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
|
||||
final String themeColors = (isNight && prefs.getBoolean(Settings.PREF_THEME_DAY_NIGHT, context.getResources().getBoolean(R.bool.day_night_default)))
|
||||
final boolean isNight = ResourceUtils.isNight(context.getResources());
|
||||
final String themeColors = (isNight && prefs.getBoolean(PREF_THEME_DAY_NIGHT, context.getResources().getBoolean(R.bool.day_night_default)))
|
||||
? prefs.getString(Settings.PREF_THEME_VARIANT_NIGHT, KeyboardTheme.THEME_DARKER)
|
||||
: prefs.getString(Settings.PREF_THEME_VARIANT, KeyboardTheme.THEME_LIGHT);
|
||||
final String themeStyle = prefs.getString(Settings.PREF_THEME_STYLE, KeyboardTheme.THEME_STYLE_MATERIAL);
|
||||
|
@ -542,4 +544,58 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
|||
return KeyboardTheme.getThemeColors(themeColors, themeStyle, context, prefs);
|
||||
}
|
||||
|
||||
public static int readUserColor(final SharedPreferences prefs, final Context context, final String colorName, final boolean isNight) {
|
||||
final String pref = getColorPref(colorName, isNight);
|
||||
if (prefs.getBoolean(pref + PREF_AUTO_USER_COLOR_SUFFIX, true)) {
|
||||
return determineAutoColor(prefs, context, colorName, isNight);
|
||||
}
|
||||
if (prefs.contains(pref))
|
||||
return prefs.getInt(pref, Color.GRAY);
|
||||
else return determineAutoColor(prefs, context, colorName, isNight);
|
||||
}
|
||||
|
||||
public static String getColorPref(final String color, final boolean isNight) {
|
||||
return (isNight ? PREF_THEME_USER_COLOR_NIGHT_PREFIX : PREF_THEME_USER_COLOR_PREFIX) + color;
|
||||
}
|
||||
|
||||
private static int determineAutoColor(final SharedPreferences prefs, final Context context, final String color, final boolean isNight) {
|
||||
switch (color) {
|
||||
case PREF_COLOR_ACCENT_SUFFIX:
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
||||
// try determining accent color on Android 10 & 11, accent is not available in resources
|
||||
// todo: test whether this actually works
|
||||
final Context wrapper = new ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault);
|
||||
final TypedValue value = new TypedValue();
|
||||
if (wrapper.getTheme().resolveAttribute(android.R.attr.colorAccent, value, true))
|
||||
return value.data;
|
||||
}
|
||||
return ContextCompat.getColor(getDayNightContext(context, isNight), R.color.accent);
|
||||
case PREF_COLOR_TEXT_SUFFIX:
|
||||
// base it on background color, and not key, because it's also used for suggestions
|
||||
if (ColorUtilKt.isBrightColor(readUserColor(prefs, context, PREF_COLOR_BACKGROUND_SUFFIX, isNight))) return Color.BLACK;
|
||||
else return Color.WHITE;
|
||||
case PREF_COLOR_HINT_TEXT_SUFFIX:
|
||||
if (ColorUtilKt.isBrightColor(readUserColor(prefs, context, PREF_COLOR_KEYS_SUFFIX, isNight))) return Color.DKGRAY;
|
||||
else return Color.LTGRAY;
|
||||
case PREF_COLOR_KEYS_SUFFIX:
|
||||
return ColorUtilKt.brightenOrDarken(readUserColor(prefs, context, PREF_COLOR_BACKGROUND_SUFFIX, isNight), isNight);
|
||||
case PREF_COLOR_BACKGROUND_SUFFIX:
|
||||
default:
|
||||
return ContextCompat.getColor(getDayNightContext(context, isNight), R.color.keyboard_background);
|
||||
}
|
||||
}
|
||||
|
||||
public static Context getDayNightContext(final Context context, final boolean wantNight) {
|
||||
final boolean isNight = (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
|
||||
if (isNight == wantNight)
|
||||
return context;
|
||||
final Configuration config = new Configuration(context.getResources().getConfiguration());
|
||||
final int night = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
final int uiModeWithNightBitsZero = config.uiMode - night;
|
||||
config.uiMode = uiModeWithNightBitsZero + (wantNight ? Configuration.UI_MODE_NIGHT_YES : Configuration.UI_MODE_NIGHT_NO);
|
||||
final ContextThemeWrapper wrapper = new ContextThemeWrapper(context, R.style.platformActivityTheme);
|
||||
wrapper.applyOverrideConfiguration(config);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.dslul.openboard.inputmethod.latin.utils;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Build;
|
||||
|
@ -298,4 +299,9 @@ public final class ResourceUtils {
|
|||
public static boolean isStringValue(final TypedValue v) {
|
||||
return v.type == TypedValue.TYPE_STRING;
|
||||
}
|
||||
|
||||
public static boolean isNight(final Resources res) {
|
||||
// todo: night mode can be unspecified -> maybe need to adjust for correct behavior on some devices?
|
||||
return (res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue