feature: support switching language on longpress of emoji key
This commit is contained in:
parent
3cfd184387
commit
210da88052
8 changed files with 325 additions and 16 deletions
|
@ -0,0 +1,57 @@
|
|||
package com.simplemobiletools.keyboard.dialogs
|
||||
|
||||
import android.view.View
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.keyboard.R
|
||||
import com.simplemobiletools.keyboard.extensions.config
|
||||
import com.simplemobiletools.keyboard.helpers.*
|
||||
|
||||
class ChangeLanguagePopup(
|
||||
inputView: View,
|
||||
private val onSelect: () -> Unit,
|
||||
) {
|
||||
private val context = inputView.context
|
||||
private val config = context.config
|
||||
|
||||
init {
|
||||
val items = arrayListOf(
|
||||
RadioItem(LANGUAGE_BENGALI, getKeyboardLanguageText(LANGUAGE_BENGALI)),
|
||||
RadioItem(LANGUAGE_BULGARIAN, getKeyboardLanguageText(LANGUAGE_BULGARIAN)),
|
||||
RadioItem(LANGUAGE_ENGLISH_QWERTY, getKeyboardLanguageText(LANGUAGE_ENGLISH_QWERTY)),
|
||||
RadioItem(LANGUAGE_ENGLISH_QWERTZ, getKeyboardLanguageText(LANGUAGE_ENGLISH_QWERTZ)),
|
||||
RadioItem(LANGUAGE_ENGLISH_DVORAK, getKeyboardLanguageText(LANGUAGE_ENGLISH_DVORAK)),
|
||||
RadioItem(LANGUAGE_FRENCH, getKeyboardLanguageText(LANGUAGE_FRENCH)),
|
||||
RadioItem(LANGUAGE_GERMAN, getKeyboardLanguageText(LANGUAGE_GERMAN)),
|
||||
RadioItem(LANGUAGE_LITHUANIAN, getKeyboardLanguageText(LANGUAGE_LITHUANIAN)),
|
||||
RadioItem(LANGUAGE_ROMANIAN, getKeyboardLanguageText(LANGUAGE_ROMANIAN)),
|
||||
RadioItem(LANGUAGE_RUSSIAN, getKeyboardLanguageText(LANGUAGE_RUSSIAN)),
|
||||
RadioItem(LANGUAGE_SLOVENIAN, getKeyboardLanguageText(LANGUAGE_SLOVENIAN)),
|
||||
RadioItem(LANGUAGE_SPANISH, getKeyboardLanguageText(LANGUAGE_SPANISH)),
|
||||
RadioItem(LANGUAGE_TURKISH_Q, getKeyboardLanguageText(LANGUAGE_TURKISH_Q)),
|
||||
)
|
||||
|
||||
KeyboardRadioGroupDialog(inputView, items, config.keyboardLanguage) {
|
||||
config.keyboardLanguage = it as Int
|
||||
onSelect.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun getKeyboardLanguageText(language: Int): String {
|
||||
return when (language) {
|
||||
LANGUAGE_BENGALI -> context.getString(R.string.translation_bengali)
|
||||
LANGUAGE_BULGARIAN -> context.getString(R.string.translation_bulgarian)
|
||||
LANGUAGE_ENGLISH_DVORAK -> "${context.getString(R.string.translation_english)} (DVORAK)"
|
||||
LANGUAGE_ENGLISH_QWERTZ -> "${context.getString(R.string.translation_english)} (QWERTZ)"
|
||||
LANGUAGE_FRENCH -> context.getString(R.string.translation_french)
|
||||
LANGUAGE_GERMAN -> context.getString(R.string.translation_german)
|
||||
LANGUAGE_LITHUANIAN -> context.getString(R.string.translation_lithuanian)
|
||||
LANGUAGE_ROMANIAN -> context.getString(R.string.translation_romanian)
|
||||
LANGUAGE_RUSSIAN -> context.getString(R.string.translation_russian)
|
||||
LANGUAGE_SLOVENIAN -> context.getString(R.string.translation_slovenian)
|
||||
LANGUAGE_SPANISH -> context.getString(R.string.translation_spanish)
|
||||
LANGUAGE_TURKISH_Q -> "${context.getString(R.string.translation_turkish)} (Q)"
|
||||
else -> "${context.getString(R.string.translation_english)} (QWERTY)"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package com.simplemobiletools.keyboard.dialogs
|
||||
|
||||
import android.view.ContextThemeWrapper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RadioButton
|
||||
import android.widget.RadioGroup
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.simplemobiletools.commons.extensions.onGlobalLayout
|
||||
import com.simplemobiletools.commons.models.RadioItem
|
||||
import com.simplemobiletools.keyboard.R
|
||||
import com.simplemobiletools.keyboard.extensions.getKeyboardDialogBuilder
|
||||
import com.simplemobiletools.keyboard.extensions.setupKeyboardDialogStuff
|
||||
import kotlinx.android.synthetic.main.dialog_radio_group.view.dialog_radio_group
|
||||
import kotlinx.android.synthetic.main.dialog_radio_group.view.dialog_radio_holder
|
||||
|
||||
class KeyboardRadioGroupDialog(
|
||||
private val inputView: View,
|
||||
private val items: ArrayList<RadioItem>,
|
||||
private val checkedItemId: Int = -1,
|
||||
private val titleId: Int = 0,
|
||||
showOKButton: Boolean = false,
|
||||
private val cancelCallback: (() -> Unit)? = null,
|
||||
private val callback: (newValue: Any) -> Unit
|
||||
) {
|
||||
private val context = ContextThemeWrapper(inputView.context, R.style.MyKeyboard_Alert)
|
||||
private var dialog: AlertDialog? = null
|
||||
private var wasInit = false
|
||||
private var selectedItemId = -1
|
||||
private val layoutInflater = LayoutInflater.from(context)
|
||||
|
||||
init {
|
||||
val view = layoutInflater.inflate(R.layout.dialog_radio_group, null)
|
||||
view.dialog_radio_group.apply {
|
||||
for (i in 0 until items.size) {
|
||||
val radioButton = (layoutInflater.inflate(R.layout.radio_button, null) as RadioButton).apply {
|
||||
text = items[i].title
|
||||
isChecked = items[i].id == checkedItemId
|
||||
id = i
|
||||
setOnClickListener { itemSelected(i) }
|
||||
}
|
||||
|
||||
if (items[i].id == checkedItemId) {
|
||||
selectedItemId = i
|
||||
}
|
||||
|
||||
addView(radioButton, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
|
||||
}
|
||||
}
|
||||
|
||||
val builder = context.getKeyboardDialogBuilder()
|
||||
.setOnCancelListener { cancelCallback?.invoke() }
|
||||
|
||||
if (selectedItemId != -1 && showOKButton) {
|
||||
builder.setPositiveButton(R.string.ok) { _, _ -> itemSelected(selectedItemId) }
|
||||
}
|
||||
|
||||
builder.apply {
|
||||
context.setupKeyboardDialogStuff(inputView.windowToken, view, this, titleId) { alertDialog ->
|
||||
dialog = alertDialog
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (selectedItemId != -1) {
|
||||
view.dialog_radio_holder.apply {
|
||||
onGlobalLayout {
|
||||
scrollY = view.dialog_radio_group.findViewById<View>(selectedItemId).bottom - height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wasInit = true
|
||||
}
|
||||
|
||||
private fun itemSelected(checkedId: Int) {
|
||||
if (wasInit) {
|
||||
callback(items[checkedId].value)
|
||||
dialog?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,9 +3,18 @@ package com.simplemobiletools.keyboard.extensions
|
|||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import com.simplemobiletools.commons.extensions.getProperBackgroundColor
|
||||
import com.simplemobiletools.commons.extensions.isUsingSystemDarkTheme
|
||||
import com.simplemobiletools.commons.extensions.lightenColor
|
||||
import android.os.IBinder
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.Window
|
||||
import android.view.WindowManager
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.views.MyTextView
|
||||
import com.simplemobiletools.keyboard.R
|
||||
import com.simplemobiletools.keyboard.databases.ClipsDatabase
|
||||
import com.simplemobiletools.keyboard.helpers.Config
|
||||
|
@ -36,3 +45,107 @@ fun Context.getStrokeColor(): Int {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getKeyboardDialogBuilder() = if (baseConfig.isUsingSystemTheme) {
|
||||
MaterialAlertDialogBuilder(this, R.style.MyKeyboard_Alert)
|
||||
} else {
|
||||
AlertDialog.Builder(this, R.style.MyKeyboard_Alert)
|
||||
}
|
||||
|
||||
|
||||
fun Context.setupKeyboardDialogStuff(
|
||||
windowToken: IBinder,
|
||||
view: View,
|
||||
dialog: AlertDialog.Builder,
|
||||
titleId: Int = 0,
|
||||
titleText: String = "",
|
||||
cancelOnTouchOutside: Boolean = true,
|
||||
callback: ((alertDialog: AlertDialog) -> Unit)? = null
|
||||
) {
|
||||
|
||||
|
||||
val textColor = getProperTextColor()
|
||||
val backgroundColor = getProperBackgroundColor()
|
||||
val primaryColor = getProperPrimaryColor()
|
||||
if (view is ViewGroup) {
|
||||
updateTextColors(view)
|
||||
} else if (view is MyTextView) {
|
||||
view.setColors(textColor, primaryColor, backgroundColor)
|
||||
}
|
||||
|
||||
if (dialog is MaterialAlertDialogBuilder) {
|
||||
dialog.create().apply {
|
||||
if (titleId != 0) {
|
||||
setTitle(titleId)
|
||||
} else if (titleText.isNotEmpty()) {
|
||||
setTitle(titleText)
|
||||
}
|
||||
|
||||
val lp = window?.attributes
|
||||
lp?.token = windowToken
|
||||
lp?.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG
|
||||
window?.attributes = lp
|
||||
window?.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)
|
||||
|
||||
setView(view)
|
||||
setCancelable(cancelOnTouchOutside)
|
||||
show()
|
||||
|
||||
val bgDrawable = when {
|
||||
isBlackAndWhiteTheme() -> ResourcesCompat.getDrawable(resources, R.drawable.black_dialog_background, theme)
|
||||
baseConfig.isUsingSystemTheme -> ResourcesCompat.getDrawable(resources, R.drawable.dialog_you_background, theme)
|
||||
else -> resources.getColoredDrawableWithColor(R.drawable.dialog_bg, baseConfig.backgroundColor)
|
||||
}
|
||||
|
||||
window?.setBackgroundDrawable(bgDrawable)
|
||||
callback?.invoke(this)
|
||||
}
|
||||
} else {
|
||||
var title: TextView? = null
|
||||
if (titleId != 0 || titleText.isNotEmpty()) {
|
||||
title = LayoutInflater.from(this).inflate(R.layout.dialog_title, null) as TextView
|
||||
title.apply {
|
||||
if (titleText.isNotEmpty()) {
|
||||
text = titleText
|
||||
} else {
|
||||
setText(titleId)
|
||||
}
|
||||
setTextColor(textColor)
|
||||
}
|
||||
}
|
||||
|
||||
// if we use the same primary and background color, use the text color for dialog confirmation buttons
|
||||
val dialogButtonColor = if (primaryColor == baseConfig.backgroundColor) {
|
||||
textColor
|
||||
} else {
|
||||
primaryColor
|
||||
}
|
||||
|
||||
dialog.create().apply {
|
||||
setView(view)
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
setCustomTitle(title)
|
||||
|
||||
val lp = window?.attributes
|
||||
lp?.token = windowToken
|
||||
lp?.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG
|
||||
window?.attributes = lp
|
||||
window?.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)
|
||||
|
||||
setCanceledOnTouchOutside(cancelOnTouchOutside)
|
||||
show()
|
||||
getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(dialogButtonColor)
|
||||
getButton(AlertDialog.BUTTON_NEGATIVE).setTextColor(dialogButtonColor)
|
||||
getButton(AlertDialog.BUTTON_NEUTRAL).setTextColor(dialogButtonColor)
|
||||
|
||||
val bgDrawable = when {
|
||||
isBlackAndWhiteTheme() -> ResourcesCompat.getDrawable(resources, R.drawable.black_dialog_background, theme)
|
||||
baseConfig.isUsingSystemTheme -> ResourcesCompat.getDrawable(resources, R.drawable.dialog_you_background, theme)
|
||||
else -> resources.getColoredDrawableWithColor(R.drawable.dialog_bg, baseConfig.backgroundColor)
|
||||
}
|
||||
|
||||
window?.setBackgroundDrawable(bgDrawable)
|
||||
callback?.invoke(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,18 +61,7 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL
|
|||
inputTypeClass = attribute!!.inputType and TYPE_MASK_CLASS
|
||||
enterKeyType = attribute.imeOptions and (IME_MASK_ACTION or IME_FLAG_NO_ENTER_ACTION)
|
||||
|
||||
val keyboardXml = when (inputTypeClass) {
|
||||
TYPE_CLASS_NUMBER, TYPE_CLASS_DATETIME, TYPE_CLASS_PHONE -> {
|
||||
keyboardMode = KEYBOARD_SYMBOLS
|
||||
R.xml.keys_symbols
|
||||
}
|
||||
else -> {
|
||||
keyboardMode = KEYBOARD_LETTERS
|
||||
getKeyboardLayoutXML()
|
||||
}
|
||||
}
|
||||
|
||||
keyboard = MyKeyboard(this, keyboardXml, enterKeyType)
|
||||
keyboard = getKeyBoard()
|
||||
keyboardView?.setKeyboard(keyboard!!)
|
||||
keyboardView?.setEditorInfo(attribute)
|
||||
updateShiftKeyState()
|
||||
|
@ -220,6 +209,27 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL
|
|||
currentInputConnection?.commitText(text, 0)
|
||||
}
|
||||
|
||||
override fun reloadKeyboard() {
|
||||
val keyboard = getKeyBoard()
|
||||
this.keyboard = keyboard
|
||||
keyboardView?.setKeyboard(keyboard)
|
||||
}
|
||||
|
||||
private fun getKeyBoard(): MyKeyboard {
|
||||
val keyboardXml = when (inputTypeClass) {
|
||||
TYPE_CLASS_NUMBER, TYPE_CLASS_DATETIME, TYPE_CLASS_PHONE -> {
|
||||
keyboardMode = KEYBOARD_SYMBOLS
|
||||
R.xml.keys_symbols
|
||||
}
|
||||
else -> {
|
||||
keyboardMode = KEYBOARD_LETTERS
|
||||
getKeyboardLayoutXML()
|
||||
}
|
||||
}
|
||||
|
||||
return MyKeyboard(this, keyboardXml, enterKeyType)
|
||||
}
|
||||
|
||||
override fun onUpdateSelection(oldSelStart: Int, oldSelEnd: Int, newSelStart: Int, newSelEnd: Int, candidatesStart: Int, candidatesEnd: Int) {
|
||||
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd)
|
||||
if (newSelStart == newSelEnd) {
|
||||
|
|
|
@ -37,6 +37,7 @@ import com.simplemobiletools.keyboard.activities.ManageClipboardItemsActivity
|
|||
import com.simplemobiletools.keyboard.activities.SettingsActivity
|
||||
import com.simplemobiletools.keyboard.adapters.ClipsKeyboardAdapter
|
||||
import com.simplemobiletools.keyboard.adapters.EmojisAdapter
|
||||
import com.simplemobiletools.keyboard.dialogs.ChangeLanguagePopup
|
||||
import com.simplemobiletools.keyboard.extensions.*
|
||||
import com.simplemobiletools.keyboard.helpers.*
|
||||
import com.simplemobiletools.keyboard.helpers.MyKeyboard.Companion.KEYCODE_DELETE
|
||||
|
@ -90,6 +91,11 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
|||
* @param text the string to be displayed.
|
||||
*/
|
||||
fun onText(text: String)
|
||||
|
||||
/**
|
||||
* Called to force the KeyboardView to reload the keyboard
|
||||
*/
|
||||
fun reloadKeyboard()
|
||||
}
|
||||
|
||||
private var mKeyboard: MyKeyboard? = null
|
||||
|
@ -932,7 +938,15 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
|||
}
|
||||
|
||||
val popupKey = mKeys[mCurrentKey]
|
||||
val result = onLongPress(popupKey, me)
|
||||
val result = if (popupKey.code == KEYCODE_EMOJI) {
|
||||
ChangeLanguagePopup(this, onSelect = {
|
||||
mOnKeyboardActionListener?.reloadKeyboard()
|
||||
})
|
||||
true
|
||||
} else {
|
||||
onLongPress(popupKey, me)
|
||||
}
|
||||
|
||||
if (result) {
|
||||
mAbortKey = true
|
||||
showPreview(NOT_A_KEY)
|
||||
|
@ -982,6 +996,10 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
|
|||
override fun onText(text: String) {
|
||||
mOnKeyboardActionListener!!.onText(text)
|
||||
}
|
||||
|
||||
override fun reloadKeyboard() {
|
||||
mOnKeyboardActionListener!!.reloadKeyboard()
|
||||
}
|
||||
}
|
||||
|
||||
val keyboard = if (popupKey.popupCharacters != null) {
|
||||
|
|
16
app/src/main/res/layout/dialog_radio_group.xml
Normal file
16
app/src/main/res/layout/dialog_radio_group.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/dialog_radio_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/dialog_radio_group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/activity_margin"
|
||||
android:paddingBottom="@dimen/normal_margin" />
|
||||
|
||||
</ScrollView>
|
5
app/src/main/res/layout/radio_button_item.xml
Normal file
5
app/src/main/res/layout/radio_button_item.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/dialog_radio_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
|
@ -13,4 +13,11 @@
|
|||
<style name="MyKeyboardViewPopup" parent="MyKeyboard">
|
||||
<item name="keyTextSize">@dimen/preview_text_size</item>
|
||||
</style>
|
||||
|
||||
<style name="MyKeyboard.Alert" parent="Theme.Material3.Light.Dialog.Alert">
|
||||
<item name="colorAccent">@color/color_primary</item>
|
||||
<item name="android:buttonBarNegativeButtonStyle">@style/DialogButtonStyle</item>
|
||||
<item name="android:buttonBarPositiveButtonStyle">@style/DialogButtonStyle</item>
|
||||
<item name="android:buttonBarNeutralButtonStyle">@style/DialogButtonStyle</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in a new issue