mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Create certain drawables during runtime for theming
This commit is contained in:
parent
039f9145c3
commit
5a4f42cafe
@ -30,10 +30,13 @@ import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.NinePatchDrawable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.View;
|
||||
|
||||
import org.futo.inputmethod.keyboard.internal.KeyDrawParams;
|
||||
import org.futo.inputmethod.keyboard.internal.KeyVisualAttributes;
|
||||
import org.futo.inputmethod.latin.KeyboardDrawableProvider;
|
||||
import org.futo.inputmethod.latin.KeyboardDrawableProviderOwner;
|
||||
import org.futo.inputmethod.latin.R;
|
||||
import org.futo.inputmethod.latin.common.Constants;
|
||||
import org.futo.inputmethod.latin.utils.TypefaceUtils;
|
||||
@ -89,9 +92,11 @@ public class KeyboardView extends View {
|
||||
private final float mKeyShiftedLetterHintPadding;
|
||||
private final float mKeyTextShadowRadius;
|
||||
private final float mVerticalCorrection;
|
||||
private final Drawable mKeyboardBackground;
|
||||
private final Drawable mKeyBackground;
|
||||
private final Drawable mFunctionalKeyBackground;
|
||||
private final Drawable mSpacebarBackground;
|
||||
private final KeyboardDrawableProvider mDrawableProvider;
|
||||
private final float mSpacebarIconWidthRatio;
|
||||
private final Rect mKeyBackgroundPadding = new Rect();
|
||||
private static final float KET_TEXT_SHADOW_RADIUS_DISABLED = -1.0f;
|
||||
@ -131,15 +136,26 @@ public class KeyboardView extends View {
|
||||
|
||||
final TypedArray keyboardViewAttr = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
|
||||
mKeyBackground = keyboardViewAttr.getDrawable(R.styleable.KeyboardView_keyBackground);
|
||||
|
||||
assert(context instanceof ContextThemeWrapper);
|
||||
assert(((ContextThemeWrapper) context).getBaseContext() instanceof KeyboardDrawableProviderOwner);
|
||||
|
||||
mDrawableProvider = ((KeyboardDrawableProviderOwner) ((ContextThemeWrapper) context).getBaseContext()).getDrawableProvider();
|
||||
|
||||
boolean isMoreKeys = defStyle == R.attr.moreKeysKeyboardViewStyle || defStyle == R.attr.moreKeysKeyboardViewForActionStyle;
|
||||
|
||||
mKeyboardBackground = isMoreKeys ?
|
||||
mDrawableProvider.getMoreKeysKeyboardBackground() : mDrawableProvider.getKeyboardBackground();
|
||||
setBackground(mKeyboardBackground);
|
||||
|
||||
mKeyBackground = isMoreKeys ?
|
||||
mDrawableProvider.getPopupKey() : mDrawableProvider.getKeyBackground();
|
||||
mKeyBackground.getPadding(mKeyBackgroundPadding);
|
||||
final Drawable functionalKeyBackground = keyboardViewAttr.getDrawable(
|
||||
R.styleable.KeyboardView_functionalKeyBackground);
|
||||
mFunctionalKeyBackground = (functionalKeyBackground != null) ? functionalKeyBackground
|
||||
: mKeyBackground;
|
||||
final Drawable spacebarBackground = keyboardViewAttr.getDrawable(
|
||||
R.styleable.KeyboardView_spacebarBackground);
|
||||
mSpacebarBackground = (spacebarBackground != null) ? spacebarBackground : mKeyBackground;
|
||||
|
||||
mFunctionalKeyBackground = mKeyBackground;
|
||||
|
||||
mSpacebarBackground = mDrawableProvider.getSpaceBarBackground();
|
||||
|
||||
mSpacebarIconWidthRatio = keyboardViewAttr.getFloat(
|
||||
R.styleable.KeyboardView_spacebarIconWidthRatio, 1.0f);
|
||||
mKeyHintLetterPadding = keyboardViewAttr.getDimension(
|
||||
|
@ -2,22 +2,37 @@ package org.futo.inputmethod.latin
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.graphics.drawable.InsetDrawable
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.graphics.drawable.ShapeDrawable
|
||||
import android.graphics.drawable.StateListDrawable
|
||||
import android.graphics.drawable.shapes.OvalShape
|
||||
import android.graphics.drawable.shapes.Shape
|
||||
import android.inputmethodservice.InputMethodService
|
||||
import android.util.TypedValue
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.inputmethod.CompletionInfo
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.view.inputmethod.InputMethodSubtype
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
@ -34,8 +49,151 @@ import androidx.savedstate.SavedStateRegistryOwner
|
||||
import androidx.savedstate.findViewTreeSavedStateRegistryOwner
|
||||
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
|
||||
import org.futo.inputmethod.latin.uix.ActionBar
|
||||
import org.futo.inputmethod.latin.uix.theme.DarkColorScheme
|
||||
|
||||
|
||||
interface KeyboardDrawableProvider {
|
||||
val primaryKeyboardColor: Int
|
||||
|
||||
val keyboardBackground: Drawable
|
||||
val keyBackground: Drawable
|
||||
val spaceBarBackground: Drawable
|
||||
|
||||
val moreKeysKeyboardBackground: Drawable
|
||||
val popupKey: Drawable
|
||||
}
|
||||
|
||||
// TODO: Expand the number of drawables this provides so it covers the full theme, and
|
||||
// build some system to dynamically change these colors
|
||||
class BasicThemeProvider(val context: Context) : KeyboardDrawableProvider {
|
||||
override val primaryKeyboardColor: Int
|
||||
|
||||
override val keyboardBackground: Drawable
|
||||
override val keyBackground: Drawable
|
||||
override val spaceBarBackground: Drawable
|
||||
|
||||
override val moreKeysKeyboardBackground: Drawable
|
||||
override val popupKey: Drawable
|
||||
|
||||
private fun dp(dp: Dp): Float {
|
||||
return TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
dp.value,
|
||||
context.resources.displayMetrics
|
||||
);
|
||||
}
|
||||
|
||||
private fun coloredRectangle(@ColorInt color: Int): GradientDrawable {
|
||||
return GradientDrawable().apply {
|
||||
shape = GradientDrawable.RECTANGLE
|
||||
setColor(color)
|
||||
}
|
||||
}
|
||||
|
||||
private fun coloredRoundedRectangle(@ColorInt color: Int, radius: Float): GradientDrawable {
|
||||
return GradientDrawable().apply {
|
||||
shape = GradientDrawable.RECTANGLE
|
||||
cornerRadius = radius
|
||||
setColor(color)
|
||||
}
|
||||
}
|
||||
|
||||
private fun coloredOval(@ColorInt color: Int): GradientDrawable {
|
||||
return GradientDrawable().apply {
|
||||
shape = GradientDrawable.OVAL
|
||||
cornerRadius = Float.MAX_VALUE
|
||||
setColor(color)
|
||||
}
|
||||
}
|
||||
|
||||
private fun StateListDrawable.addStateWithHighlightLayerOnPressed(@ColorInt highlight: Int, stateSet: IntArray, drawable: Drawable) {
|
||||
addState(intArrayOf(android.R.attr.state_pressed) + stateSet, LayerDrawable(arrayOf(
|
||||
drawable,
|
||||
coloredRoundedRectangle(highlight, dp(8.dp))
|
||||
)))
|
||||
addState(stateSet, drawable)
|
||||
}
|
||||
|
||||
init {
|
||||
val primary = DarkColorScheme.primary.toArgb()
|
||||
val secondary = DarkColorScheme.secondary.toArgb()
|
||||
val highlight = DarkColorScheme.outline.copy(alpha = 0.33f).toArgb()
|
||||
val background = DarkColorScheme.surface.toArgb()
|
||||
val surface = DarkColorScheme.background.toArgb()
|
||||
val outline = DarkColorScheme.outline.toArgb()
|
||||
|
||||
val transparent = Color.TRANSPARENT
|
||||
|
||||
primaryKeyboardColor = background
|
||||
|
||||
keyboardBackground = LayerDrawable(arrayOf(
|
||||
coloredRectangle(primary),
|
||||
InsetDrawable(coloredRectangle(background),
|
||||
0, 1, 0, 0)
|
||||
))
|
||||
|
||||
keyBackground = StateListDrawable().apply {
|
||||
addStateWithHighlightLayerOnPressed(highlight, intArrayOf(android.R.attr.state_active),
|
||||
coloredRoundedRectangle(secondary, dp(8.dp)).apply {
|
||||
setSize(dp(64.dp).toInt(), dp(48.dp).toInt())
|
||||
}
|
||||
)
|
||||
|
||||
addStateWithHighlightLayerOnPressed(highlight, intArrayOf(android.R.attr.state_checkable, android.R.attr.state_checked),
|
||||
coloredRoundedRectangle(secondary, dp(8.dp))
|
||||
)
|
||||
|
||||
addStateWithHighlightLayerOnPressed(highlight, intArrayOf(android.R.attr.state_checkable),
|
||||
coloredRectangle(transparent)
|
||||
)
|
||||
|
||||
addStateWithHighlightLayerOnPressed(highlight, intArrayOf(android.R.attr.state_empty),
|
||||
coloredRectangle(transparent)
|
||||
)
|
||||
|
||||
addStateWithHighlightLayerOnPressed(highlight, intArrayOf(),
|
||||
coloredRectangle(transparent)
|
||||
)
|
||||
}
|
||||
|
||||
spaceBarBackground = StateListDrawable().apply {
|
||||
addState(intArrayOf(android.R.attr.state_pressed),
|
||||
LayerDrawable(arrayOf(
|
||||
coloredRoundedRectangle(secondary, dp(32.dp)),
|
||||
coloredRoundedRectangle(highlight, dp(32.dp))
|
||||
))
|
||||
)
|
||||
addState(intArrayOf(),
|
||||
coloredRoundedRectangle(secondary, dp(32.dp))
|
||||
)
|
||||
}
|
||||
|
||||
moreKeysKeyboardBackground = coloredRoundedRectangle(surface, dp(8.dp)).apply {
|
||||
|
||||
}
|
||||
popupKey = StateListDrawable().apply {
|
||||
addStateWithHighlightLayerOnPressed(highlight, intArrayOf(),
|
||||
coloredRoundedRectangle(surface, dp(8.dp))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface KeyboardDrawableProviderOwner {
|
||||
fun getDrawableProvider(): KeyboardDrawableProvider
|
||||
}
|
||||
|
||||
class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner, LatinIMELegacy.SuggestionStripController, KeyboardDrawableProviderOwner {
|
||||
private var drawableProvider: KeyboardDrawableProvider? = null
|
||||
override fun getDrawableProvider(): KeyboardDrawableProvider {
|
||||
if(drawableProvider == null) {
|
||||
drawableProvider = BasicThemeProvider(this)
|
||||
}
|
||||
|
||||
return drawableProvider!!
|
||||
}
|
||||
|
||||
class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, SavedStateRegistryOwner, LatinIMELegacy.SuggestionStripController {
|
||||
private val latinIMELegacy = LatinIMELegacy(
|
||||
this as InputMethodService,
|
||||
this as LatinIMELegacy.SuggestionStripController
|
||||
|
@ -823,6 +823,8 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
* @see android.content.Context#createDisplayContext(Display)
|
||||
*/
|
||||
private @NonNull Context getDisplayContext() {
|
||||
// TODO: We need to pass LatinIME for theming
|
||||
/*
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
// createDisplayContext is not available.
|
||||
return mInputMethodService;
|
||||
@ -837,6 +839,8 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
// keyboard layout with this context.
|
||||
final WindowManager wm = (WindowManager) mInputMethodService.getSystemService(Context.WINDOW_SERVICE);
|
||||
return mInputMethodService.createDisplayContext(wm.getDefaultDisplay());
|
||||
*/
|
||||
return mInputMethodService;
|
||||
}
|
||||
|
||||
public View onCreateInputView() {
|
||||
@ -1944,11 +1948,12 @@ public class LatinIMELegacy implements KeyboardActionListener,
|
||||
}
|
||||
|
||||
private void setNavigationBarVisibility(final boolean visible) {
|
||||
int color = ((KeyboardDrawableProviderOwner)getInputMethodService()).getDrawableProvider().getPrimaryKeyboardColor();
|
||||
if (BuildCompatUtils.EFFECTIVE_SDK_INT > Build.VERSION_CODES.M) {
|
||||
// For N and later, IMEs can specify Color.TRANSPARENT to make the navigation bar
|
||||
// transparent. For other colors the system uses the default color.
|
||||
mInputMethodService.getWindow().getWindow().setNavigationBarColor(
|
||||
visible ? Color.BLACK : Color.TRANSPARENT);
|
||||
visible ? color : Color.TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,7 +277,7 @@ fun ExpandActionsButton(isActionsOpen: Boolean, onClick: () -> Unit) {
|
||||
val moreActionsFill = if(isActionsOpen) {
|
||||
MaterialTheme.colorScheme.primary
|
||||
} else {
|
||||
MaterialTheme.colorScheme.surface
|
||||
MaterialTheme.colorScheme.background
|
||||
}
|
||||
IconButton(
|
||||
onClick = onClick,
|
||||
@ -314,7 +314,7 @@ fun ActionBar(
|
||||
WhisperVoiceInputTheme {
|
||||
Surface(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(40.dp), color = MaterialTheme.colorScheme.surface)
|
||||
.height(40.dp), color = MaterialTheme.colorScheme.background)
|
||||
{
|
||||
Row {
|
||||
ExpandActionsButton(isActionsOpen.value) { isActionsOpen.value = !isActionsOpen.value }
|
||||
|
@ -9,7 +9,7 @@ import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.core.view.WindowCompat
|
||||
|
||||
private val DarkColorScheme = darkColorScheme(
|
||||
val DarkColorScheme = darkColorScheme(
|
||||
primary = Slate600,
|
||||
onPrimary = Slate50,
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user