update themes to work with the new base theme

slight adjustments to base theme to work around some strange issues
start replacing old themes with color variants of the base theme
This commit is contained in:
Helium314 2023-07-30 08:34:29 +02:00
parent d04b8a8ca7
commit 9d8571db0f
34 changed files with 285 additions and 167 deletions

View file

@ -1137,10 +1137,6 @@ public class Key implements Comparable<Key> {
}
}
public boolean isPressed() {
return mPressed;
}
public boolean isFunctional() {
return mBackgroundType == BACKGROUND_TYPE_FUNCTIONAL
|| mBackgroundType == BACKGROUND_TYPE_STICKY_OFF

View file

@ -18,11 +18,16 @@ package org.dslul.openboard.inputmethod.keyboard;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.util.Log;
import androidx.core.content.ContextCompat;
import org.dslul.openboard.inputmethod.latin.R;
import org.dslul.openboard.inputmethod.latin.common.Colors;
import org.dslul.openboard.inputmethod.latin.settings.Settings;
import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils;
import java.util.Arrays;
@ -48,6 +53,8 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
new String[] {THEME_VARIANT_LIGHT, THEME_VARIANT_DARK, THEME_VARIANT_CUSTOM});
THEME_VARIANTS.put(THEME_FAMILY_HOLO,
new String[] {THEME_VARIANT_WHITE, THEME_VARIANT_BLUE, THEME_VARIANT_HOLO_USER});
THEME_VARIANTS.put(THEME_FAMILY_HOLO,
new String[] {THEME_VARIANT_WHITE, THEME_VARIANT_BLUE, THEME_VARIANT_HOLO_USER});
}
private static final String TAG = KeyboardTheme.class.getSimpleName();
@ -347,4 +354,63 @@ public final class KeyboardTheme implements Comparable<KeyboardTheme> {
if (keyBorders) return THEME_ID_LXX_LIGHT_BORDER;
return THEME_ID_LXX_LIGHT;
}
public static final String THEME_LIGHT = "light";
public static final String THEME_DARK = "dark";
public static final String THEME_DARKER = "darker";
public static final String THEME_BLACK = "black";
public static final String THEME_USER = "user";
public static Colors getCustomTheme(String theme, Context context, SharedPreferences prefs) {
switch (theme) {
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);
return new Colors(accent, background, keyBgColor, Colors.darken(keyBgColor), keyBgColor, keyTextColor, hintTextColor);
case THEME_DARK:
return new Colors(
ContextCompat.getColor(context, R.color.gesture_trail_color_lxx_dark),
Color.parseColor("#263238"),
Color.parseColor("#364248"),
Color.parseColor("#2d393f"),
Color.parseColor("#364248"),
ContextCompat.getColor(context, R.color.key_text_color_lxx_dark),
ContextCompat.getColor(context, R.color.key_hint_letter_color_lxx_dark)
);
case THEME_DARKER:
return new Colors(
ContextCompat.getColor(context, R.color.gesture_trail_color_lxx_dark),
ContextCompat.getColor(context, R.color.keyboard_background_lxx_dark_border),
ContextCompat.getColor(context, R.color.key_background_normal_lxx_dark_border),
ContextCompat.getColor(context, R.color.key_background_functional_lxx_dark_border),
ContextCompat.getColor(context, R.color.key_background_normal_lxx_dark_border),
ContextCompat.getColor(context, R.color.key_text_color_lxx_dark),
ContextCompat.getColor(context, R.color.key_hint_letter_color_lxx_dark)
);
case THEME_BLACK:
return new Colors(
ContextCompat.getColor(context, R.color.gesture_trail_color_lxx_dark),
ContextCompat.getColor(context, R.color.background_amoled_black),
ContextCompat.getColor(context, R.color.background_amoled_dark),
ContextCompat.getColor(context, R.color.background_amoled_dark),
ContextCompat.getColor(context, R.color.background_amoled_dark),
ContextCompat.getColor(context, R.color.key_text_color_lxx_dark),
ContextCompat.getColor(context, R.color.key_hint_letter_color_lxx_dark)
);
case THEME_LIGHT:
default:
return new Colors(
ContextCompat.getColor(context, R.color.gesture_trail_color_lxx_light),
ContextCompat.getColor(context, R.color.keyboard_background_lxx_light_border),
ContextCompat.getColor(context, R.color.key_background_normal_lxx_light_border),
ContextCompat.getColor(context, R.color.key_background_functional_lxx_light_border),
ContextCompat.getColor(context, R.color.key_background_normal_lxx_light_border),
ContextCompat.getColor(context, R.color.key_text_color_lxx_light),
ContextCompat.getColor(context, R.color.key_hint_letter_color_lxx_light)
);
}
}
}

View file

@ -31,6 +31,7 @@ import android.graphics.drawable.NinePatchDrawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import androidx.core.graphics.drawable.DrawableCompat;
import org.dslul.openboard.inputmethod.keyboard.internal.KeyDrawParams;
import org.dslul.openboard.inputmethod.keyboard.internal.KeyVisualAttributes;
@ -171,8 +172,12 @@ public class KeyboardView extends View {
mPaint.setAntiAlias(true);
mColors = Settings.getInstance().getCurrent().mColors;
if (mColors.isCustom)
if (mColors.isCustom) {
DrawableCompat.setTintMode(mKeyBackground, PorterDuff.Mode.MULTIPLY);
DrawableCompat.setTintMode(mSpacebarBackground, PorterDuff.Mode.MULTIPLY);
DrawableCompat.setTintMode(mFunctionalKeyBackground, PorterDuff.Mode.MULTIPLY);
getBackground().setColorFilter(mColors.backgroundFilter);
}
}
@Nullable
@ -625,38 +630,21 @@ public class KeyboardView extends View {
}
private void setCustomKeyBackgroundColor(Key key, Keyboard keyboard, Drawable background) {
// color filter is applied to background, which is re-used
// action key and normal key share the same background drawable, so we need to select the correct color filter
// colors are applied to background, which is re-used
// action key and normal key share the same background drawable, so we need to select the correct colors
if (isAccentColoredKey(key)) { // action key and its popup keys
if (key.isPressed())
background.setColorFilter(mColors.accentPressedColorFilter);
else
background.setColorFilter(mColors.accentColorFilter);
DrawableCompat.setTintList(background, mColors.actionKeyStateList);
} else if (key.getBackgroundType() == Key.BACKGROUND_TYPE_SPACEBAR) { // space
if (key.isPressed())
background.setColorFilter(mColors.spaceBarPressedFilter);
else
background.setColorFilter(mColors.spaceBarFilter);
DrawableCompat.setTintList(background, mColors.spaceBarStateList);
} else if (key.isFunctional()) { // shift, 123, delete,...
if (key.isPressed())
background.setColorFilter(mColors.functionalKeyPressedBackgroundFilter);
else
background.setColorFilter(mColors.functionalKeyBackgroundFilter);
DrawableCompat.setTintList(background, mColors.functionalKeyStateList);
} else if (this.getClass() == MoreKeysKeyboardView.class) { // more keys popup (except on action key, which is handled above)
if (key.isPressed())
background.setColorFilter(mColors.backgroundPressedFilter);
else
background.setColorFilter(mColors.backgroundFilter);
DrawableCompat.setTintList(background, mColors.backgroundStateList);
} else if (key.getBackgroundType() == Key.BACKGROUND_TYPE_NORMAL) { // normal keys
if (key.isPressed())
background.setColorFilter(mColors.keyPressedBackgroundFilter);
else
background.setColorFilter(mColors.keyBackgroundFilter);
DrawableCompat.setTintList(background, mColors.keyStateList);
} else if (keyboard.mId.mElementId >= 10 && keyboard.mId.mElementId <= 26) { // emoji keyboard keys
if (key.isPressed())
background.setColorFilter(mColors.backgroundPressedFilter);
else
background.setColorFilter(mColors.backgroundFilter);
DrawableCompat.setTintList(background, mColors.backgroundStateList);
}
}

View file

@ -1,6 +1,6 @@
package org.dslul.openboard.inputmethod.keyboard.clipboard
import android.graphics.ColorFilter
import android.graphics.PorterDuff
import android.graphics.Typeface
import android.util.TypedValue
import android.view.LayoutInflater
@ -9,6 +9,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.graphics.drawable.DrawableCompat
import androidx.recyclerview.widget.RecyclerView
import org.dslul.openboard.inputmethod.latin.ClipboardHistoryEntry
import org.dslul.openboard.inputmethod.latin.ClipboardHistoryManager
@ -24,7 +25,6 @@ class ClipboardAdapter(
var pinnedIconResId = 0
var itemBackgroundId = 0
var itemBackgroundColorFilter: ColorFilter? = null
var itemTypeFace: Typeface? = null
var itemTextColor = 0
var itemTextSize = 0f
@ -56,7 +56,11 @@ class ClipboardAdapter(
setOnTouchListener(this@ViewHolder)
setOnLongClickListener(this@ViewHolder)
setBackgroundResource(itemBackgroundId)
background.colorFilter = itemBackgroundColorFilter
val colors = Settings.getInstance().current.mColors
if (colors.isCustom) {
DrawableCompat.setTintList(background, colors.keyStateList)
DrawableCompat.setTintMode(background, PorterDuff.Mode.MULTIPLY)
}
}
pinnedIconView = view.findViewById<ImageView>(R.id.clipboard_entry_pinned_icon).apply {
visibility = View.GONE
@ -78,11 +82,8 @@ class ClipboardAdapter(
override fun onTouch(view: View, event: MotionEvent): Boolean {
if (event.actionMasked != MotionEvent.ACTION_DOWN) {
if (event.actionMasked == MotionEvent.ACTION_UP)
view.background.colorFilter = Settings.getInstance().current.mColors.keyBackgroundFilter
return false
}
view.background.colorFilter = Settings.getInstance().current.mColors.keyPressedBackgroundFilter
keyEventListener.onKeyDown(view.tag as Long)
return false
}

View file

@ -9,6 +9,7 @@ import android.widget.FrameLayout
import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.graphics.drawable.DrawableCompat
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import org.dslul.openboard.inputmethod.keyboard.KeyboardActionListener
import org.dslul.openboard.inputmethod.keyboard.internal.KeyDrawParams
@ -114,9 +115,10 @@ class ClipboardHistoryView @JvmOverloads constructor(
text = label
typeface = params.mTypeface
val colors = Settings.getInstance().current.mColors
if (colors.isCustom)
if (colors.isCustom) {
setTextColor(colors.keyText)
else
DrawableCompat.setTintList(this.background, colors.functionalKeyStateList)
} else
setTextColor(params.mFunctionalTextColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mLabelSize.toFloat())
}
@ -127,11 +129,10 @@ class ClipboardHistoryView @JvmOverloads constructor(
itemBackgroundId = keyBackgroundId
itemTypeFace = params.mTypeface
val colors = Settings.getInstance().current.mColors
if (colors.isCustom) {
itemTextColor = colors.keyText
itemBackgroundColorFilter = colors.keyBackgroundFilter
} else
itemTextColor = params.mTextColor
itemTextColor = if (colors.isCustom)
colors.keyText
else
params.mTextColor
itemTextSize = params.mLabelSize.toFloat()
}
}
@ -183,18 +184,12 @@ class ClipboardHistoryView @JvmOverloads constructor(
override fun onTouch(view: View, event: MotionEvent): Boolean {
if (event.actionMasked != MotionEvent.ACTION_DOWN) {
if (view == alphabetKey && event.actionMasked != MotionEvent.ACTION_UP)
alphabetKey.background.colorFilter = Settings.getInstance().current.mColors.functionalKeyBackgroundFilter
return false
}
when (view) {
alphabetKey -> {
alphabetKey.background.colorFilter = Settings.getInstance().current.mColors.functionalKeyPressedBackgroundFilter
keyboardActionListener?.onPressKey(
alphabetKey -> keyboardActionListener?.onPressKey(
Constants.CODE_ALPHA_FROM_CLIPBOARD, 0 /* repeatCount */,
true /* isSinglePointer */)
}
clearKey -> keyboardActionListener?.onPressKey(
Constants.CODE_UNSPECIFIED, 0 /* repeatCount */,
true /* isSinglePointer */)

View file

@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
@ -34,6 +35,7 @@ import android.widget.TabWidget;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.dslul.openboard.inputmethod.compat.TabHostCompat;
@ -55,9 +57,6 @@ import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
import org.jetbrains.annotations.NotNull;
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_ALPHA_FROM_EMOJI;
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_DELETE;
import static org.dslul.openboard.inputmethod.latin.common.Constants.CODE_SPACE;
import static org.dslul.openboard.inputmethod.latin.common.Constants.NOT_A_COORDINATE;
/**
@ -274,12 +273,15 @@ public final class EmojiPalettesView extends LinearLayout
mSpacebar.setOnClickListener(this);
final Colors colors = Settings.getInstance().getCurrent().mColors;
if (colors.isCustom) {
mAlphabetKeyLeft.getBackground().setColorFilter(colors.functionalKeyBackgroundFilter);
mSpacebar.getBackground().setColorFilter(colors.spaceBarFilter);
mDeleteKey.getBackground().setColorFilter(colors.functionalKeyBackgroundFilter);
DrawableCompat.setTintList(mAlphabetKeyLeft.getBackground(), colors.functionalKeyStateList);
DrawableCompat.setTintList(mSpacebar.getBackground(), colors.spaceBarStateList);
DrawableCompat.setTintList(mDeleteKey.getBackground(), colors.functionalKeyStateList);
DrawableCompat.setTintMode(mAlphabetKeyLeft.getBackground(), PorterDuff.Mode.MULTIPLY);
DrawableCompat.setTintMode(mSpacebar.getBackground(), PorterDuff.Mode.MULTIPLY);
DrawableCompat.setTintMode(mDeleteKey.getBackground(), PorterDuff.Mode.MULTIPLY);
getBackground().setColorFilter(colors.backgroundFilter);
mEmojiCategoryPageIndicatorView.setColors(colors.accent, colors.background);
findViewById(R.id.emoji_tab_strip).getBackground().setColorFilter(colors.backgroundFilter);
findViewById(R.id.emoji_tab_strip).getBackground().setColorFilter(colors.adjustedBackgroundFilter);
}
mEmojiLayoutParams.setKeyProperties(mSpacebar);
mSpacebarIcon = findViewById(R.id.emoji_keyboard_space_icon);
@ -307,7 +309,8 @@ public final class EmojiPalettesView extends LinearLayout
if (mCurrentTab != null)
mCurrentTab.setColorFilter(colors.keyTextFilter);
mCurrentTab = (ImageView) mTabHost.getCurrentTabView();
mCurrentTab.setColorFilter(colors.accentColorFilter);
// mCurrentTab.setColorFilter(colors.accentColorFilter); // todo (later): doesn't work properly, because enabled drawable is blue -> adjust
mCurrentTab.setColorFilter(colors.accent);
}
}
@ -320,20 +323,7 @@ public final class EmojiPalettesView extends LinearLayout
*/
@Override
public boolean onTouch(final View v, final MotionEvent event) {
final int eventCode = event.getActionMasked();
if (eventCode != MotionEvent.ACTION_DOWN) {
if (eventCode == MotionEvent.ACTION_UP) {
final Object tag = v.getTag();
if (!(tag instanceof Integer))
return false;
final int code = (Integer) tag;
if (code == CODE_SPACE)
v.getBackground().setColorFilter(Settings.getInstance().getCurrent().mColors.spaceBarFilter);
else if (code == CODE_DELETE)
v.getBackground().setColorFilter(Settings.getInstance().getCurrent().mColors.functionalKeyBackgroundFilter);
else if (code == CODE_ALPHA_FROM_EMOJI)
v.getBackground().setColorFilter(Settings.getInstance().getCurrent().mColors.functionalKeyBackgroundFilter);
}
if (event.getActionMasked() != MotionEvent.ACTION_DOWN) {
return false;
}
final Object tag = v.getTag();
@ -341,12 +331,6 @@ public final class EmojiPalettesView extends LinearLayout
return false;
}
final int code = (Integer) tag;
if (code == CODE_SPACE)
v.getBackground().setColorFilter(Settings.getInstance().getCurrent().mColors.spaceBarPressedFilter);
else if (code == CODE_DELETE)
v.getBackground().setColorFilter(Settings.getInstance().getCurrent().mColors.functionalKeyPressedBackgroundFilter);
else if (code == CODE_ALPHA_FROM_EMOJI)
v.getBackground().setColorFilter(Settings.getInstance().getCurrent().mColors.functionalKeyPressedBackgroundFilter);
mKeyboardActionListener.onPressKey(
code, 0 /* repeatCount */, true /* isSinglePointer */);
// It's important to return false here. Otherwise, {@link #onClick} and touch-down visual

View file

@ -1,5 +1,6 @@
package org.dslul.openboard.inputmethod.latin.common;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.ColorFilter;
@ -12,7 +13,7 @@ import org.dslul.openboard.inputmethod.keyboard.KeyboardTheme;
public class Colors {
public final boolean isCustom; // todo: could be removed?
public final boolean isCustom;
public final int navBar;
public final int accent;
public final int background;
@ -21,32 +22,37 @@ public class Colors {
public final int spaceBar;
public final int keyText;
public final int keyHintText;
// todo: evaluate which colors, colorFilters and colorStateLists area actually necessary
public ColorFilter backgroundFilter;
public ColorFilter backgroundPressedFilter;
public ColorFilter adjustedBackgroundFilter;
public ColorFilter keyBackgroundFilter;
public ColorFilter keyPressedBackgroundFilter;
public ColorFilter functionalKeyBackgroundFilter;
public ColorFilter functionalKeyPressedBackgroundFilter;
public ColorFilter spaceBarFilter;
public ColorFilter spaceBarPressedFilter;
public ColorFilter keyTextFilter; // todo: really necessary?
public ColorFilter keyHintTextFilter; // todo: really? color alone should be sufficient i think... test!
public ColorFilter accentColorFilter; // todo: really necessary?
public ColorFilter accentPressedColorFilter;
public ColorFilter keyTextFilter;
public ColorFilter accentColorFilter;
public ColorFilter actionKeyIconColorFilter;
public Colors(int acc, int bg, int k, int fun, int space, int kt, int kht) {
public ColorStateList backgroundStateList;
public ColorStateList keyStateList;
public ColorStateList functionalKeyStateList;
public ColorStateList actionKeyStateList;
public ColorStateList spaceBarStateList;
public ColorStateList adjustedBackgroundStateList; // todo (later): use in MoreKeys popup, without breaking when the selection has a radius set
public Colors(int _accent, int _background, int _keyBackground, int _functionalKey, int _spaceBar, int _keyText, int _keyHintText) {
isCustom = true;
accent = acc;
background = bg;
keyBackground = k;
functionalKey = fun;
spaceBar = space;
keyText = kt;
keyHintText = kht;
accent = _accent;
background = _background;
keyBackground = _keyBackground;
functionalKey = _functionalKey;
spaceBar = _spaceBar;
keyText = _keyText;
keyHintText = _keyHintText;
navBar = background;
}
// todo (later): remove this and isCustom, once the old themes can be completely replaced
public Colors(int themeId, int nightModeFlags) {
isCustom = false;
if (KeyboardTheme.getIsDayNight(themeId)) {
@ -74,42 +80,45 @@ public class Colors {
}
public void createColorFilters(final boolean hasKeyBorders) {
final int[][] states = new int[][] {
// new int[] { android.R.attr.state_checked}, // checked -> todo: when is this happening? there are more states, but when are they used?
new int[] { android.R.attr.state_pressed}, // pressed
new int[] { -android.R.attr.state_pressed}, // not pressed
};
backgroundFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(background, BlendModeCompat.MODULATE);
backgroundPressedFilter = isDarkColor(background)
// todo: below is not working, but why?
// ? BlendModeColorFilterCompat.createBlendModeColorFilterCompat(ColorUtils.blendARGB(background, Color.WHITE, 0.1f), BlendModeCompat.MODULATE)
? BlendModeColorFilterCompat.createBlendModeColorFilterCompat(background, BlendModeCompat.SCREEN)
: backgroundFilter;
// todo: use adjusted? or is this just for space bar in no border theme?
// maybe for morekeys popup, but then need to set background color there too
final int adjustedBackground = brightenOrDarken(background, true);
adjustedBackgroundStateList = new ColorStateList(states, new int[] { brightenOrDarken(adjustedBackground, true), adjustedBackground });
adjustedBackgroundFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(adjustedBackground, BlendModeCompat.MODULATE);
// todo (later): for bright colors there often is no need for 2 states, could just have one (because keys will darken anyway) -> test!
if (hasKeyBorders) {
keyBackgroundFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(keyBackground, BlendModeCompat.MODULATE);
functionalKeyBackgroundFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(functionalKey, BlendModeCompat.MODULATE);
spaceBarFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(spaceBar, BlendModeCompat.MODULATE);
keyPressedBackgroundFilter = isDarkColor(keyBackground)
? BlendModeColorFilterCompat.createBlendModeColorFilterCompat(ColorUtils.blendARGB(keyBackground, Color.WHITE, 0.1f), BlendModeCompat.MODULATE)
: keyBackgroundFilter;
functionalKeyPressedBackgroundFilter = isDarkColor(functionalKey)
? BlendModeColorFilterCompat.createBlendModeColorFilterCompat(ColorUtils.blendARGB(functionalKey, Color.WHITE, 0.1f), BlendModeCompat.MODULATE)
: functionalKeyBackgroundFilter;
spaceBarPressedFilter = isDarkColor(spaceBar)
? BlendModeColorFilterCompat.createBlendModeColorFilterCompat(ColorUtils.blendARGB(spaceBar, Color.WHITE, 0.1f), BlendModeCompat.MODULATE)
: spaceBarFilter;
backgroundStateList = new ColorStateList(states, new int[] { brightenOrDarken(background, true), background });
keyStateList = new ColorStateList(states, new int[] { brightenOrDarken(keyBackground, true), keyBackground });
functionalKeyStateList = new ColorStateList(states, new int[] { brightenOrDarken(functionalKey, true), functionalKey });
actionKeyStateList = new ColorStateList(states, new int[] { brightenOrDarken(accent, true), accent });
spaceBarStateList = new ColorStateList(states, new int[] { brightenOrDarken(spaceBar, true), spaceBar });
} else {
// need to set color to background if key borders are disabled, or there will be ugly keys
keyBackgroundFilter = backgroundFilter;
functionalKeyBackgroundFilter = keyBackgroundFilter;
spaceBarFilter = keyBackgroundFilter;
keyPressedBackgroundFilter = backgroundPressedFilter;
functionalKeyPressedBackgroundFilter = keyBackgroundFilter;
spaceBarPressedFilter = keyBackgroundFilter;
backgroundStateList = new ColorStateList(states, new int[] { brightenOrDarken(background, true), background });
keyStateList = backgroundStateList;
functionalKeyStateList = backgroundStateList;
actionKeyStateList = new ColorStateList(states, new int[] { brightenOrDarken(accent, true), accent });
spaceBarStateList = adjustedBackgroundStateList;
}
// todo: some of these should be modulate (once the base theme is done)
// especially the accent pressed filter should use modulate/screen
keyTextFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(keyText, BlendModeCompat.SRC_ATOP);
keyHintTextFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(keyHintText, BlendModeCompat.SRC_ATOP);
accentColorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(accent, BlendModeCompat.SRC_ATOP);
accentPressedColorFilter = isDarkColor(accent)
? BlendModeColorFilterCompat.createBlendModeColorFilterCompat(ColorUtils.blendARGB(accent, Color.WHITE, 0.1f), BlendModeCompat.SRC_ATOP)
: BlendModeColorFilterCompat.createBlendModeColorFilterCompat(ColorUtils.blendARGB(accent, Color.BLACK, 0.1f), BlendModeCompat.SRC_ATOP);
accentColorFilter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(accent, BlendModeCompat.MODULATE);
actionKeyIconColorFilter = isBrightColor(accent) // the white icon may not have enough contrast, and can't be adjusted by the user
? BlendModeColorFilterCompat.createBlendModeColorFilterCompat(Color.DKGRAY, BlendModeCompat.SRC_ATOP)
: null;
@ -126,6 +135,7 @@ public class Colors {
return brightnessSquared >= 210*210;
}
// todo (later): what needs to be public?
public static boolean isDarkColor(int color) {
if (android.R.color.transparent == color) {
return true;
@ -136,4 +146,19 @@ public class Colors {
int brightnessSquared = (int) (rgb[0] * rgb[0] * .241 + rgb[1] * rgb[1] * .691 + rgb[2] * rgb[2] * .068);
return brightnessSquared < 50*50;
}
public static int brightenOrDarken(final int color, final boolean preferDarken) {
if (preferDarken) {
if (isDarkColor(color)) return brighten(color);
else return darken(color);
} else if (isBrightColor(color)) return darken(color);
else return brighten(color);
}
public static int brighten(final int color) {
return ColorUtils.blendARGB(color, Color.WHITE, 0.2f); // brighten is stronger, because often the drawables get darker when pressed
}
public static int darken(final int color) {
return ColorUtils.blendARGB(color, Color.BLACK, 0.1f);
}
}

View file

@ -22,6 +22,7 @@ import android.os.Bundle
import android.preference.ListPreference
import android.preference.Preference
import android.preference.TwoStatePreference
import androidx.core.content.edit
import org.dslul.openboard.inputmethod.keyboard.KeyboardSwitcher
import org.dslul.openboard.inputmethod.keyboard.KeyboardTheme
import org.dslul.openboard.inputmethod.latin.R
@ -32,6 +33,7 @@ import java.util.*
/**
* "Appearance" settings sub screen.
*/
@Suppress("Deprecation") // yes everything here is deprecated, but only work on this if really necessary
class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceChangeListener {
private var selectedThemeId = 0
@ -39,6 +41,7 @@ class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceC
private lateinit var themeFamilyPref: ListPreference
private lateinit var themeVariantPref: ListPreference
private lateinit var customThemeVariantPref: ListPreference
private lateinit var keyBordersPref: TwoStatePreference
private lateinit var amoledModePref: TwoStatePreference
private var dayNightPref: TwoStatePreference? = null
@ -55,6 +58,7 @@ class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceC
removePreference(Settings.PREF_THEME_DAY_NIGHT)
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
// todo: consider removing the preference, and always set the navbar color
removePreference(Settings.PREF_NAVBAR_COLOR)
}
setupTheme()
@ -120,6 +124,25 @@ class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceC
isEnabled = isLegacyFamily || !KeyboardTheme.getIsDayNight(selectedThemeId)
}
}
customThemeVariantPref.apply {
val variant = sharedPreferences.getString(Settings.PREF_CUSTOM_THEME_VARIANT, KeyboardTheme.THEME_LIGHT)
// todo: some way of following system, with setting a dark and a light theme
// check whether night mode is active using context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK
// this is needed so the auto-theme can be replaced
// idea: add a "dark theme variant" preference when auto-switch is on
// todo (later): material you, system accent, ...
// todo (idea): re-work setting to actually see preview of theme colors... but that's a lot of work
val variants = arrayOf(KeyboardTheme.THEME_LIGHT, KeyboardTheme.THEME_DARK, KeyboardTheme.THEME_DARKER, KeyboardTheme.THEME_BLACK, KeyboardTheme.THEME_USER)
entries = variants.map {
val resId = resources.getIdentifier("theme_name_$it", "string", activity.packageName)
if (resId == 0) it else getString(resId)
}.toTypedArray()
entryValues = variants
value = variant
val resId = resources.getIdentifier("theme_name_$variant", "string", activity.packageName)
summary = if (resId == 0) variant else getString(resId)
isEnabled = true
}
keyBordersPref.apply {
isEnabled = !isLegacyFamily && !KeyboardTheme.getIsAmoledMode(selectedThemeId)
isChecked = isLegacyFamily || KeyboardTheme.getHasKeyBorders(selectedThemeId)
@ -135,7 +158,7 @@ class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceC
isChecked = !isLegacyFamily && !KeyboardTheme.getIsCustom(selectedThemeId) && KeyboardTheme.getIsDayNight(selectedThemeId)
}
userColorsPref.apply {
isEnabled = KeyboardTheme.getIsCustom(selectedThemeId)
isEnabled = KeyboardTheme.getIsCustom(selectedThemeId) && sharedPreferences.getString(Settings.PREF_CUSTOM_THEME_VARIANT, KeyboardTheme.THEME_LIGHT) == KeyboardTheme.THEME_USER
}
}
@ -153,6 +176,7 @@ class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceC
}
themeVariantPref = preferenceScreen.findPreference(Settings.PREF_THEME_VARIANT) as ListPreference
themeVariantPref.apply {
title = "$title old (to be removed)" // todo: remove, this is just a workaround while there are still 2 ways of selecting variant
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, value ->
summary = entries[entryValues.indexOfFirst { it == value }]
saveSelectedThemeId(variant = value as String)
@ -178,6 +202,29 @@ class AppearanceSettingsFragment : SubScreenFragment(), Preference.OnPreferenceC
updateThemePreferencesState(skipThemeFamily = true)
true
}
customThemeVariantPref = preferenceScreen.findPreference(Settings.PREF_CUSTOM_THEME_VARIANT) as ListPreference
customThemeVariantPref.apply {
title = "$title new" // todo: remove, this is just a workaround while there are still 2 ways of selecting variant
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, value ->
// not so nice workaround, could be removed in the necessary re-work: new value seems
// to be stored only after this method call, but we update the summary and user-defined color enablement in here -> store it now
if (value == sharedPreferences.getString(Settings.PREF_CUSTOM_THEME_VARIANT, KeyboardTheme.THEME_LIGHT))
return@OnPreferenceChangeListener true // avoid infinite loop
sharedPreferences.edit { putString(Settings.PREF_CUSTOM_THEME_VARIANT, value as String) }
summary = entries[entryValues.indexOfFirst { it == value }]
needsReload = true
// always switch to user-defined theme variant
val themeFamily = KeyboardTheme.getThemeFamily(selectedThemeId)
val variants = KeyboardTheme.THEME_VARIANTS[themeFamily]!!
val userVariant = variants.first { it.contains("user", true) }
saveSelectedThemeId(variant = userVariant as String)
updateThemePreferencesState(skipThemeFamily = true)
true
}
}
userColorsPref = preferenceScreen.findPreference(Settings.PREF_THEME_USER)
userColorsPref.onPreferenceClickListener = Preference.OnPreferenceClickListener { _ ->
val items = listOf(R.string.select_color_background, R.string.select_color_key, R.string.select_color_key_hint, R.string.select_color_accent, R.string.select_color_key_background)

View file

@ -27,6 +27,9 @@ import android.os.Build;
import android.util.Log;
import android.view.Gravity;
import androidx.core.content.ContextCompat;
import org.dslul.openboard.inputmethod.keyboard.KeyboardTheme;
import org.dslul.openboard.inputmethod.latin.AudioAndHapticFeedbackManager;
import org.dslul.openboard.inputmethod.latin.InputAttributes;
@ -48,7 +51,6 @@ import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = Settings.class.getSimpleName();
@ -63,6 +65,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_POPUP_ON = "popup_on";
public static final String PREF_THEME_FAMILY = "theme_family";
public static final String PREF_THEME_VARIANT = "theme_variant";
public static final String PREF_CUSTOM_THEME_VARIANT = "custom_theme_variant";
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_AMOLED_MODE = "theme_amoled_mode";
@ -544,7 +547,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
return null;
}
public static Colors getColors(final Configuration configuration, final SharedPreferences prefs) {
public static Colors getColors(final Context context, final SharedPreferences prefs) {
final int keyboardThemeId = KeyboardTheme.getThemeForParameters(
prefs.getString(Settings.PREF_THEME_FAMILY, ""),
prefs.getString(Settings.PREF_THEME_VARIANT, ""),
@ -553,16 +556,9 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
prefs.getBoolean(Settings.PREF_THEME_AMOLED_MODE, false)
);
if (!KeyboardTheme.getIsCustom(keyboardThemeId))
return new Colors(keyboardThemeId, configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK);
return new Colors(keyboardThemeId, context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK);
// we have a custom theme, which is user only (at the moment)
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);
return new Colors(accent, background, keyBgColor, keyBgColor, keyBgColor, keyTextColor, hintTextColor);
return KeyboardTheme.getCustomTheme(prefs.getString(Settings.PREF_CUSTOM_THEME_VARIANT, KeyboardTheme.THEME_LIGHT), context, prefs);
}
}

View file

@ -256,7 +256,7 @@ public class SettingsValues {
mOneHandedModeGravity = Settings.readOneHandedModeGravity(prefs);
mSecondaryLocale = Settings.getSecondaryLocale(prefs, RichInputMethodManager.getInstance().getCurrentSubtypeLocale().toString());
mColors = Settings.getColors(context.getResources().getConfiguration(), prefs);
mColors = Settings.getColors(context, prefs);
mColors.createColorFilters(prefs.getBoolean(Settings.PREF_THEME_KEY_BORDERS, false));
mAddToPersonalDictionary = prefs.getBoolean(Settings.PREF_ADD_TO_PERSONAL_DICTIONARY, false);

View file

@ -184,7 +184,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
final Colors colors = Settings.getInstance().getCurrent().mColors;
if (colors.isCustom) {
mStripVisibilityGroup.mSuggestionStripView.getBackground().setColorFilter(colors.backgroundFilter);
mStripVisibilityGroup.mSuggestionStripView.getBackground().setColorFilter(colors.adjustedBackgroundFilter);
mClipboardKey.setColorFilter(colors.keyText);
} else mClipboardKey.clearColorFilter();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -22,14 +22,14 @@
android:drawable="@drawable/btn_keyboard_key_action_normal_lxx_base" />
<!-- Toggle keys. Use checkable/checked state. -->
<item android:state_checkable="true" android:state_checked="true" android:state_pressed="true"
android:drawable="@color/key_background_pressed_lxx_base" />
<item android:state_checkable="true" android:state_pressed="true"
android:drawable="@color/key_background_lxx_base" />
<item android:state_checkable="true" android:state_checked="true"
android:drawable="@color/key_background_pressed_lxx_base" />
<item android:state_checkable="true"
android:drawable="@color/key_background_lxx_base" />
<item android:state_checkable="true" android:state_checked="true" android:state_pressed="true"
android:drawable="@color/key_background_pressed_lxx_base" />
<item android:state_checkable="true" android:state_pressed="true"
android:drawable="@color/key_background_lxx_base" />
<item android:state_checkable="true" android:state_checked="true"
android:drawable="@color/key_background_pressed_lxx_base" />
<item android:state_checkable="true"
android:drawable="@color/key_background_lxx_base" />
<!-- Empty background keys. -->
<item android:state_empty="true" android:state_pressed="true"

View file

@ -15,7 +15,10 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/btn_keyboard_key_popup_selected_lxx_base" />
<item android:drawable="@android:color/transparent" />
<item android:state_pressed="true" >
<shape android:shape="rectangle">
<solid android:color="@color/key_background_normal_lxx_base_border" />
</shape>
</item>
<item android:drawable="@android:color/white" />
</selector>

View file

@ -1,21 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 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.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/btn_keyboard_spacebar_pressed_lxx_base" />
<item android:drawable="@drawable/btn_keyboard_spacebar_normal_lxx_base" />
<!-- without this weirdly nested layer list the bottom/top things are ignored -->
<item android:state_pressed="true">
<layer-list>
<item android:bottom="12dp" android:top="12dp">
<shape android:shape="rectangle">
<solid android:color="@color/key_background_pressed_lxx_base" />
<corners android:radius="5dp" />
</shape>
</item>
</layer-list>
</item>
<item>
<layer-list>
<item android:bottom="12dp" android:top="12dp">
<shape android:shape="rectangle">
<solid android:color="@color/key_background_lxx_base" />
<corners android:radius="5dp" />
</shape>
</item>
</layer-list>
</item>
</selector>

View file

@ -116,7 +116,7 @@
<color name="morekey_normal_lxx_base">@android:color/white</color>
<color name="morekey_pressed_lxx_base">#F4F4F5</color>
<color name="suggested_word_background_selected_lxx_base">#F4F4F5</color>
<color name="emoji_tab_page_indicator_background_lxx_base">@android:color/white</color>
<color name="emoji_tab_page_indicator_background_lxx_base">#F4F4F5</color>
<!-- Color resources for LXX_Base_Border theme.
15%:0x26 70%:0xB3 75%:0xC0 80%:0xCC 85%:0xD9 90%:0xE6 -->
@ -125,7 +125,7 @@
<color name="key_background_pressed_lxx_base_border">#F4F4F5</color>
<color name="key_background_functional_lxx_base_border">@android:color/white</color>
<color name="key_bottom_bevel_lxx_base">#A9ABAD</color>
<color name="emoji_tab_page_indicator_background_lxx_base_border">@android:color/white</color>
<color name="emoji_tab_page_indicator_background_lxx_base_border">#F4F4F5</color>
<!-- Color resources for setup wizard and tutorial -->
<color name="setup_background">#FFEBEBEB</color>

View file

@ -646,6 +646,16 @@ disposition rather than other common dispositions for Latin languages. [CHAR LIM
<string name="amoled_mode_summary">Can reduce power usage depending on the devices screen technology</string>
<!-- Option for setting navbar to follow keyboard color -->
<string name="theme_navbar">Color navigation bar</string>
<!-- Theme name for light theme -->
<string name="theme_name_light">Light</string>
<!-- Theme name for dark theme (based on old no-border dark) -->
<string name="theme_name_dark">Dark</string>
<!-- Theme name for darker theme (based on old border dark), todo: re-consider that stupid name -->
<string name="theme_name_darker">Darker</string>
<!-- Theme name for black theme (based on old amoled black) -->
<string name="theme_name_black">Black</string>
<!-- Theme name for user-defined theme -->
<string name="theme_name_user">User-Defined</string>
<!-- Option for selecting custom theme colors -->
<string name="select_user_colors">Adjust theme colors</string>
<!-- Description for selection of user-defined colors. -->

View file

@ -3,7 +3,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="KeyboardTheme.LXX_Base_Border"
parent="KeyboardTheme.LXX_Base">
<item name="keyboardStyle">@style/Keyboard.LXX_Base_Border</item>
<item name="keyboardStyle">@style/Keyboard.LXX_Light_Border</item> <!-- todo: see comment for lxx-base, though here only the action key popup in search field is weird -->
<item name="keyboardViewStyle">@style/KeyboardView.LXX_Base_Border</item>
<item name="mainKeyboardViewStyle">@style/MainKeyboardView.LXX_Base_Border</item>
<item name="emojiPalettesViewStyle">@style/EmojiPalettesView.LXX_Base_Border</item>

View file

@ -3,7 +3,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="KeyboardTheme.LXX_Base" parent="KeyboardIcons.LXX_Light">
<item name="inputViewStyle">@style/InputView.LXX</item>
<item name="keyboardStyle">@style/Keyboard.LXX_Base</item>
<item name="keyboardStyle">@style/Keyboard.LXX_Light</item> <!-- todo: when using Keyboard.LXX_Base, the action key doesn't keep aspect ratio, and sometimes action more keys popup looks bad... wtf? -->
<item name="keyboardViewStyle">@style/KeyboardView.LXX_Base</item>
<item name="mainKeyboardViewStyle">@style/MainKeyboardView.LXX_Base</item>
<item name="emojiPalettesViewStyle">@style/EmojiPalettesView.LXX_Base</item>

View file

@ -31,6 +31,10 @@
android:key="theme_variant"
android:title="@string/theme_variant"/>
<ListPreference
android:key="custom_theme_variant"
android:title="@string/theme_variant"/>
<CheckBoxPreference
android:key="theme_key_borders"
android:title="@string/key_borders"/>