0
0
mirror of https://github.com/florisboard/florisboard.git synced 2024-09-20 03:52:18 +02:00

Add internal subtype management with language/layout selection

- The subtype management is done only internally because the default
  Android subtypes don't really allow for dynamically added Subtypes.
  Additionally the official Android docs recommend against using the
  default Subtypes when providing a way to customize the locale/layout
  association.
- Subtypes are always a triple: id/locale/layout, where the user can
  configure both the locale and the layout in the Settings.
- Fallback subtype if none is specified is English/QWERTY.
- Language switch now shows accordingly to the number of subtypes defined.
- Current language name is shown on SpaceBar.
- PrefHelper.Keyboard now provides methods to easily manipulate the
  subtype list and to get the current active subtype.
- Other fixes in KeyView and Looknfeel which get fixed with this commit:
  - Key preview may flicker if the pointer is between the screen edge and
    the first KeyView of the row, due to a indefinite circle between loose
    in interest and giving the interest to the view.
  - Cleanup in LooknfeelFragment.kt
This commit is contained in:
Patrick Goldinger 2020-06-20 18:46:16 +02:00
parent adaa3f0a9c
commit 05ccaeea66
18 changed files with 510 additions and 40 deletions

View File

@ -7,6 +7,7 @@
<application
android:allowBackup="false"
android:extractNativeLibs="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"

View File

@ -27,10 +27,8 @@ import dev.patrickgold.florisboard.ime.text.TextInputManager
import dev.patrickgold.florisboard.ime.text.key.KeyCode
import dev.patrickgold.florisboard.ime.text.key.KeyData
import dev.patrickgold.florisboard.settings.SettingsMainActivity
import dev.patrickgold.florisboard.util.ViewLayoutUtils
import dev.patrickgold.florisboard.util.getBooleanFromAttr
import dev.patrickgold.florisboard.util.getColorFromAttr
import dev.patrickgold.florisboard.util.refreshLayoutOf
import dev.patrickgold.florisboard.util.*
import java.util.*
/**
* Variable which holds the current [FlorisBoard] instance. To get this instance from another
@ -44,6 +42,7 @@ private var florisboardInstance: FlorisBoard? = null
*/
class FlorisBoard : InputMethodService() {
lateinit var activeSubtype: Subtype
private var audioManager: AudioManager? = null
val context: Context
get() = inputView?.context ?: this
@ -78,6 +77,8 @@ class FlorisBoard : InputMethodService() {
prefs.initDefaultPreferences()
prefs.sync()
activeSubtype = prefs.keyboard.fetchActiveSubtype() ?: Subtype(-1, Locale.ENGLISH, "qwerty")
currentThemeResId = prefs.theme.getSelectedThemeResId()
setTheme(currentThemeResId)
@ -145,6 +146,8 @@ class FlorisBoard : InputMethodService() {
prefs.sync()
updateThemeIfNecessary()
updateOneHandedPanelVisibility()
activeSubtype = prefs.keyboard.fetchActiveSubtype() ?: Subtype(-1, Locale.ENGLISH, "qwerty")
onSubtypeChanged(activeSubtype)
setActiveInput(R.id.text_input)
super.onWindowShown()
@ -332,11 +335,20 @@ class FlorisBoard : InputMethodService() {
}
/**
* TODO: evaluate the boolean based on the language prefs
* @return If the language switch should be shown
*/
fun shouldShowLanguageSwitch(): Boolean {
return false
return prefs.keyboard.subtypes.size > 1
}
fun switchToNextSubtype() {
activeSubtype = prefs.keyboard.switchToNextSubtype() ?: Subtype(-1, Locale.ENGLISH, "qwerty")
onSubtypeChanged(activeSubtype)
}
private fun onSubtypeChanged(newSubtype: Subtype) {
textInputManager.onSubtypeChanged(newSubtype)
mediaInputManager.onSubtypeChanged(newSubtype)
}
fun setActiveInput(type: Int) {
@ -405,6 +417,28 @@ class FlorisBoard : InputMethodService() {
}, 0)
}
data class Subtype(
var id: Int,
var locale: Locale,
var layoutName: String
) {
companion object {
fun fromString(string: String): Subtype {
val data = string.split("/")
if (data.size != 3) {
throw Exception("Given string is malformed...")
} else {
val locale = LocaleUtils.stringToLocale(data[1])
return Subtype(data[0].toInt(), locale, data[2])
}
}
}
override fun toString(): String {
return "$id/$locale/$layoutName"
}
}
interface EventListener {
fun onCreate() {}
fun onCreateInputView() {}
@ -428,5 +462,7 @@ class FlorisBoard : InputMethodService() {
candidatesStart: Int,
candidatesEnd: Int
) {}
fun onSubtypeChanged(newSubtype: Subtype) {}
}
}

View File

@ -21,6 +21,9 @@ import android.content.SharedPreferences
import android.provider.Settings
import androidx.preference.PreferenceManager
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.util.LocaleUtils
import java.util.*
import kotlin.collections.HashMap
/**
* Helper class for an organized access to the shared preferences.
@ -34,6 +37,7 @@ class PrefHelper(
private val cacheString: HashMap<String, String> = hashMapOf()
val advanced = Advanced(this)
val keyboard = Keyboard(this)
val looknfeel = Looknfeel(this)
val theme = Theme(this)
@ -110,9 +114,11 @@ class PrefHelper(
*/
fun initDefaultPreferences() {
PreferenceManager.setDefaultValues(context, R.xml.prefs_advanced, true)
PreferenceManager.setDefaultValues(context, R.xml.prefs_correction, true)
PreferenceManager.setDefaultValues(context, R.xml.prefs_keyboard, true)
PreferenceManager.setDefaultValues(context, R.xml.prefs_looknfeel, true)
PreferenceManager.setDefaultValues(context, R.xml.prefs_theme, true)
//setPref(Keyboard.SUBTYPES, "")
}
/**
@ -149,6 +155,111 @@ class PrefHelper(
private set
}
/**
* Wrapper class for keyboard preferences.
*/
class Keyboard(private val prefHelper: PrefHelper) {
companion object {
const val ACTIVE_SUBTYPE_ID = "keyboard__active_subtype_id"
const val SUBTYPES = "keyboard__subtypes"
}
private var activeSubtypeId: Int
get() = prefHelper.getPref(ACTIVE_SUBTYPE_ID, -1)
private set(v) = prefHelper.setPref(ACTIVE_SUBTYPE_ID, v)
var subtypes: List<FlorisBoard.Subtype>
get() {
val listRaw = prefHelper.getPref(SUBTYPES, "")
return if (listRaw == "") {
listOf()
} else {
listRaw.split(";").map {
FlorisBoard.Subtype.fromString(it)
}
}
}
set(value) = prefHelper.setPref(SUBTYPES, value.joinToString(";"))
private fun addSubtype(subtype: FlorisBoard.Subtype) {
val oldListRaw = prefHelper.getPref(SUBTYPES, "")
if (oldListRaw.isBlank()) {
prefHelper.setPref(SUBTYPES, "$subtype")
} else {
prefHelper.setPref(SUBTYPES, "$oldListRaw;$subtype")
}
}
fun addSubtype(locale: Locale, layoutName: String) {
addSubtype(FlorisBoard.Subtype(
locale.hashCode() + layoutName.hashCode(),
locale,
layoutName
))
}
fun fetchActiveSubtype(): FlorisBoard.Subtype? {
for (s in subtypes) {
if (s.id == activeSubtypeId) {
return s
}
}
val subtypes = this.subtypes
return if (subtypes.isNotEmpty()) {
activeSubtypeId = subtypes[0].id
subtypes[0]
} else {
activeSubtypeId = -1
null
}
}
fun getSubtypeById(id: Int): FlorisBoard.Subtype? {
for (s in subtypes) {
if (s.id == id) {
return s
}
}
return null
}
fun removeSubtype(subtype: FlorisBoard.Subtype) {
val oldListRaw = prefHelper.getPref(SUBTYPES, "")
var newListRaw = ""
for (s in oldListRaw.split(";")) {
if (s != subtype.toString()) {
newListRaw += "$s;"
}
}
if (newListRaw.isNotEmpty()) {
newListRaw = newListRaw.substring(0, newListRaw.length - 1)
}
prefHelper.setPref(SUBTYPES, newListRaw)
if (subtype.id == activeSubtypeId) {
fetchActiveSubtype()
}
}
fun switchToNextSubtype(): FlorisBoard.Subtype? {
val subtypes = this.subtypes
val activeSubtype = fetchActiveSubtype() ?: return null
var triggerNextSubtype = false
var newActiveSubtype: FlorisBoard.Subtype? = null
for (s in subtypes) {
if (triggerNextSubtype) {
triggerNextSubtype = false
newActiveSubtype = s
} else if (s == activeSubtype) {
triggerNextSubtype = true
}
}
if (triggerNextSubtype) {
newActiveSubtype = subtypes[0]
}
return if (newActiveSubtype == null) {
activeSubtypeId = -1
null
} else {
activeSubtypeId = newActiveSubtype.id
newActiveSubtype
}
}
}
/**
* Wrapper class for looknfeel preferences.
*/

View File

@ -26,7 +26,6 @@ import android.view.inputmethod.EditorInfo
import android.view.inputmethod.ExtractedTextRequest
import android.view.inputmethod.InputMethodManager
import android.widget.LinearLayout
import android.widget.Toast
import android.widget.ViewFlipper
import dev.patrickgold.florisboard.BuildConfig
import dev.patrickgold.florisboard.R
@ -104,7 +103,7 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(),
override fun onCreate() {
if (BuildConfig.DEBUG) Log.i(this::class.simpleName, "onCreate()")
layoutManager.autoFetchAssociationsFromPrefs()
layoutManager.autoFetchAssociationsFromPrefs(florisboard.prefs)
smartbarManager = SmartbarManager.getInstance()
}
@ -208,6 +207,10 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(),
smartbarManager.onFinishInputView()
}
override fun onWindowShown() {
keyboardViews[KeyboardMode.CHARACTERS]?.updateVisibility()
}
/**
* Gets [activeKeyboardMode].
*
@ -230,6 +233,13 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(),
smartbarManager.activeContainerId = smartbarManager.getPreferredContainerId()
}
override fun onSubtypeChanged(newSubtype: FlorisBoard.Subtype) {
layoutManager.autoFetchAssociationsFromPrefs(florisboard.prefs)
val keyboardView = keyboardViews[KeyboardMode.CHARACTERS]
keyboardView?.setKeyboardMode(KeyboardMode.CHARACTERS)
keyboardView?.updateVisibility()
}
/**
* Main logic point for processing cursor updates as well as parsing the current composing word
* and passing this info on to the [SmartbarManager] to turn it into candidate suggestions.
@ -451,10 +461,7 @@ class TextInputManager private constructor() : CoroutineScope by MainScope(),
when (keyData.code) {
KeyCode.DELETE -> handleDelete()
KeyCode.ENTER -> handleEnter()
KeyCode.LANGUAGE_SWITCH -> {
Toast.makeText(florisboard, "[NYI]: Language switch",
Toast.LENGTH_SHORT).show()
}
KeyCode.LANGUAGE_SWITCH -> florisboard.switchToNextSubtype()
KeyCode.SHIFT -> handleShift()
KeyCode.SHOW_INPUT_METHOD_PICKER -> {
val im =

View File

@ -217,8 +217,11 @@ class KeyView(
keyboardView.dismissActiveKeyViewReference()
}
} else {
if (event.x < -0.1f * measuredWidth || event.x > 1.1f * measuredWidth
|| event.y < -0.35f * measuredHeight || event.y > 1.35f * measuredHeight
val parent = parent as ViewGroup
if ((event.x < -0.1f * measuredWidth && parent.children.first() != this)
|| (event.x > 1.1f * measuredWidth && parent.children.last() != this)
|| event.y < -0.35f * measuredHeight
|| event.y > 1.35f * measuredHeight
) {
if (!shouldBlockNextKeyCode) {
keyboardView.dismissActiveKeyViewReference()
@ -480,6 +483,9 @@ class KeyView(
drawable = getDrawable(context, R.drawable.ic_space_bar)
drawableColor = getColorFromAttr(context, R.attr.key_fgColor)
}
KeyboardMode.CHARACTERS -> {
label = florisboard?.activeSubtype?.locale?.displayName
}
else -> {}
}
}
@ -535,12 +541,15 @@ class KeyView(
// Draw label
val label = label
if (label != null) {
if (data.code == KeyCode.VIEW_NUMERIC || data.code == KeyCode.VIEW_NUMERIC_ADVANCED) {
if (data.code == KeyCode.VIEW_NUMERIC || data.code == KeyCode.VIEW_NUMERIC_ADVANCED
|| data.code == KeyCode.SPACE) {
labelPaint.textSize = resources.getDimension(R.dimen.key_numeric_textSize)
} else {
labelPaint.textSize = resources.getDimension(R.dimen.key_textSize)
}
labelPaint.color = getColorFromAttr(context, R.attr.key_fgColor)
labelPaint.alpha = if (keyboardView.computedLayout?.mode == KeyboardMode.CHARACTERS &&
data.code == KeyCode.SPACE) { 120 } else { 255 }
val isPortrait =
resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT
if (keyboardView.prefs.looknfeel.oneHandedMode != "off" && isPortrait) {

View File

@ -3,6 +3,8 @@ package dev.patrickgold.florisboard.ime.text.layout
import android.content.Context
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import dev.patrickgold.florisboard.ime.core.FlorisBoard
import dev.patrickgold.florisboard.ime.core.PrefHelper
import dev.patrickgold.florisboard.ime.text.key.KeyData
import dev.patrickgold.florisboard.ime.text.key.KeyTypeAdapter
import dev.patrickgold.florisboard.ime.text.key.KeyVariationAdapter
@ -25,9 +27,10 @@ class LayoutManager(private val context: Context) {
* This method automatically fetches the current user selected keyboard layout prefs from
* the shared preferences and sets the associations for each layout type.
*/
fun autoFetchAssociationsFromPrefs() {
fun autoFetchAssociationsFromPrefs(prefs: PrefHelper) {
// TODO: Fetch current layout preferences instead of using dev constants
associate(LayoutType.CHARACTERS, "qwerty")
val activeSubtype = prefs.keyboard.fetchActiveSubtype()
associate(LayoutType.CHARACTERS, activeSubtype?.layoutName ?: "qwerty")
associate(LayoutType.CHARACTERS_MOD, "default")
associate(LayoutType.EXTENSION, "number_row")
associate(LayoutType.NUMERIC, "default")

View File

@ -1,15 +1,32 @@
package dev.patrickgold.florisboard.settings
import android.app.AlertDialog
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.*
import androidx.appcompat.widget.AppCompatButton
import androidx.appcompat.widget.AppCompatSpinner
import androidx.appcompat.widget.AppCompatTextView
import androidx.fragment.app.Fragment
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.ime.core.PrefHelper
import dev.patrickgold.florisboard.util.LocaleUtils
import java.util.*
class KeyboardFragment : Fragment() {
private lateinit var prefs: PrefHelper
private lateinit var rootView: LinearLayout
private lateinit var subtypeListView: LinearLayout
private lateinit var subtypeAddButton: AppCompatButton
private lateinit var subtypeNotConfiguredView: AppCompatTextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
prefs = (activity as SettingsMainActivity).prefs
}
override fun onCreateView(
inflater: LayoutInflater,
@ -17,14 +34,102 @@ class KeyboardFragment : Fragment() {
savedInstanceState: Bundle?
): View? {
rootView = inflater.inflate(R.layout.settings_fragment_keyboard, container, false) as LinearLayout
subtypeListView = rootView.findViewById(R.id.settings__keyboard__subtype_list)
subtypeNotConfiguredView = rootView.findViewById(R.id.settings__keyboard__subtype_not_conf_warning)
subtypeAddButton = rootView.findViewById(R.id.subtype_add_btn)
subtypeAddButton.setOnClickListener { showAddSubtypeDialog() }
updateSubtypeListView()
val transaction = childFragmentManager.beginTransaction()
transaction.replace(
R.id.settings__keyboard__frame_container,
SettingsMainActivity.PrefFragment.createFromResource(R.xml.prefs_keyboard)
SettingsMainActivity.PrefFragment.createFromResource(R.xml.prefs_correction)
)
transaction.commit()
return rootView
}
private fun showAddSubtypeDialog() {
val dialogView =
View.inflate(context, R.layout.settings_fragment_keyboard_subtype_dialog, null)
val languageSpinner = dialogView.findViewById<AppCompatSpinner>(R.id.language_dropdown)
val layoutSpinner = dialogView.findViewById<AppCompatSpinner>(R.id.layout_dropdown)
AlertDialog.Builder(context).apply {
setTitle(R.string.settings__keyboard__subtype_add_title)
setCancelable(true)
setView(dialogView)
setPositiveButton(R.string.settings__keyboard__subtype_add) { _, _ ->
val languageCode = languageSpinner.selectedItem.toString()
val layoutName = layoutSpinner.selectedItem.toString()
prefs.keyboard.addSubtype(LocaleUtils.stringToLocale(languageCode), layoutName)
updateSubtypeListView()
}
setNegativeButton(R.string.settings__keyboard__subtype_cancel) { _, _ -> }
create()
show()
}
}
@Suppress("UNCHECKED_CAST")
private fun showEditSubtypeDialog(id: Int) {
var subtypeIndex = -1
val subtypes = prefs.keyboard.subtypes
for ((i, subtype) in subtypes.withIndex()) {
if (subtype.id == id) {
subtypeIndex = i
break
}
}
if (subtypeIndex < 0) {
return
}
val dialogView =
View.inflate(context, R.layout.settings_fragment_keyboard_subtype_dialog, null)
val languageSpinner = dialogView.findViewById<AppCompatSpinner>(R.id.language_dropdown)
languageSpinner.setSelection((languageSpinner.adapter as ArrayAdapter<String>).getPosition(subtypes[subtypeIndex].locale.toString()))
val layoutSpinner = dialogView.findViewById<AppCompatSpinner>(R.id.layout_dropdown)
layoutSpinner.setSelection((layoutSpinner.adapter as ArrayAdapter<String>).getPosition(subtypes[subtypeIndex].layoutName))
AlertDialog.Builder(context).apply {
setTitle(R.string.settings__keyboard__subtype_edit_title)
setCancelable(true)
setView(dialogView)
setPositiveButton(R.string.settings__keyboard__subtype_apply) { _, _ ->
val languageCode = languageSpinner.selectedItem.toString()
val layoutName = layoutSpinner.selectedItem.toString()
subtypes[subtypeIndex].locale = LocaleUtils.stringToLocale(languageCode)
subtypes[subtypeIndex].layoutName = layoutName
prefs.keyboard.subtypes = subtypes
updateSubtypeListView()
}
setNeutralButton(R.string.settings__keyboard__subtype_delete) { _, _ ->
prefs.keyboard.removeSubtype(subtypes[subtypeIndex])
updateSubtypeListView()
}
setNegativeButton(R.string.settings__keyboard__subtype_cancel) { _, _ -> }
create()
show()
}
}
private fun updateSubtypeListView() {
val subtypes = prefs.keyboard.subtypes
subtypeListView.removeAllViews()
if (subtypes.isEmpty()) {
subtypeNotConfiguredView.visibility = View.VISIBLE
} else {
subtypeNotConfiguredView.visibility = View.GONE
for (subtype in subtypes) {
val itemView =
View.inflate(context, R.layout.settings_fragment_keyboard_subtype_list_item, null)
itemView.findViewById<TextView>(R.id.titleText)?.text =
subtype.locale.displayName
itemView.findViewById<TextView>(R.id.captionText)?.text =
subtype.layoutName.toUpperCase(Locale.getDefault())
itemView.setOnClickListener { showEditSubtypeDialog(subtype.id) }
subtypeListView.addView(itemView)
}
}
}
}

View File

@ -7,7 +7,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.ime.core.PrefHelper
import dev.patrickgold.florisboard.ime.text.keyboard.KeyboardMode
@ -17,7 +16,7 @@ import kotlinx.coroutines.*
class LooknfeelFragment : Fragment(), CoroutineScope by MainScope() {
lateinit var keyboardView: KeyboardView
private lateinit var keyboardView: KeyboardView
lateinit var prefs: PrefHelper
private lateinit var rootView: LinearLayout
@ -37,7 +36,7 @@ class LooknfeelFragment : Fragment(), CoroutineScope by MainScope() {
launch(Dispatchers.Default) {
val themeContext = ContextThemeWrapper(context, prefs.theme.getSelectedThemeResId())
val layoutManager = LayoutManager(themeContext)
layoutManager.autoFetchAssociationsFromPrefs()
layoutManager.autoFetchAssociationsFromPrefs(prefs)
keyboardView = KeyboardView(themeContext)
keyboardView.prefs = prefs
keyboardView.isPreviewMode = true

View File

@ -0,0 +1,33 @@
/*
* Copyright (C) 2020 Patrick Goldinger
*
* 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.
*/
package dev.patrickgold.florisboard.util
import java.util.*
object LocaleUtils {
fun stringToLocale(string: String): Locale {
return when {
string.contains("_") -> {
val lc = string.split("_")
Locale(lc[0], lc[1])
}
else -> {
Locale(string)
}
}
}
}

View File

@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#000000" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>

View File

@ -9,10 +9,43 @@
android:layout_marginTop="16dp"
android:layout_marginBottom="0dp">
<TextView
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TODO: implement language and layout selection" />
android:orientation="vertical">
<TextView
android:id="@+id/settings__keyboard__subtype_not_conf_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="16dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:padding="8dp"
android:background="@drawable/shape_rect_rounded"
android:backgroundTint="#F8F808"
android:text="@string/settings__keyboard__subtype_no_subtypes_configured_warning"
android:textColor="#000000"/>
<LinearLayout
android:id="@+id/settings__keyboard__subtype_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
<Button
android:id="@+id/subtype_add_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:textAllCaps="false"
android:text="@string/settings__keyboard__subtype_add_title"
android:drawableStart="@drawable/ic_add"
android:drawablePadding="8dp"
android:drawableTint="?colorAccent"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
@ -20,6 +53,6 @@
<RelativeLayout
android:id="@+id/settings__keyboard__frame_container"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"/>
</LinearLayout>

View File

@ -0,0 +1,60 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- TODO: improve the design and UX of this layout -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings__keyboard__subtype_locale"/>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/language_dropdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/supported_languages"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings__keyboard__subtype_layout"/>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/layout_dropdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/valid_layout_names"/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,28 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="64dp"
android:orientation="vertical"
android:padding="16dp"
android:clickable="true"
android:focusable="true"
android:background="?selectableItemBackground">
<TextView
android:id="@+id/titleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textStyle="bold"
tools:text="Title"/>
<TextView
android:id="@+id/captionText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textStyle="normal"
tools:text="Caption"/>
</LinearLayout>

View File

@ -0,0 +1,19 @@
<!-- TODO: properly configure this temporary file -->
<!-- NOTE: The specified layouts and languages currently do not represent what the keyboard
really supports!! -->
<resources>
<string-array name="valid_layout_names">
<item>qwerty</item>
<item>qwertz</item>
</string-array>
<string-array name="supported_languages">
<item>en_US</item>
<item>en_UK</item>
<item>en_CA</item>
<item>en_AU</item>
<item>de_DE</item>
<item>de_AT</item>
<item>de_CH</item>
</string-array>
</resources>

View File

@ -53,8 +53,18 @@
<string name="settings__home__title">Welcome to %s</string>
<string name="settings__keyboard__title">Keyboard &amp; Input</string>
<string name="pref__keyboard__group_text_correction__label">Text correction</string>
<string name="settings__keyboard__title">Keyboard &amp; Text Correction</string>
<string name="settings__keyboard__subtype_no_subtypes_configured_warning">It seems that you haven\'t configured any subtypes. As a fallback the subtype English/QWERTY will be used!</string>
<string name="settings__keyboard__subtype_add">Add</string>
<string name="settings__keyboard__subtype_add_title">Add subtype</string>
<string name="settings__keyboard__subtype_apply">Apply</string>
<string name="settings__keyboard__subtype_cancel">Cancel</string>
<string name="settings__keyboard__subtype_delete">Delete</string>
<string name="settings__keyboard__subtype_edit_title">Edit subtype</string>
<string name="settings__keyboard__subtype_locale">Locale</string>
<string name="settings__keyboard__subtype_layout">Keyboard layout</string>
<string name="pref__correction__group_suggestions__label">Suggestions</string>
<string name="pref__correction__group_corrections__label">Corrections</string>
<string name="settings__looknfeel__title">Look &amp; feel</string>
<string name="pref__looknfeel__group_layout__label">Layout</string>

View File

@ -1,9 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<input-method xmlns:android="https://schemas.android.com/apk/res/android"
android:icon="@mipmap/ic_launcher"
android:settingsActivity="dev.patrickgold.florisboard.settings.SettingsMainActivity">
<subtype
android:label="@string/subtype_en_US"
android:imeSubtypeLocale="en_US"
android:imeSubtypeMode="keyboard" />
</input-method>
android:isDefault="false"
android:settingsActivity="dev.patrickgold.florisboard.settings.SettingsMainActivity" />

View File

@ -0,0 +1,21 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
app:iconSpaceReserved="false"
app:title="@string/pref__correction__group_suggestions__label">
<!-- TODO: implement text correction prefs -->
</PreferenceCategory>
<PreferenceCategory
app:iconSpaceReserved="false"
app:title="@string/pref__correction__group_corrections__label">
<!-- TODO: implement text correction prefs -->
</PreferenceCategory>
</PreferenceScreen>

View File

@ -2,12 +2,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory
app:iconSpaceReserved="false"
app:title="@string/pref__keyboard__group_text_correction__label">
<!-- TODO: implement text correction prefs -->
</PreferenceCategory>
</PreferenceScreen>