1
0
Fork 0

vibration on keypress option

This commit is contained in:
sspanak 2024-06-20 17:40:49 +03:00 committed by Dimo Karaivanov
parent 390085e4b3
commit d66a0c3f21
27 changed files with 225 additions and 48 deletions

View file

@ -24,10 +24,11 @@ public class AppearanceScreen extends BaseScreenFragment {
private void createMainSection() {
(new ItemStatusIcon(findPreference(ItemStatusIcon.NAME), activity.getSettings())).populate();
ItemHapticFeedback hapticFeedback = (new ItemHapticFeedback(findPreference(ItemHapticFeedback.NAME), activity.getSettings())).populate();
ItemDropDown[] items = {
new ItemSelectTheme(findPreference(ItemSelectTheme.NAME), activity),
new ItemSelectLayoutType(findPreference(ItemSelectLayoutType.NAME), activity),
new ItemSelectLayoutType(findPreference(ItemSelectLayoutType.NAME), activity, hapticFeedback::populate),
new ItemSelectSettingsFontSize(findPreference(ItemSelectSettingsFontSize.NAME), this)
};

View file

@ -0,0 +1,37 @@
package io.github.sspanak.tt9.preferences.screens.appearance;
import androidx.annotation.NonNull;
import androidx.preference.Preference;
import androidx.preference.SwitchPreferenceCompat;
import io.github.sspanak.tt9.preferences.items.ItemClickable;
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
class ItemHapticFeedback extends ItemClickable {
static final String NAME = "pref_haptic_feedback";
private final SettingsStore settings;
ItemHapticFeedback(Preference item, @NonNull SettingsStore settings) {
super(item);
this.settings = settings;
}
@Override
protected boolean onClick(Preference p) {
return true;
}
ItemHapticFeedback populate() {
return populate(settings.getMainViewLayout());
}
ItemHapticFeedback populate(int mainViewLayout) {
if (item != null) {
item.setEnabled(mainViewLayout == SettingsStore.LAYOUT_NUMPAD || mainViewLayout == SettingsStore.LAYOUT_SMALL);
((SwitchPreferenceCompat) item).setChecked(settings.getHapticFeedback());
}
return this;
}
}

View file

@ -1,6 +1,7 @@
package io.github.sspanak.tt9.preferences.screens.appearance;
import androidx.preference.DropDownPreference;
import androidx.preference.Preference;
import java.util.LinkedHashMap;
@ -8,15 +9,18 @@ import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.preferences.PreferencesActivity;
import io.github.sspanak.tt9.preferences.items.ItemDropDown;
import io.github.sspanak.tt9.preferences.settings.SettingsUI;
import io.github.sspanak.tt9.util.ConsumerCompat;
public class ItemSelectLayoutType extends ItemDropDown {
public static final String NAME = "pref_layout_type";
private final PreferencesActivity activity;
private final ConsumerCompat<Integer> onChange;
public ItemSelectLayoutType(DropDownPreference item, PreferencesActivity activity) {
public ItemSelectLayoutType(DropDownPreference item, PreferencesActivity activity, ConsumerCompat<Integer> onChange) {
super(item);
this.activity = activity;
this.onChange = onChange;
}
public ItemDropDown populate() {
@ -31,4 +35,12 @@ public class ItemSelectLayoutType extends ItemDropDown {
return this;
}
@Override
protected boolean onClick(Preference preference, Object newKey) {
if (onChange != null) {
onChange.accept(Integer.parseInt(newKey.toString()));
}
return super.onClick(preference, newKey);
}
}

View file

@ -32,6 +32,10 @@ public class SettingsUI extends SettingsTyping {
}
}
public boolean getHapticFeedback() {
return prefs.getBoolean("pref_haptic_feedback", true);
}
public int getSettingsFontSize() {
int defaultSize = DeviceInfo.isQinF21() || DeviceInfo.isLgX100S() ? FONT_SIZE_LARGE : FONT_SIZE_DEFAULT;
return getStringifiedInt("pref_font_size", defaultSize);

View file

@ -8,6 +8,7 @@ import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.languages.LanguageKind;
public class SoftBackspaceKey extends SoftKey {
private boolean hold;
public SoftBackspaceKey(Context context) {
super(context);
@ -23,11 +24,25 @@ public class SoftBackspaceKey extends SoftKey {
@Override
final protected boolean handlePress() {
return handleHold();
super.handlePress();
hold = false;
return deleteText();
}
@Override
final protected boolean handleHold() {
final protected void handleHold() {
hold = true;
deleteText();
}
@Override
final protected boolean handleRelease() {
vibrate(hold ? Vibration.getReleaseVibration() : Vibration.getNoVibration());
hold = false;
return true;
}
private boolean deleteText() {
if (validateTT9Handler() && !tt9.onBackspace()) {
// Limited or special numeric field (e.g. formatted money or dates) cannot always return
// the text length, therefore onBackspace() seems them as empty and does nothing. This results
@ -39,11 +54,6 @@ public class SoftBackspaceKey extends SoftKey {
return false;
}
@Override
final protected boolean handleRelease() {
return false;
}
@Override
protected int getNoEmojiTitle() {
return R.string.virtual_key_del;

View file

@ -16,18 +16,18 @@ public class SoftFilterKey extends SoftKey {
}
@Override
protected boolean handleHold() {
if (!validateTT9Handler()) {
return false;
protected void handleHold() {
preventRepeat();
if (validateTT9Handler() && tt9.onKeyFilterClear(false)) {
vibrate(Vibration.getHoldVibration());
}
return tt9.onKeyFilterClear(false);
}
@Override
protected boolean handleRelease() {
boolean multiplePress = getLastPressedKey() == getId();
return tt9.onKeyFilterSuggestions(false, multiplePress);
return
validateTT9Handler()
&& tt9.onKeyFilterSuggestions(false, getLastPressedKey() == getId());
}
@Override

View file

@ -19,15 +19,13 @@ public class SoftInputModeKey extends SoftKey {
}
@Override
protected boolean handleHold() {
protected void handleHold() {
preventRepeat();
if (validateTT9Handler()) {
vibrate(Vibration.getHoldVibration());
tt9.changeKeyboard();
return true;
}
return false;
}
@Override

View file

@ -9,6 +9,7 @@ import android.text.Spanned;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.util.AttributeSet;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
@ -36,14 +37,17 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
public SoftKey(Context context) {
super(context);
setHapticFeedbackEnabled(false);
}
public SoftKey(Context context, AttributeSet attrs) {
super(context, attrs);
setHapticFeedbackEnabled(false);
}
public SoftKey(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setHapticFeedbackEnabled(false);
}
@ -51,12 +55,14 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
this.tt9 = tt9;
}
public void setDarkTheme(boolean darkEnabled) {
int textColor = ContextCompat.getColor(
getContext(),
darkEnabled ? R.color.dark_button_text : R.color.button_text
);
setTextColor(textColor);
protected boolean validateTT9Handler() {
if (tt9 == null) {
Logger.w(LOG_TAG, "Traditional T9 handler is not set. Ignoring key press.");
return false;
}
return true;
}
@ -72,6 +78,7 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
}
}
@Override
public boolean onTouch(View view, MotionEvent event) {
super.onTouchEvent(event);
@ -81,18 +88,18 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
if (action == MotionEvent.ACTION_DOWN) {
return handlePress();
} else if (action == MotionEvent.ACTION_UP) {
preventRepeat();
if (!repeat) {
if (!repeat || hold) {
hold = false;
boolean result = handleRelease();
lastPressedKey = getId();
return result;
}
repeat = false;
}
return false;
}
@Override
public boolean onLongClick(View view) {
hold = true;
@ -103,6 +110,7 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
return true;
}
/**
* repeatOnLongPress
* Repeatedly calls "handleHold()" upon holding the respective SoftKey, to simulate physical keyboard behavior.
@ -122,6 +130,7 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
}
}
/**
* preventRepeat
* Prevents "handleHold()" from being called repeatedly when the SoftKey is being held.
@ -131,17 +140,23 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
repeatHandler.removeCallbacks(this::repeatOnLongPress);
}
protected static int getLastPressedKey() {
return lastPressedKey;
}
protected boolean handlePress() {
if (validateTT9Handler()) {
vibrate(Vibration.getPressVibration(this));
}
return false;
}
protected boolean handleHold() {
return false;
}
protected void handleHold() {}
protected boolean handleRelease() {
if (!validateTT9Handler()) {
@ -149,29 +164,29 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
}
int keyId = getId();
if (keyId == R.id.soft_key_command_palette) return tt9.onKeyCommandPalette(false);
if (keyId == R.id.soft_key_settings) { tt9.showSettings(); return true; }
if (keyId == R.id.soft_key_voice_input) { tt9.toggleVoiceInput(); return true; }
return false;
}
protected boolean validateTT9Handler() {
if (tt9 == null) {
Logger.w(LOG_TAG, "Traditional T9 handler is not set. Ignoring key press.");
return false;
}
return true;
public void setDarkTheme(boolean darkEnabled) {
int textColor = ContextCompat.getColor(
getContext(),
darkEnabled ? R.color.dark_button_text : R.color.button_text
);
setTextColor(textColor);
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
setTextColor(getTextColors().withAlpha(enabled ? 255 : 80));
}
/**
* getTitle
* Generates the name of the key, for example: "OK", "Backspace", "1", etc...
@ -180,6 +195,7 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
return null;
}
/**
* getNoEmojiTitle
* Generates a text representation of the key title, when emojis are not supported and getTitle()
@ -187,6 +203,7 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
*/
protected int getNoEmojiTitle() { return 0; }
/**
* getSubTitle
* Generates a String describing what the key does.
@ -198,6 +215,7 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
return null;
}
/**
* Returns a meaningful key title depending on the current emoji support.
*/
@ -210,6 +228,7 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
}
}
/**
* render
* Sets the key label using "getTitle()" and "getSubtitle()" or if they both
@ -248,4 +267,11 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
setText(sb);
}
protected void vibrate(int vibrationType) {
if (tt9 != null && tt9.getSettings().getHapticFeedback() && vibrationType != Vibration.getNoVibration()) {
getRootView().performHapticFeedback(vibrationType, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
}
}

View file

@ -6,17 +6,36 @@ import android.util.AttributeSet;
import io.github.sspanak.tt9.R;
public class SoftKeyArrow extends SoftKey {
private boolean hold;
public SoftKeyArrow(Context context) { super(context); }
public SoftKeyArrow(Context context, AttributeSet attrs) { super(context, attrs); }
public SoftKeyArrow(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
@Override
protected boolean handleRelease() {
return handleHold();
protected boolean handlePress() {
hold = false;
return super.handlePress();
}
@Override
protected boolean handleHold() {
protected void handleHold() {
hold = true;
moveCursor();
}
@Override
protected boolean handleRelease() {
if (hold) {
hold = false;
vibrate(Vibration.getReleaseVibration());
return true;
} else {
return moveCursor();
}
}
private boolean moveCursor() {
if (!validateTT9Handler()) {
return false;
}

View file

@ -10,6 +10,15 @@ public class SoftKeySettings extends SoftKey {
public SoftKeySettings(Context context, AttributeSet attrs) { super(context, attrs); }
public SoftKeySettings(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
@Override
protected boolean handleRelease() {
if (validateTT9Handler()) {
tt9.showSettings();
return true;
}
return false;
}
@Override
protected int getNoEmojiTitle() {

View file

@ -28,18 +28,17 @@ public class SoftNumberKey extends SoftKey {
}
@Override
protected boolean handleHold() {
protected void handleHold() {
int keyCode = Key.numberToCode(getUpsideDownNumber(getId()));
if (keyCode < 0 || !validateTT9Handler()) {
return false;
return;
}
preventRepeat();
vibrate(Vibration.getHoldVibration());
tt9.onKeyLongPress(keyCode, new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
tt9.onKeyUp(keyCode, new KeyEvent(KeyEvent.ACTION_UP, keyCode));
return true;
}
@Override

View file

@ -21,7 +21,7 @@ public class SoftPunctuationKey extends SoftKey {
@Override
protected boolean handleRelease() {
return tt9.onText(getKeyChar(), false);
return validateTT9Handler() && tt9.onText(getKeyChar(), false);
}
@Override

View file

@ -0,0 +1,31 @@
package io.github.sspanak.tt9.ui.main.keys;
import android.os.Build;
import android.view.HapticFeedbackConstants;
class Vibration {
static int getNoVibration() {
return -1;
}
static int getPressVibration(SoftKey key) {
return key instanceof SoftNumberKey ? HapticFeedbackConstants.KEYBOARD_TAP : HapticFeedbackConstants.VIRTUAL_KEY;
}
static int getHoldVibration() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return HapticFeedbackConstants.CONFIRM;
} else {
return HapticFeedbackConstants.VIRTUAL_KEY;
}
}
static int getReleaseVibration() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
return HapticFeedbackConstants.KEYBOARD_RELEASE;
} else {
return HapticFeedbackConstants.VIRTUAL_KEY;
}
}
}

View file

@ -141,4 +141,6 @@
<string name="voice_input_error_no_network">Няма връзка с интернет</string>
<string name="voice_input_error_network_failed">Проблем с мрежовата връзка</string>
<string name="voice_input_stopping">Изключване на микрофона…</string>
<string name="pref_haptic_feedback_summary">Вибрация при натискане на виртуален клавиш</string>
<string name="pref_haptic_feedback">Вибрация</string>
</resources>

View file

@ -21,6 +21,7 @@
<string name="pref_layout_small">Funktionstasten</string>
<string name="pref_layout_stealth">Unsichtbarer Modus</string>
<string name="pref_layout_tray">Nur Wortliste</string>
<string name="pref_haptic_feedback_summary">Vibrieren beim Drücken einer virtuellen Taste.</string>
<string name="pref_help">Hilfe</string>
<string name="pref_dark_theme">Dunkles Thema</string>
<string name="pref_abc_auto_accept">Automatische Buchstabenauswahl</string>
@ -134,4 +135,5 @@
<string name="voice_input_error_no_network">Keine Internetverbindung</string>
<string name="voice_input_error_not_available">Spracheingabe ist nicht verfügbar</string>
<string name="voice_input_stopping">Mikrofon ausschalten…</string>
<string name="pref_haptic_feedback">Vibration</string>
</resources>

View file

@ -10,6 +10,7 @@
<string name="pref_layout_small">Teclas de función</string>
<string name="pref_layout_stealth">Modo invisible</string>
<string name="pref_layout_tray">Solo lista de palabras</string>
<string name="pref_haptic_feedback_summary">Vibrar al presionar una tecla virtual.</string>
<string name="pref_help">Ayuda</string>
<string name="pref_font_size_large">Grande</string>
<string name="completed">Terminado</string>
@ -141,4 +142,5 @@
<string name="voice_input_error_no_network">Sin conexión a Internet</string>
<string name="voice_input_error_not_available">La entrada de voz no está disponible</string>
<string name="voice_input_stopping">Apagando el micrófono…</string>
<string name="pref_haptic_feedback">Vibración</string>
</resources>

View file

@ -20,6 +20,7 @@
<string name="pref_layout_small">Touches de fonction</string>
<string name="pref_layout_stealth">Invisible</string>
<string name="pref_layout_tray">Seulement liste de mots</string>
<string name="pref_haptic_feedback_summary">Vibrer lors de l\'appui sur une touche virtuelle.</string>
<string name="pref_help">Aide</string>
<string name="pref_dark_theme">Thème sombre</string>
<string name="pref_auto_capitals_after_newline">Majuscules automatiques sur chaque ligne</string>
@ -139,4 +140,5 @@
<string name="voice_input_error_no_network">Pas de connexion Internet</string>
<string name="voice_input_error_not_available">La saisie vocale n\'est pas disponible</string>
<string name="voice_input_stopping">Désactivation du microphone…</string>
<string name="pref_haptic_feedback">Vibration</string>
</resources>

View file

@ -23,6 +23,7 @@
<string name="pref_layout_small">Tasti di funzione</string>
<string name="pref_layout_stealth">Invisibile</string>
<string name="pref_layout_tray">Solo elenco delle parole</string>
<string name="pref_haptic_feedback_summary">Vibrare alla pressione di un tasto virtuale.</string>
<string name="pref_help">Aiuto</string>
<string name="pref_dark_theme">Tema scuro</string>
<string name="pref_abc_auto_accept">Selezione automatica delle lettere</string>
@ -134,5 +135,6 @@
<string name="voice_input_error_no_network">Nessuna connessione Internet</string>
<string name="voice_input_error_not_available">L\'input vocale non è disponibile</string>
<string name="voice_input_stopping">Spegnimento del microfono…</string>
<string name="pref_haptic_feedback">Vibrazione</string>
</resources>

View file

@ -49,6 +49,7 @@
<string name="pref_layout_small">מקשי פונקציה</string>
<string name="pref_layout_stealth">מצב בלתי נראה</string>
<string name="pref_layout_tray">רשימת מילים בלבד</string>
<string name="pref_haptic_feedback_summary">לרטוט בעת לחיצה על מקש וירטואלי.</string>
<string name="pref_help">עזרה</string>
<string name="pref_status_icon">סמל מצב</string>
@ -144,4 +145,5 @@
<string name="voice_input_error_no_network">אין חיבור לאינטרנט</string>
<string name="voice_input_error_not_available">קלט קולי אינו זמין</string>
<string name="voice_input_stopping">מכבה את המיקרופון…</string>
<string name="pref_haptic_feedback">רטט</string>
</resources>

View file

@ -54,6 +54,7 @@
<string name="pref_layout_small">Funkcijos klavišai</string>
<string name="pref_layout_stealth">Nematomas režimas</string>
<string name="pref_layout_tray">Tik žodžių sąrašas</string>
<string name="pref_haptic_feedback_summary">Vibruoti paspaudus virtualų klavišą.</string>
<string name="pref_help">Pagalba</string>
<string name="pref_upside_down_keys">Atvirkštinė klavišų tvarka</string>
<string name="pref_upside_down_keys_summary">Įjunkite šį nustatymą jei pirmoje eilutėje turite 789, o ne 123.</string>
@ -150,4 +151,5 @@
<string name="voice_input_error_no_network">Nėra interneto ryšio</string>
<string name="voice_input_error_not_available">Balso įvestis nėra prieinama</string>
<string name="voice_input_stopping">Išjungiamas mikrofonas…</string>
<string name="pref_haptic_feedback">Vibracija</string>
</resources>

View file

@ -20,6 +20,7 @@
<string name="pref_layout_small">Functieknoppen</string>
<string name="pref_layout_stealth">Onzichtbare modus</string>
<string name="pref_layout_tray">Alleen suggestielijst</string>
<string name="pref_haptic_feedback_summary">Trillen bij het indrukken van een virtuele toets.</string>
<string name="pref_help">Helpen</string>
<string name="pref_dark_theme">Donker thema</string>
<string name="pref_abc_auto_accept">Automatische letterselectie</string>
@ -132,4 +133,5 @@
<string name="voice_input_error_no_network">Geen internetverbinding</string>
<string name="voice_input_error_not_available">Spraakopvoer is niet beschikbaar</string>
<string name="voice_input_stopping">Microfoon uitschakelen…</string>
<string name="pref_haptic_feedback">Trilling</string>
</resources>

View file

@ -50,6 +50,7 @@
<string name="pref_layout_small">Teclas de função</string>
<string name="pref_layout_stealth">Modo invisível</string>
<string name="pref_layout_tray">Apenas lista de palavras</string>
<string name="pref_haptic_feedback_summary">Vibrar ao pressionar uma tecla virtual.</string>
<string name="pref_help">Ajuda</string>
<string name="pref_status_icon">Ícone de status</string>
@ -144,4 +145,5 @@
<string name="voice_input_error_no_network">Sem conexão com a Internet</string>
<string name="voice_input_error_not_available">A entrada de voz não está disponível</string>
<string name="voice_input_stopping">Desligando o microfone…</string>
<string name="pref_haptic_feedback">Vibração</string>
</resources>

View file

@ -20,6 +20,7 @@
<string name="pref_layout_small">Функциональные клавиши</string>
<string name="pref_layout_stealth">Невидимый режим</string>
<string name="pref_layout_tray">Только список слов</string>
<string name="pref_haptic_feedback_summary">Вибрировать при нажатии виртуальной клавиши.</string>
<string name="pref_help">Помощь</string>
<string name="pref_dark_theme">Темная тема</string>
<string name="pref_auto_capitals_after_newline">Автоматические заглавные буквы на каждой строке</string>
@ -141,4 +142,5 @@
<string name="voice_input_error_no_network">Нет подключения к Интернету</string>
<string name="voice_input_error_not_available">Голосовой ввод недоступен</string>
<string name="voice_input_stopping">Отключение микрофона…</string>
<string name="pref_haptic_feedback">Вибрация</string>
</resources>

View file

@ -21,6 +21,7 @@
<string name="pref_layout_small">İşlevsel Tuşlar</string>
<string name="pref_layout_stealth">Görünmez</string>
<string name="pref_layout_tray">Sadece Tahminler</string>
<string name="pref_haptic_feedback_summary">Sanal bir tuşa basıldığında titremek.</string>
<string name="pref_help">Yardım</string>
<string name="pref_dark_theme">Karanlık Tema</string>
<string name="pref_abc_auto_accept">Otomatik Harf Seçimi</string>
@ -144,4 +145,5 @@
<string name="voice_input_error_no_network">İnternet bağlantısı yok</string>
<string name="voice_input_error_not_available">Sesli giriş kullanılamıyor</string>
<string name="voice_input_stopping">Mikrofon kapatılıyor…</string>
<string name="pref_haptic_feedback">Titreşim</string>
</resources>

View file

@ -61,6 +61,7 @@
<string name="pref_layout_small">Функціональні клавіші</string>
<string name="pref_layout_stealth">Невидимий режим</string>
<string name="pref_layout_tray">Лише список слів</string>
<string name="pref_haptic_feedback_summary">Вібрувати при натисканні віртуальної клавіші.</string>
<string name="pref_help">Допомога</string>
<string name="pref_upside_down_keys">Зворотній порядок клавіш</string>
<string name="pref_upside_down_keys_summary">Використовуйте це налаштування, якщо у вас в першому ряді 789 замість 123.</string>
@ -152,4 +153,5 @@
<string name="voice_input_error_no_network">Немає підключення до Інтернету</string>
<string name="voice_input_error_not_available">Голосовий ввід недоступний</string>
<string name="voice_input_stopping">Вимикання мікрофона…</string>
<string name="pref_haptic_feedback">Вібрація</string>
</resources>

View file

@ -64,6 +64,8 @@
<string name="pref_hack_fb_messenger">Send with \"OK\" in Facebook Messenger</string>
<string name="pref_hack_key_pad_debounce_time">Accidental Key Repeat Protection</string>
<string name="pref_hack_key_pad_debounce_off">Off</string>
<string name="pref_haptic_feedback">Vibration</string>
<string name="pref_haptic_feedback_summary">Vibrate when a virtual key is pressed.</string>
<string name="pref_help">Help</string>
<string name="pref_layout">On-screen Layout</string>
<string name="pref_layout_numpad">Virtual numpad (BETA)</string>

View file

@ -10,6 +10,11 @@
app:key="pref_layout_type"
app:title="@string/pref_layout" />
<SwitchPreferenceCompat
app:key="pref_haptic_feedback"
app:title="@string/pref_haptic_feedback"
app:summary="@string/pref_haptic_feedback_summary"/>
<SwitchPreferenceCompat
app:key="pref_status_icon"
app:title="@string/pref_status_icon"