Merge branch 'main' into hide-clipboard
This commit is contained in:
commit
4b5380b7f2
|
@ -65,7 +65,7 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.github.SimpleMobileTools:Simple-Commons:6323be1fd7'
|
implementation 'com.github.SimpleMobileTools:Simple-Commons:a85f77a67f'
|
||||||
implementation 'androidx.emoji2:emoji2-bundled:1.2.0'
|
implementation 'androidx.emoji2:emoji2-bundled:1.2.0'
|
||||||
|
|
||||||
kapt 'androidx.room:room-compiler:2.4.3'
|
kapt 'androidx.room:room-compiler:2.4.3'
|
||||||
|
|
|
@ -23,7 +23,7 @@ class MainActivity : SimpleActivity() {
|
||||||
setupOptionsMenu()
|
setupOptionsMenu()
|
||||||
refreshMenuItems()
|
refreshMenuItems()
|
||||||
|
|
||||||
updateMaterialActivityViews(main_coordinator, main_holder)
|
updateMaterialActivityViews(main_coordinator, main_holder, useTransparentNavigation = false, useTopSearchMenu = false)
|
||||||
setupMaterialScrollListener(main_nested_scrollview, main_toolbar)
|
setupMaterialScrollListener(main_nested_scrollview, main_toolbar)
|
||||||
|
|
||||||
change_keyboard_holder.setOnClickListener {
|
change_keyboard_holder.setOnClickListener {
|
||||||
|
|
|
@ -36,7 +36,7 @@ class ManageClipboardItemsActivity : SimpleActivity(), RefreshRecyclerViewListen
|
||||||
updateTextColors(clipboard_items_holder)
|
updateTextColors(clipboard_items_holder)
|
||||||
updateClips()
|
updateClips()
|
||||||
|
|
||||||
updateMaterialActivityViews(clipboard_coordinator, clipboard_items_list)
|
updateMaterialActivityViews(clipboard_coordinator, clipboard_items_list, useTransparentNavigation = true, useTopSearchMenu = false)
|
||||||
setupMaterialScrollListener(clipboard_nested_scrollview, clipboard_toolbar)
|
setupMaterialScrollListener(clipboard_nested_scrollview, clipboard_toolbar)
|
||||||
|
|
||||||
clipboard_items_placeholder.text = "${getText(R.string.manage_clipboard_empty)}\n\n${getText(R.string.manage_clips)}"
|
clipboard_items_placeholder.text = "${getText(R.string.manage_clipboard_empty)}\n\n${getText(R.string.manage_clips)}"
|
||||||
|
|
|
@ -25,7 +25,7 @@ class SettingsActivity : SimpleActivity() {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_settings)
|
setContentView(R.layout.activity_settings)
|
||||||
|
|
||||||
updateMaterialActivityViews(settings_coordinator, settings_holder)
|
updateMaterialActivityViews(settings_coordinator, settings_holder, useTransparentNavigation = false, useTopSearchMenu = false)
|
||||||
setupMaterialScrollListener(settings_nested_scrollview, settings_toolbar)
|
setupMaterialScrollListener(settings_nested_scrollview, settings_toolbar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ class SettingsActivity : SimpleActivity() {
|
||||||
setupManageClipboardItems()
|
setupManageClipboardItems()
|
||||||
setupVibrateOnKeypress()
|
setupVibrateOnKeypress()
|
||||||
setupShowPopupOnKeypress()
|
setupShowPopupOnKeypress()
|
||||||
|
setupShowKeyBorders()
|
||||||
setupKeyboardLanguage()
|
setupKeyboardLanguage()
|
||||||
setupKeyboardHeightMultiplier()
|
setupKeyboardHeightMultiplier()
|
||||||
setupShowClipboardContent()
|
setupShowClipboardContent()
|
||||||
|
@ -107,6 +108,14 @@ class SettingsActivity : SimpleActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupShowKeyBorders() {
|
||||||
|
settings_show_key_borders.isChecked = config.showKeyBorders
|
||||||
|
settings_show_key_borders_holder.setOnClickListener {
|
||||||
|
settings_show_key_borders.toggle()
|
||||||
|
config.showKeyBorders = settings_show_key_borders.isChecked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupKeyboardLanguage() {
|
private fun setupKeyboardLanguage() {
|
||||||
settings_keyboard_language.text = getKeyboardLanguageText(config.keyboardLanguage)
|
settings_keyboard_language.text = getKeyboardLanguageText(config.keyboardLanguage)
|
||||||
settings_keyboard_language_holder.setOnClickListener {
|
settings_keyboard_language_holder.setOnClickListener {
|
||||||
|
|
|
@ -17,6 +17,10 @@ class Config(context: Context) : BaseConfig(context) {
|
||||||
get() = prefs.getBoolean(SHOW_POPUP_ON_KEYPRESS, true)
|
get() = prefs.getBoolean(SHOW_POPUP_ON_KEYPRESS, true)
|
||||||
set(showPopupOnKeypress) = prefs.edit().putBoolean(SHOW_POPUP_ON_KEYPRESS, showPopupOnKeypress).apply()
|
set(showPopupOnKeypress) = prefs.edit().putBoolean(SHOW_POPUP_ON_KEYPRESS, showPopupOnKeypress).apply()
|
||||||
|
|
||||||
|
var showKeyBorders: Boolean
|
||||||
|
get() = prefs.getBoolean(SHOW_KEY_BORDERS, false)
|
||||||
|
set(showKeyBorders) = prefs.edit().putBoolean(SHOW_KEY_BORDERS, showKeyBorders).apply()
|
||||||
|
|
||||||
var lastExportedClipsFolder: String
|
var lastExportedClipsFolder: String
|
||||||
get() = prefs.getString(LAST_EXPORTED_CLIPS_FOLDER, "")!!
|
get() = prefs.getString(LAST_EXPORTED_CLIPS_FOLDER, "")!!
|
||||||
set(lastExportedClipsFolder) = prefs.edit().putString(LAST_EXPORTED_CLIPS_FOLDER, lastExportedClipsFolder).apply()
|
set(lastExportedClipsFolder) = prefs.edit().putString(LAST_EXPORTED_CLIPS_FOLDER, lastExportedClipsFolder).apply()
|
||||||
|
|
|
@ -10,6 +10,7 @@ const val MAX_KEYS_PER_MINI_ROW = 9
|
||||||
// shared prefs
|
// shared prefs
|
||||||
const val VIBRATE_ON_KEYPRESS = "vibrate_on_keypress"
|
const val VIBRATE_ON_KEYPRESS = "vibrate_on_keypress"
|
||||||
const val SHOW_POPUP_ON_KEYPRESS = "show_popup_on_keypress"
|
const val SHOW_POPUP_ON_KEYPRESS = "show_popup_on_keypress"
|
||||||
|
const val SHOW_KEY_BORDERS = "show_key_borders"
|
||||||
const val LAST_EXPORTED_CLIPS_FOLDER = "last_exported_clips_folder"
|
const val LAST_EXPORTED_CLIPS_FOLDER = "last_exported_clips_folder"
|
||||||
const val KEYBOARD_LANGUAGE = "keyboard_language"
|
const val KEYBOARD_LANGUAGE = "keyboard_language"
|
||||||
const val HEIGHT_MULTIPLIER = "height_multiplier"
|
const val HEIGHT_MULTIPLIER = "height_multiplier"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.simplemobiletools.keyboard.services
|
package com.simplemobiletools.keyboard.services
|
||||||
|
|
||||||
|
import android.content.SharedPreferences
|
||||||
import android.inputmethodservice.InputMethodService
|
import android.inputmethodservice.InputMethodService
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.text.InputType.TYPE_CLASS_DATETIME
|
import android.text.InputType.TYPE_CLASS_DATETIME
|
||||||
|
@ -14,6 +15,7 @@ import android.view.inputmethod.EditorInfo.IME_ACTION_NONE
|
||||||
import android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION
|
import android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION
|
||||||
import android.view.inputmethod.EditorInfo.IME_MASK_ACTION
|
import android.view.inputmethod.EditorInfo.IME_MASK_ACTION
|
||||||
import android.view.inputmethod.ExtractedTextRequest
|
import android.view.inputmethod.ExtractedTextRequest
|
||||||
|
import com.simplemobiletools.commons.extensions.getSharedPrefs
|
||||||
import com.simplemobiletools.keyboard.R
|
import com.simplemobiletools.keyboard.R
|
||||||
import com.simplemobiletools.keyboard.extensions.config
|
import com.simplemobiletools.keyboard.extensions.config
|
||||||
import com.simplemobiletools.keyboard.helpers.*
|
import com.simplemobiletools.keyboard.helpers.*
|
||||||
|
@ -21,7 +23,7 @@ import com.simplemobiletools.keyboard.views.MyKeyboardView
|
||||||
import kotlinx.android.synthetic.main.keyboard_view_keyboard.view.*
|
import kotlinx.android.synthetic.main.keyboard_view_keyboard.view.*
|
||||||
|
|
||||||
// based on https://www.androidauthority.com/lets-build-custom-keyboard-android-832362/
|
// based on https://www.androidauthority.com/lets-build-custom-keyboard-android-832362/
|
||||||
class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionListener {
|
class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionListener, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
private var SHIFT_PERM_TOGGLE_SPEED = 500 // how quickly do we have to doubletap shift to enable permanent caps lock
|
private var SHIFT_PERM_TOGGLE_SPEED = 500 // how quickly do we have to doubletap shift to enable permanent caps lock
|
||||||
private val KEYBOARD_LETTERS = 0
|
private val KEYBOARD_LETTERS = 0
|
||||||
private val KEYBOARD_SYMBOLS = 1
|
private val KEYBOARD_SYMBOLS = 1
|
||||||
|
@ -38,6 +40,7 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL
|
||||||
override fun onInitializeInterface() {
|
override fun onInitializeInterface() {
|
||||||
super.onInitializeInterface()
|
super.onInitializeInterface()
|
||||||
keyboard = MyKeyboard(this, getKeyboardLayoutXML(), enterKeyType)
|
keyboard = MyKeyboard(this, getKeyboardLayoutXML(), enterKeyType)
|
||||||
|
getSharedPrefs().registerOnSharedPreferenceChangeListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateInputView(): View {
|
override fun onCreateInputView(): View {
|
||||||
|
@ -275,4 +278,8 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL
|
||||||
else -> R.xml.keys_letters_english_qwerty
|
else -> R.xml.keys_letters_english_qwerty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||||
|
keyboardView?.setupKeyboard()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,7 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.*
|
import android.graphics.*
|
||||||
import android.graphics.Paint.Align
|
import android.graphics.Paint.Align
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.*
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.LayerDrawable
|
|
||||||
import android.graphics.drawable.RippleDrawable
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.os.Message
|
import android.os.Message
|
||||||
|
@ -107,6 +104,8 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
private var mTextColor = 0
|
private var mTextColor = 0
|
||||||
private var mBackgroundColor = 0
|
private var mBackgroundColor = 0
|
||||||
private var mPrimaryColor = 0
|
private var mPrimaryColor = 0
|
||||||
|
private var mKeyColor = 0
|
||||||
|
private var mKeyColorPressed = 0
|
||||||
|
|
||||||
private var mPreviewText: TextView? = null
|
private var mPreviewText: TextView? = null
|
||||||
private val mPreviewPopup: PopupWindow
|
private val mPreviewPopup: PopupWindow
|
||||||
|
@ -158,6 +157,8 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
private var ignoreTouches = false
|
private var ignoreTouches = false
|
||||||
|
|
||||||
private var mKeyBackground: Drawable? = null
|
private var mKeyBackground: Drawable? = null
|
||||||
|
private var mShowKeyBorders: Boolean = false
|
||||||
|
private var mUsingSystemTheme: Boolean = true
|
||||||
|
|
||||||
private var mToolbarHolder: View? = null
|
private var mToolbarHolder: View? = null
|
||||||
private var mClipboardManagerHolder: View? = null
|
private var mClipboardManagerHolder: View? = null
|
||||||
|
@ -275,75 +276,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
closeEmojiPalette()
|
closeEmojiPalette()
|
||||||
|
|
||||||
if (visibility == VISIBLE) {
|
if (visibility == VISIBLE) {
|
||||||
mTextColor = context.getProperTextColor()
|
setupKeyboard(changedView)
|
||||||
mBackgroundColor = context.getProperBackgroundColor()
|
|
||||||
mPrimaryColor = context.getProperPrimaryColor()
|
|
||||||
val strokeColor = context.getStrokeColor()
|
|
||||||
|
|
||||||
val toolbarColor = if (context.config.isUsingSystemTheme) {
|
|
||||||
resources.getColor(R.color.you_keyboard_toolbar_color, context.theme)
|
|
||||||
} else {
|
|
||||||
mBackgroundColor.darkenColor()
|
|
||||||
}
|
|
||||||
|
|
||||||
val darkerColor = if (context.config.isUsingSystemTheme) {
|
|
||||||
resources.getColor(R.color.you_keyboard_background_color, context.theme)
|
|
||||||
} else {
|
|
||||||
mBackgroundColor.darkenColor(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
val miniKeyboardBackgroundColor = if (context.config.isUsingSystemTheme) {
|
|
||||||
resources.getColor(R.color.you_keyboard_toolbar_color, context.theme)
|
|
||||||
} else {
|
|
||||||
mBackgroundColor.darkenColor(4)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changedView == mini_keyboard_view) {
|
|
||||||
val previewBackground = background as LayerDrawable
|
|
||||||
previewBackground.findDrawableByLayerId(R.id.button_background_shape).applyColorFilter(miniKeyboardBackgroundColor)
|
|
||||||
previewBackground.findDrawableByLayerId(R.id.button_background_stroke).applyColorFilter(strokeColor)
|
|
||||||
background = previewBackground
|
|
||||||
} else {
|
|
||||||
background.applyColorFilter(darkerColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
val rippleBg = resources.getDrawable(R.drawable.clipboard_background, context.theme) as RippleDrawable
|
|
||||||
val layerDrawable = rippleBg.findDrawableByLayerId(R.id.clipboard_background_holder) as LayerDrawable
|
|
||||||
layerDrawable.findDrawableByLayerId(R.id.clipboard_background_stroke).applyColorFilter(strokeColor)
|
|
||||||
layerDrawable.findDrawableByLayerId(R.id.clipboard_background_shape).applyColorFilter(mBackgroundColor)
|
|
||||||
|
|
||||||
val wasDarkened = mBackgroundColor != mBackgroundColor.darkenColor()
|
|
||||||
mToolbarHolder?.apply {
|
|
||||||
top_keyboard_divider.beGoneIf(wasDarkened)
|
|
||||||
top_keyboard_divider.background = ColorDrawable(strokeColor)
|
|
||||||
|
|
||||||
background = ColorDrawable(toolbarColor)
|
|
||||||
clipboard_value.apply {
|
|
||||||
background = rippleBg
|
|
||||||
setTextColor(mTextColor)
|
|
||||||
setLinkTextColor(mTextColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
settings_cog.applyColorFilter(mTextColor)
|
|
||||||
pinned_clipboard_items.applyColorFilter(mTextColor)
|
|
||||||
clipboard_clear.applyColorFilter(mTextColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
mClipboardManagerHolder?.apply {
|
|
||||||
top_clipboard_divider.beGoneIf(wasDarkened)
|
|
||||||
top_clipboard_divider.background = ColorDrawable(strokeColor)
|
|
||||||
clipboard_manager_holder.background = ColorDrawable(toolbarColor)
|
|
||||||
|
|
||||||
clipboard_manager_close.applyColorFilter(mTextColor)
|
|
||||||
clipboard_manager_manage.applyColorFilter(mTextColor)
|
|
||||||
|
|
||||||
clipboard_manager_label.setTextColor(mTextColor)
|
|
||||||
clipboard_content_placeholder_1.setTextColor(mTextColor)
|
|
||||||
clipboard_content_placeholder_2.setTextColor(mTextColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
setupEmojiPalette(toolbarColor = toolbarColor, backgroundColor = mBackgroundColor, textColor = mTextColor)
|
|
||||||
setupStoredClips()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,6 +371,77 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
emojiCompatMetadataVersion = editorInfo.extras?.getInt(EmojiCompat.EDITOR_INFO_METAVERSION_KEY, 0) ?: 0
|
emojiCompatMetadataVersion = editorInfo.extras?.getInt(EmojiCompat.EDITOR_INFO_METAVERSION_KEY, 0) ?: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setupKeyboard(changedView: View? = null) {
|
||||||
|
mTextColor = context.getProperTextColor()
|
||||||
|
mBackgroundColor = context.getProperBackgroundColor()
|
||||||
|
mPrimaryColor = context.getProperPrimaryColor()
|
||||||
|
|
||||||
|
mShowKeyBorders = context.config.showKeyBorders
|
||||||
|
mUsingSystemTheme = context.config.isUsingSystemTheme
|
||||||
|
|
||||||
|
val isMainKeyboard = changedView == null || changedView != mini_keyboard_view
|
||||||
|
mKeyBackground = if (mShowKeyBorders && isMainKeyboard) {
|
||||||
|
resources.getDrawable(R.drawable.keyboard_key_selector_outlined, context.theme)
|
||||||
|
} else {
|
||||||
|
resources.getDrawable(R.drawable.keyboard_key_selector, context.theme)
|
||||||
|
}
|
||||||
|
mKeyColor = getKeyColor()
|
||||||
|
mKeyColorPressed = mKeyColor.adjustAlpha(0.2f)
|
||||||
|
|
||||||
|
val strokeColor = context.getStrokeColor()
|
||||||
|
|
||||||
|
val toolbarColor = getToolbarColor()
|
||||||
|
val darkerColor = getKeyboardBackgroundColor()
|
||||||
|
val miniKeyboardBackgroundColor = getToolbarColor(4)
|
||||||
|
|
||||||
|
if (!isMainKeyboard) {
|
||||||
|
val previewBackground = background as LayerDrawable
|
||||||
|
previewBackground.findDrawableByLayerId(R.id.button_background_shape).applyColorFilter(miniKeyboardBackgroundColor)
|
||||||
|
previewBackground.findDrawableByLayerId(R.id.button_background_stroke).applyColorFilter(strokeColor)
|
||||||
|
background = previewBackground
|
||||||
|
} else {
|
||||||
|
background.applyColorFilter(darkerColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
val rippleBg = resources.getDrawable(R.drawable.clipboard_background, context.theme) as RippleDrawable
|
||||||
|
val layerDrawable = rippleBg.findDrawableByLayerId(R.id.clipboard_background_holder) as LayerDrawable
|
||||||
|
layerDrawable.findDrawableByLayerId(R.id.clipboard_background_stroke).applyColorFilter(strokeColor)
|
||||||
|
layerDrawable.findDrawableByLayerId(R.id.clipboard_background_shape).applyColorFilter(mBackgroundColor)
|
||||||
|
|
||||||
|
val wasDarkened = mBackgroundColor != mBackgroundColor.darkenColor()
|
||||||
|
mToolbarHolder?.apply {
|
||||||
|
top_keyboard_divider.beGoneIf(wasDarkened)
|
||||||
|
top_keyboard_divider.background = ColorDrawable(strokeColor)
|
||||||
|
|
||||||
|
background = ColorDrawable(toolbarColor)
|
||||||
|
clipboard_value.apply {
|
||||||
|
background = rippleBg
|
||||||
|
setTextColor(mTextColor)
|
||||||
|
setLinkTextColor(mTextColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
settings_cog.applyColorFilter(mTextColor)
|
||||||
|
pinned_clipboard_items.applyColorFilter(mTextColor)
|
||||||
|
clipboard_clear.applyColorFilter(mTextColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
mClipboardManagerHolder?.apply {
|
||||||
|
top_clipboard_divider.beGoneIf(wasDarkened)
|
||||||
|
top_clipboard_divider.background = ColorDrawable(strokeColor)
|
||||||
|
clipboard_manager_holder.background = ColorDrawable(toolbarColor)
|
||||||
|
|
||||||
|
clipboard_manager_close.applyColorFilter(mTextColor)
|
||||||
|
clipboard_manager_manage.applyColorFilter(mTextColor)
|
||||||
|
|
||||||
|
clipboard_manager_label.setTextColor(mTextColor)
|
||||||
|
clipboard_content_placeholder_1.setTextColor(mTextColor)
|
||||||
|
clipboard_content_placeholder_2.setTextColor(mTextColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
setupEmojiPalette(toolbarColor = toolbarColor, backgroundColor = mBackgroundColor, textColor = mTextColor)
|
||||||
|
setupStoredClips()
|
||||||
|
}
|
||||||
|
|
||||||
fun vibrateIfNeeded() {
|
fun vibrateIfNeeded() {
|
||||||
if (context.config.vibrateOnKeypress) {
|
if (context.config.vibrateOnKeypress) {
|
||||||
performHapticFeedback()
|
performHapticFeedback()
|
||||||
|
@ -563,36 +567,10 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
for (i in 0 until keyCount) {
|
for (i in 0 until keyCount) {
|
||||||
val key = keys[i]
|
val key = keys[i]
|
||||||
val code = key.code
|
val code = key.code
|
||||||
var keyBackground = mKeyBackground
|
setupKeyBackground(key, code, canvas)
|
||||||
if (code == KEYCODE_SPACE) {
|
|
||||||
keyBackground = if (context.config.isUsingSystemTheme) {
|
|
||||||
resources.getDrawable(R.drawable.keyboard_space_background_material, context.theme)
|
|
||||||
} else {
|
|
||||||
resources.getDrawable(R.drawable.keyboard_space_background, context.theme)
|
|
||||||
}
|
|
||||||
} else if (code == KEYCODE_ENTER) {
|
|
||||||
keyBackground = resources.getDrawable(R.drawable.keyboard_enter_background, context.theme)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switch the character to uppercase if shift is pressed
|
// Switch the character to uppercase if shift is pressed
|
||||||
val label = adjustCase(key.label)?.toString()
|
val label = adjustCase(key.label)?.toString()
|
||||||
val bounds = keyBackground!!.bounds
|
|
||||||
if (key.width != bounds.right || key.height != bounds.bottom) {
|
|
||||||
keyBackground.setBounds(0, 0, key.width, key.height)
|
|
||||||
}
|
|
||||||
|
|
||||||
keyBackground.state = when {
|
|
||||||
key.pressed -> intArrayOf(android.R.attr.state_pressed)
|
|
||||||
key.focused -> intArrayOf(android.R.attr.state_focused)
|
|
||||||
else -> intArrayOf()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key.focused || code == KEYCODE_ENTER) {
|
|
||||||
keyBackground.applyColorFilter(mPrimaryColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas.translate(key.x.toFloat(), key.y.toFloat())
|
|
||||||
keyBackground.draw(canvas)
|
|
||||||
if (label?.isNotEmpty() == true) {
|
if (label?.isNotEmpty() == true) {
|
||||||
// For characters, use large font. For labels like "Done", use small font.
|
// For characters, use large font. For labels like "Done", use small font.
|
||||||
if (label.length > 1) {
|
if (label.length > 1) {
|
||||||
|
@ -656,6 +634,72 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
mDirtyRect.setEmpty()
|
mDirtyRect.setEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupKeyBackground(key: MyKeyboard.Key, keyCode: Int, canvas: Canvas) {
|
||||||
|
val keyBackground = when (keyCode) {
|
||||||
|
KEYCODE_SPACE -> getSpaceKeyBackground()
|
||||||
|
KEYCODE_ENTER -> getEnterKeyBackground()
|
||||||
|
else -> mKeyBackground
|
||||||
|
}
|
||||||
|
|
||||||
|
val bounds = keyBackground!!.bounds
|
||||||
|
if (key.width != bounds.right || key.height != bounds.bottom) {
|
||||||
|
keyBackground.setBounds(0, 0, key.width, key.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
keyBackground.state = when {
|
||||||
|
key.pressed -> intArrayOf(android.R.attr.state_pressed)
|
||||||
|
key.focused -> intArrayOf(android.R.attr.state_focused)
|
||||||
|
else -> intArrayOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.focused || keyCode == KEYCODE_ENTER) {
|
||||||
|
val keyColor = if (key.pressed) {
|
||||||
|
mPrimaryColor.adjustAlpha(0.8f)
|
||||||
|
} else {
|
||||||
|
mPrimaryColor
|
||||||
|
}
|
||||||
|
keyBackground.applyColorFilter(keyColor)
|
||||||
|
} else if (mShowKeyBorders) {
|
||||||
|
if (keyCode != KEYCODE_SPACE || !mUsingSystemTheme) {
|
||||||
|
val keyColor = if (key.pressed) {
|
||||||
|
mKeyColorPressed
|
||||||
|
} else {
|
||||||
|
mKeyColor
|
||||||
|
}
|
||||||
|
keyBackground.applyColorFilter(keyColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.translate(key.x.toFloat(), key.y.toFloat())
|
||||||
|
keyBackground.draw(canvas)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSpaceKeyBackground(): Drawable? {
|
||||||
|
val drawableId = if (mUsingSystemTheme) {
|
||||||
|
if (mShowKeyBorders) {
|
||||||
|
R.drawable.keyboard_space_background_material_outlined
|
||||||
|
} else {
|
||||||
|
R.drawable.keyboard_space_background_material
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mShowKeyBorders) {
|
||||||
|
R.drawable.keyboard_key_selector_outlined
|
||||||
|
} else {
|
||||||
|
R.drawable.keyboard_space_background
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resources.getDrawable(drawableId, context.theme)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getEnterKeyBackground(): Drawable? {
|
||||||
|
val drawableId = if (mShowKeyBorders) {
|
||||||
|
R.drawable.keyboard_enter_background_outlined
|
||||||
|
} else {
|
||||||
|
R.drawable.keyboard_enter_background
|
||||||
|
}
|
||||||
|
return resources.getDrawable(drawableId, context.theme)
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleClipboard() {
|
private fun handleClipboard() {
|
||||||
if (mToolbarHolder != null && mPopupParent.id != R.id.mini_keyboard_view && context.config.showClipboardContent) {
|
if (mToolbarHolder != null && mPopupParent.id != R.id.mini_keyboard_view && context.config.showClipboardContent) {
|
||||||
val clipboardContent = context.getCurrentClip()
|
val clipboardContent = context.getCurrentClip()
|
||||||
|
@ -745,10 +789,6 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showPreview(keyIndex: Int) {
|
private fun showPreview(keyIndex: Int) {
|
||||||
if (!context.config.showPopupOnKeypress) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val oldKeyIndex = mCurrentKeyIndex
|
val oldKeyIndex = mCurrentKeyIndex
|
||||||
val previewPopup = mPreviewPopup
|
val previewPopup = mPreviewPopup
|
||||||
mCurrentKeyIndex = keyIndex
|
mCurrentKeyIndex = keyIndex
|
||||||
|
@ -767,7 +807,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
val newKey = keys[mCurrentKeyIndex]
|
val newKey = keys[mCurrentKeyIndex]
|
||||||
|
|
||||||
val code = newKey.code
|
val code = newKey.code
|
||||||
if (code == KEYCODE_SHIFT || code == KEYCODE_MODE_CHANGE || code == KEYCODE_DELETE || code == KEYCODE_ENTER || code == KEYCODE_SPACE) {
|
if (context.config.showKeyBorders || (code == KEYCODE_SHIFT || code == KEYCODE_MODE_CHANGE || code == KEYCODE_DELETE || code == KEYCODE_ENTER || code == KEYCODE_SPACE)) {
|
||||||
newKey.pressed = true
|
newKey.pressed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,6 +816,10 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!context.config.showPopupOnKeypress) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// If key changed and preview is on ...
|
// If key changed and preview is on ...
|
||||||
if (oldKeyIndex != mCurrentKeyIndex) {
|
if (oldKeyIndex != mCurrentKeyIndex) {
|
||||||
if (previewPopup.isShowing) {
|
if (previewPopup.isShowing) {
|
||||||
|
@ -819,11 +863,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val previewBackgroundColor = if (context.config.isUsingSystemTheme) {
|
val previewBackgroundColor = getToolbarColor(4)
|
||||||
resources.getColor(R.color.you_keyboard_toolbar_color, context.theme)
|
|
||||||
} else {
|
|
||||||
mBackgroundColor.darkenColor(4)
|
|
||||||
}
|
|
||||||
|
|
||||||
val previewBackground = mPreviewText!!.background as LayerDrawable
|
val previewBackground = mPreviewText!!.background as LayerDrawable
|
||||||
previewBackground.findDrawableByLayerId(R.id.button_background_shape).applyColorFilter(previewBackgroundColor)
|
previewBackground.findDrawableByLayerId(R.id.button_background_shape).applyColorFilter(previewBackgroundColor)
|
||||||
|
@ -1529,4 +1569,50 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||||
invalidateAllKeys()
|
invalidateAllKeys()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun maybeDarkenColor(color: Int, factor: Int): Int {
|
||||||
|
// use darker background color when key borders are enabled
|
||||||
|
if (context.config.showKeyBorders) {
|
||||||
|
val darkerColor = color.darkenColor(factor)
|
||||||
|
return if (darkerColor == Color.WHITE) {
|
||||||
|
resources.getColor(R.color.md_grey_200, context.theme)
|
||||||
|
} else {
|
||||||
|
darkerColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return color
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getToolbarColor(factor: Int = 8): Int {
|
||||||
|
val color = if (context.config.isUsingSystemTheme) {
|
||||||
|
resources.getColor(R.color.you_keyboard_toolbar_color, context.theme)
|
||||||
|
} else {
|
||||||
|
mBackgroundColor.darkenColor(factor)
|
||||||
|
}
|
||||||
|
return maybeDarkenColor(color, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getKeyboardBackgroundColor(): Int {
|
||||||
|
val color = if (context.config.isUsingSystemTheme) {
|
||||||
|
resources.getColor(R.color.you_keyboard_background_color, context.theme)
|
||||||
|
} else {
|
||||||
|
mBackgroundColor.darkenColor(2)
|
||||||
|
}
|
||||||
|
return maybeDarkenColor(color, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getKeyColor(): Int {
|
||||||
|
val backgroundColor = getKeyboardBackgroundColor()
|
||||||
|
val lighterColor = backgroundColor.lightenColor()
|
||||||
|
val keyColor = if (context.config.isUsingSystemTheme) {
|
||||||
|
lighterColor
|
||||||
|
} else {
|
||||||
|
if (backgroundColor == Color.BLACK) {
|
||||||
|
backgroundColor.getContrastColor().adjustAlpha(0.1f)
|
||||||
|
} else {
|
||||||
|
lighterColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keyColor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@+id/key_normal" android:bottom="@dimen/small_margin" android:left="@dimen/tiny_margin" android:right="@dimen/tiny_margin" android:top="@dimen/small_margin">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="@color/white"/>
|
||||||
|
<corners android:radius="@dimen/medium_margin"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@+id/button_background_shape" android:bottom="@dimen/small_margin" android:left="@dimen/tiny_margin" android:right="@dimen/tiny_margin" android:top="@dimen/small_margin">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="@color/color_primary"/>
|
||||||
|
<corners android:radius="@dimen/medium_margin"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!--used after long pressing a key to highlight the currently selected key alternative on minikeyboard-->
|
||||||
|
<item android:drawable="@drawable/minikeyboard_selected_background" android:state_focused="true" />
|
||||||
|
<item android:drawable="@drawable/key_background_outlined" />
|
||||||
|
</selector>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_pressed="true">
|
||||||
|
<layer-list>
|
||||||
|
<item android:id="@+id/space_pressed" android:bottom="@dimen/small_margin" android:left="@dimen/tiny_margin" android:right="@dimen/tiny_margin" android:state_pressed="true" android:top="@dimen/small_margin">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="@android:color/system_accent2_600"/>
|
||||||
|
<corners android:radius="@dimen/medium_margin"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layer-list>
|
||||||
|
<item android:id="@+id/space_normal" android:bottom="@dimen/small_margin" android:left="@dimen/tiny_margin" android:right="@dimen/tiny_margin" android:state_pressed="true" android:top="@dimen/small_margin">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<solid android:color="@android:color/system_accent2_700"/>
|
||||||
|
<corners android:radius="@dimen/medium_margin"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
||||||
|
</item>
|
||||||
|
</selector>
|
|
@ -32,8 +32,8 @@
|
||||||
<string name="vibrate_on_keypress">Rezgés a billentyű lenyomásakor</string>
|
<string name="vibrate_on_keypress">Rezgés a billentyű lenyomásakor</string>
|
||||||
<string name="keyboard_language">A billentyűzet nyelve</string>
|
<string name="keyboard_language">A billentyűzet nyelve</string>
|
||||||
<string name="keyboard_height">Billentyűzet magassága</string>
|
<string name="keyboard_height">Billentyűzet magassága</string>
|
||||||
<string name="show_key_borders">Show key borders</string>
|
<string name="show_key_borders">Gombszélek megjelenítése</string>
|
||||||
<string name="show_numbers_row">Show numbers on a separate row</string>
|
<string name="show_numbers_row">Számok megjelenítése külön sorban</string>
|
||||||
<!-- Emojis -->
|
<!-- Emojis -->
|
||||||
<string name="emojis">Emojik</string>
|
<string name="emojis">Emojik</string>
|
||||||
<!--
|
<!--
|
||||||
|
|
|
@ -162,7 +162,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -123,7 +123,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -126,7 +126,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -125,7 +125,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -125,7 +125,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -106,7 +106,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -125,7 +125,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -137,7 +137,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -125,7 +125,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -159,7 +159,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -112,7 +112,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -123,7 +123,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -133,7 +133,7 @@
|
||||||
app:code="-6"
|
app:code="-6"
|
||||||
app:keyEdgeFlags="left"
|
app:keyEdgeFlags="left"
|
||||||
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
app:keyIcon="@drawable/ic_emoji_emotions_outline_vector"
|
||||||
app:keyWidth="8%p" />
|
app:keyWidth="10%p" />
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
app:keyWidth="48%p" />
|
app:keyWidth="50%p" />
|
||||||
<Key
|
<Key
|
||||||
app:keyLabel="."
|
app:keyLabel="."
|
||||||
app:keyWidth="10%p" />
|
app:keyWidth="10%p" />
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
<Key
|
<Key
|
||||||
app:code="32"
|
app:code="32"
|
||||||
app:isRepeatable="true"
|
app:isRepeatable="true"
|
||||||
app:keyWidth="48%p" />
|
app:keyWidth="50%p" />
|
||||||
<Key
|
<Key
|
||||||
app:keyLabel="."
|
app:keyLabel="."
|
||||||
app:keyWidth="10%p" />
|
app:keyWidth="10%p" />
|
||||||
|
|
|
@ -6,16 +6,16 @@
|
||||||
|
|
||||||
Он поставляется с материальным дизайном и темной темой по умолчанию, что обеспечивает отличный пользовательский опыт для простого использования. Отсутствие доступа в Интернет обеспечивает большую конфиденциальность, безопасность и стабильность по сравнению с другими приложениями.
|
Он поставляется с материальным дизайном и темной темой по умолчанию, что обеспечивает отличный пользовательский опыт для простого использования. Отсутствие доступа в Интернет обеспечивает большую конфиденциальность, безопасность и стабильность по сравнению с другими приложениями.
|
||||||
|
|
||||||
Не содержит рекламы и ненужных разрешений. Является полностью открытым исходным кодом, предоставляет настраиваемые цвета.
|
Не содержит рекламы и ненужных разрешений. Полностью открытый исходный код, предоставляет настраиваемые цвета.
|
||||||
|
|
||||||
Ознакомьтесь с полным набором простых инструментов здесь:
|
Ознакомьтесь с полным набором простых инструментов здесь:
|
||||||
https://www.simplemobiletools.com
|
https://www.simplemobiletools.com
|
||||||
|
|
||||||
Фейсбук:
|
Facebook:
|
||||||
https://www.facebook.com/simplemobiletools
|
https://www.facebook.com/simplemobiletools
|
||||||
|
|
||||||
Реддит:
|
Reddit:
|
||||||
https://www.reddit.com/r/SimpleMobileTools
|
https://www.reddit.com/r/SimpleMobileTools
|
||||||
|
|
||||||
Телеграмма:
|
Telegram:
|
||||||
https://t.me/SimpleMobileTools
|
https://t.me/SimpleMobileTools
|
Loading…
Reference in New Issue