From bf695b19e0511982b0e2fba18a6520c40ff5af54 Mon Sep 17 00:00:00 2001 From: Emil Kosz Date: Sun, 20 Oct 2024 18:25:19 +0200 Subject: [PATCH] Code restructuring, miscellaneous fixes. --- USER_EXPERIENCE.md | 19 +- app/build.gradle | 1 + .../cfpi_fpsi/eu/titanboard/InputMethod.java | 122 +++-------- .../cfpi_fpsi/eu/titanboard/InputView.java | 98 +++++++++ .../eu/titanboard/KeymapManager.java | 153 ++++++-------- .../eu/titanboard/MetaKeyManager.java | 14 +- .../eu/titanboard/PreferencesActivity.java | 4 - app/src/main/res/drawable/button.xml | 33 +++ app/src/main/res/layout/input.xml | 100 +++++---- app/src/main/res/layout/preferences.xml | 52 +++-- app/src/main/res/values/styles.xml | 62 ++++-- app/src/main/res/values/values.xml | 8 + app/src/main/res/xml/keymaps_titan.xml | 197 +++++++++++++++++- app/src/main/res/xml/method.xml | 2 +- gradle/libs.versions.toml | 1 + 15 files changed, 592 insertions(+), 274 deletions(-) create mode 100644 app/src/main/java/cfpi_fpsi/eu/titanboard/InputView.java create mode 100644 app/src/main/res/drawable/button.xml diff --git a/USER_EXPERIENCE.md b/USER_EXPERIENCE.md index 13035d8..645fc74 100644 --- a/USER_EXPERIENCE.md +++ b/USER_EXPERIENCE.md @@ -21,12 +21,13 @@ isn't very reminiscent of a regular QWERTY keyboard which people are used to: other symbols from regular QWERTY keyboards. 5. There is no extra alt-gr key to type in localized letters. -6. In my opinion, it also lacks a control key, but that is unnecessary on smartphones, unless you +6. The keyboard is too big for one hand typing. +7. In my opinion, it also lacks a control key, but that is unnecessary on smartphones, unless you use the terminal or modify spreadsheets. However, providing appropriate UI elements for the actions possible on regular computers should be the responsibility of the application. Smartphones are simply different devices, with smaller screens and less space for complexity. -7. Emojis. +8. Emojis. However, when designing a keyboard app for it one should already use all pre-existing quirks and decisions which materialized in the physical keyboard. For example, the alt key should be used for @@ -48,8 +49,10 @@ key is long pressed. A menu pops up, and as you hold the key the symbols are cyc 5. Similar to regular visual keyboards on Android, a diacritic/alternate key is assigned to each key according to the language. Long pressing a key will allow you to cycle through available alternatives. -6. I have no plans on adding a control key, as it is largely unnecessary on phones. -7. I do not really use emojis, but I am aware that they are used by the majority of people. Most +6. A toggleable UI that shows the left/right hand side keys, depending on a customizable setting for +left handed people. +7. I have no plans on adding a control key, as it is largely unnecessary on phones. +8. I do not really use emojis, but I am aware that they are used by the majority of people. Most IM apps provide their own emoji list, so this isn't a priority. Designing a good UX for it is also hard on the Titan. @@ -84,4 +87,10 @@ layout, which contains all characters used in Europe. ## European German has the most speakers, therefore it's diacritics are the first in the list. Then French and Italian, which have similar diacritics. These come next. Afterwards, Spanish, then Polish, and the -rest. \ No newline at end of file +rest. + +## Cyrillic +Regular JCUKEN layout, with additional characters for other non-Russian languages. + +## Greek +Works mostly like a regular Greek QWERTY keyboard. \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 92839bd..8059653 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,6 +9,7 @@ android { defaultConfig { applicationId "cfpi_fpsi.eu.titanboard" minSdk 19 + //noinspection OldTargetApi targetSdk 34 versionCode 21 versionName "0.2.1" diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/InputMethod.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/InputMethod.java index 591ec52..714dc16 100644 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/InputMethod.java +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/InputMethod.java @@ -20,11 +20,7 @@ package cfpi_fpsi.eu.titanboard; import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.content.Context; -import android.content.SharedPreferences; import android.inputmethodservice.InputMethodService; -import android.os.Build; import android.os.Vibrator; import android.view.KeyEvent; import android.view.View; @@ -32,9 +28,6 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; -import android.widget.Button; -import android.widget.LinearLayout; -import android.widget.TextView; import java.util.ArrayDeque; import java.util.ArrayList; @@ -46,35 +39,29 @@ import java.util.Deque; // TODO: Implement device recognition and a keymap picking based on it. public class InputMethod extends InputMethodService { - private MetaKeyManager mMetaKeyManager; - private ArrayList mCurrentValues; - private KeymapManager mKeymapManager; - private Deque mLanguageQueue = new ArrayDeque<>(); - private String mCurrentLanguage; - private LinearLayout mInputView; - private Vibrator mVibrator; - SharedPreferences mPreferences; + private final Deque mLanguageQueue = new ArrayDeque<>(); + public MetaKeyManager mMetaKeyManager; + public KeymapManager mKeymapManager; + public String mCurrentLanguage; private int mKeyCounter = 0; private boolean mRegularKeyPressed = false; - + private InputView mInputView; @Override public void onCreate() { super.onCreate(); - // Ideally, detect the device, but for now, load all available keymaps. - mKeymapManager = new KeymapManager(getResources().getXml(R.xml.keymaps_titan)); - Collections.addAll(mLanguageQueue, mKeymapManager.getAvailableLanguages()); - mCurrentLanguage = mLanguageQueue.pop(); - mLanguageQueue.addLast(mCurrentLanguage); - mVibrator = (Vibrator) getBaseContext().getSystemService(VIBRATOR_SERVICE); + Vibrator mVibrator = (Vibrator) getBaseContext().getSystemService(VIBRATOR_SERVICE); mMetaKeyManager = new MetaKeyManager(mVibrator); - mPreferences = getSharedPreferences(getString(R.string.preferences_key), Context.MODE_PRIVATE); + mKeymapManager = new KeymapManager(getResources().getXml(R.xml.keymaps_titan)); + Collections.addAll(mLanguageQueue, mKeymapManager.getAvailableKeymaps()); + cycleLanguages(); } @SuppressLint("InflateParams") @Override public void onInitializeInterface() { - mInputView = (LinearLayout) getLayoutInflater().inflate(R.layout.input, null); + mInputView = (InputView) getLayoutInflater().inflate(R.layout.input, null); + mInputView.updateStateText(); } @Override @@ -86,8 +73,8 @@ public class InputMethod extends InputMethodService { @Override public boolean onKeyDown(int keyCode, KeyEvent event) { - mMetaKeyManager.updateMetaStateDown(keyCode, event); - updateMetaStateTextView(); + mMetaKeyManager.updateMetaStateDown(keyCode); + mInputView.updateStateText(); InputConnection conn = getCurrentInputConnection(); @@ -96,7 +83,6 @@ public class InputMethod extends InputMethodService { } switch (keyCode) { - // If the keyboard is visible, hide it, otherwise, let the system handle the key. case KeyEvent.KEYCODE_BACK: if (isInputViewShown()) { requestHideSelf(0); @@ -108,10 +94,11 @@ public class InputMethod extends InputMethodService { mMetaKeyManager.adjustMetaStateAfterKeypress(); return false; case KeyEvent.KEYCODE_SPACE: - handleSpacebar(conn); + conn.commitText(" ", 1); + mMetaKeyManager.adjustMetaStateAfterKeypress(); return true; default: - mCurrentValues = getKeyValues(keyCode); + ArrayList mCurrentValues = getKeyValues(keyCode); if (mCurrentValues == null) { return false; @@ -127,29 +114,23 @@ public class InputMethod extends InputMethodService { mKeyCounter = 0; } - updateSymbolsView(mCurrentValues, mKeyCounter); + mInputView.updateSymbolsView(mCurrentValues, mKeyCounter); ExtractedText text = conn.getExtractedText(new ExtractedTextRequest(), 0); - conn.setComposingRegion(text.selectionStart - 1, text.selectionStart); - conn.setComposingText(mCurrentValues.get(mKeyCounter), 1); + if (text != null) { + conn.setComposingRegion(text.selectionStart - 1, text.selectionStart); + conn.setComposingText(mCurrentValues.get(mKeyCounter), 1); + } } return true; } } - public void handleSpacebar(InputConnection conn) { - // If we press alt + space, we switch the language. - if (mMetaKeyManager.getAlt().isActive()) { - mCurrentLanguage = mLanguageQueue.pop(); - mLanguageQueue.addLast(mCurrentLanguage); - updateMetaStateTextView(); - } else { - conn.commitText(" ", 1); - } - - mMetaKeyManager.adjustMetaStateAfterKeypress(); + public void cycleLanguages() { + mCurrentLanguage = mLanguageQueue.pop(); + mLanguageQueue.addLast(mCurrentLanguage); } public boolean onKeyUp(int keyCode, KeyEvent event) { @@ -164,11 +145,11 @@ public class InputMethod extends InputMethodService { mMetaKeyManager.adjustMetaStateAfterKeypress(); mKeyCounter = 0; mRegularKeyPressed = false; - updateSymbolsView(null, 0); + mInputView.updateSymbolsView(null, 0); } mMetaKeyManager.updateMetaStateUp(keyCode, event); - updateMetaStateTextView(); + mInputView.updateStateText(); return false; } @@ -181,13 +162,13 @@ public class InputMethod extends InputMethodService { @Override public void onStartInput(EditorInfo info, boolean restarting) { super.onStartInput(info, restarting); - updateMetaStateTextView(); + mInputView.updateStateText(); } @Override public void onFinishInput() { mMetaKeyManager.resetMetaKeyState(); - updateMetaStateTextView(); + mInputView.updateStateText(); } private ArrayList getKeyValues(int keyCode) { @@ -201,51 +182,4 @@ public class InputMethod extends InputMethodService { return mKeymapManager.getKeyBase(mCurrentLanguage, keyCode); } - - @SuppressLint("SetTextI18n") - private void updateMetaStateTextView() { - TextView shiftStateView = mInputView.findViewById(R.id.state_shift); - TextView altStateView = mInputView.findViewById(R.id.state_alt); - TextView languageStateView = mInputView.findViewById(R.id.state_language); - - shiftStateView.setText(getStringForMetaKey( - mMetaKeyManager.getShift(), "aa", "Aa", "AA")); - altStateView.setText(getStringForMetaKey( - mMetaKeyManager.getAlt(), "..", "#?", "#!")); - languageStateView.setText(mKeymapManager.getShortLabel(mCurrentLanguage)); - } - - private String getStringForMetaKey(MetaKeyManager.MetaKey key, String normal, String latched, String pressed) { - if (key.isLatched()) { - return latched; - } - - if (key.isLocked() || key.isPressed()) { - return pressed; - } - - return normal; - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public void updateSymbolsView(ArrayList symbols, int index) { - LinearLayout symbolsView = mInputView.findViewById(R.id.symbols); - symbolsView.removeAllViews(); - if (symbols != null) { - for (int i = 0; i < symbols.size(); ++i) { - Button symbolButton; - - if (i == index) { - symbolButton = new Button(getBaseContext(), null, 0, - R.style.KeyboardSymbolSelected); - } else { - symbolButton = new Button(getBaseContext(), null, 0, - R.style.KeyboardSymbol); - } - - symbolButton.setText(symbols.get(i)); - symbolsView.addView(symbolButton); - } - } - } } diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/InputView.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/InputView.java new file mode 100644 index 0000000..4fa36f8 --- /dev/null +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/InputView.java @@ -0,0 +1,98 @@ +/* + * An input method for the Unihertz Titan/physical keyboard phones + * Copyright (C) 2024 Emil Kosz + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package cfpi_fpsi.eu.titanboard; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import java.util.ArrayList; + +public class InputView extends RelativeLayout { + private final InputMethod mInputMethod; + private Button mStateButton; + private LinearLayout mMultiList; + + public InputView(Context context, AttributeSet attrs) { + super(context, attrs, 0); + mInputMethod = (InputMethod) context; + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mMultiList = findViewById(R.id.multi_list); + mStateButton = findViewById(R.id.input_state); + mStateButton.setOnClickListener(button -> { + mInputMethod.cycleLanguages(); + updateStateText(); + }); + } + + public void updateStateText() { + MetaKeyManager metaManager = mInputMethod.mMetaKeyManager; + KeymapManager keymapManager = mInputMethod.mKeymapManager; + String currentLanguage = mInputMethod.mCurrentLanguage; + + if (metaManager.getAlt().isPressed() || metaManager.getAlt().isLocked()) { + mStateButton.setText("#!"); + return; + } + + if (metaManager.getAlt().isLatched()) { + mStateButton.setText("#?"); + return; + } + + if (metaManager.getShift().isPressed() || metaManager.getShift().isLocked()) { + mStateButton.setText(keymapManager.getKeymap(currentLanguage).getLockedCode()); + return; + } + + if (metaManager.getShift().isLatched()) { + mStateButton.setText(keymapManager.getKeymap(currentLanguage).getLatchedCode()); + return; + } + + mStateButton.setText(keymapManager.getKeymap(currentLanguage).getCode()); + } + + public void updateSymbolsView(ArrayList symbols, int index) { + for (int i = 0; i < mMultiList.getChildCount(); ++i) { + TextView view = (TextView) mMultiList.getChildAt(i); + view.setText(""); + } + + if (symbols != null) { + for (int i = 0; i < Math.min(mMultiList.getChildCount(), symbols.size()); ++i) { + TextView view = (TextView) mMultiList.getChildAt(i); + view.setText(symbols.get(i)); + if (i == index) { + view.setTextAppearance(getContext(), R.style.InputViewSymbolSelected); + } else { + view.setTextAppearance(getContext(), R.style.InputViewSymbol); + } + } + } + } +} diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/KeymapManager.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/KeymapManager.java index 94a7791..63a5e98 100644 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/KeymapManager.java +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/KeymapManager.java @@ -19,24 +19,20 @@ package cfpi_fpsi.eu.titanboard; -import android.util.Log; - import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; -import java.lang.reflect.Array; import java.util.ArrayList; import java.util.HashMap; public class KeymapManager { - // Yeah... I know this is a little wacky. private final HashMap mKeymaps = new HashMap<>(); public KeymapManager(XmlPullParser parser) { Keymap keymap = null; int code = 0; - String lang = null, shortLabel = null, label = null; + String label = null, name = null, latchedName = null, lockedName = null; Key key = null; try { @@ -46,26 +42,26 @@ public class KeymapManager { // We encounter a new keymap. if (type == XmlPullParser.START_TAG && parser.getName().equals("keymap")) { keymap = new Keymap(); - lang = null; - shortLabel = null; - label = null; for (int i = 0; i < parser.getAttributeCount(); ++i) { switch (parser.getAttributeName(i)) { - case "lang": - lang = parser.getAttributeValue(i); - break; - case "short-label": - shortLabel = parser.getAttributeValue(i); - break; case "label": label = parser.getAttributeValue(i); break; + case "name": + name = parser.getAttributeValue(i); + break; + case "latched-name": + latchedName = parser.getAttributeValue(i); + break; + case "locked-name": + lockedName = parser.getAttributeValue(i); + break; } } - } else if (type == XmlPullParser.END_TAG && parser.getName().equals("keymap")) { - keymap.mShortLabel = shortLabel; - keymap.mLabel = label; - mKeymaps.put(lang, keymap); + } else if (type == XmlPullParser.END_TAG && parser.getName().equals("keymap") + && keymap != null) { + keymap.setStrings(label, name, latchedName, lockedName); + mKeymaps.put(label, keymap); } // We got a new key. @@ -76,33 +72,32 @@ public class KeymapManager { code = Integer.parseInt(parser.getAttributeValue(i)); } } - } else if (type == XmlPullParser.END_TAG && parser.getName().equals("key")) { - Log.d("STATE", "+++ Keycode: " + code); - Log.d("STATE", key.toString()); + } else if (type == XmlPullParser.END_TAG && parser.getName().equals("key") + && keymap != null) { keymap.put(code, key); } // We encountered a base value. if (type == XmlPullParser.START_TAG && parser.getName().equals("base")) { for (int i = 0; i < parser.getAttributeCount(); ++i) { - if (parser.getAttributeName(i).startsWith("value")) { - key.mBase.add(parser.getAttributeValue(i)); + if (parser.getAttributeName(i).startsWith("value") && key != null) { + key.getBase().add(parser.getAttributeValue(i)); } } } // We encountered a shift value. if (type == XmlPullParser.START_TAG && parser.getName().equals("shift")) { for (int i = 0; i < parser.getAttributeCount(); ++i) { - if (parser.getAttributeName(i).startsWith("value")) { - key.mShift.add(parser.getAttributeValue(i)); + if (parser.getAttributeName(i).startsWith("value") && key != null) { + key.getShift().add(parser.getAttributeValue(i)); } } } // We encountered an alt value. if (type == XmlPullParser.START_TAG && parser.getName().equals("alt")) { for (int i = 0; i < parser.getAttributeCount(); ++i) { - if (parser.getAttributeName(i).startsWith("value")) { - key.mAlt.add(parser.getAttributeValue(i)); + if (parser.getAttributeName(i).startsWith("value") && key != null) { + key.getAlt().add(parser.getAttributeValue(i)); } } } @@ -114,92 +109,80 @@ public class KeymapManager { } } - public String[] getAvailableLanguages() { + public String[] getAvailableKeymaps() { return mKeymaps.keySet().toArray(new String[0]); } - public String getShortLabel(String lang) { - Keymap keymap = mKeymaps.get(lang); - if (keymap != null) { - return keymap.mShortLabel; - } else { - return null; - } + public Keymap getKeymap(String lang) { + return mKeymaps.get(lang); } public ArrayList getKeyBase(String lang, int keyCode) { - Key key = getKey(lang, keyCode); - if (key != null) { - return key.mBase; - } else { - return null; - } + return getKey(lang, keyCode) != null ? getKey(lang, keyCode).getBase() : null; } public ArrayList getKeyShift(String lang, int keyCode) { - Key key = getKey(lang, keyCode); - if (key != null) { - return key.mShift; - } else { - return null; - } + return getKey(lang, keyCode) != null ? getKey(lang, keyCode).getShift() : null; } public ArrayList getKeyAlt(String lang, int keyCode) { - Key key = getKey(lang, keyCode); - if (key != null) { - return key.mAlt; - } else { - return null; - } + return getKey(lang, keyCode) != null ? getKey(lang, keyCode).getAlt() : null; } public Key getKey(String lang, int keyCode) { Keymap keymap = mKeymaps.get(lang); if (keymap != null) { - Key key = keymap.get(keyCode); - if (key != null) { - return key; - } else { - return null; - } + return keymap.get(keyCode); } else { return null; } } - private static class Keymap extends HashMap { - public String mShortLabel; - public String mLabel; + public static class Keymap extends HashMap { + private String mLabel; // The full name of the keymap. + private String mCode; // A two-letter code for when the keyboard is lowercase. + private String mLatchedCode; // Above, but when the keyboard is shift latched. + private String mLockedCode; // Above, but when the shift is locked/pressed. + + public String getCode() { + return mCode; + } + + public String getLatchedCode() { + return mLatchedCode; + } + + public String getLockedCode() { + return mLockedCode; + } + + public String getLabel() { + return mLabel; + } + + public void setStrings(String label, String code, String latched, String locked) { + mLabel = label; + mCode = code; + mLatchedCode = latched; + mLockedCode = locked; + } } public static class Key { - public ArrayList mBase = new ArrayList<>(); - public ArrayList mShift = new ArrayList<>(); - public ArrayList mAlt = new ArrayList<>(); + private final ArrayList mBase = new ArrayList<>(); + private final ArrayList mShift = new ArrayList<>(); + private final ArrayList mAlt = new ArrayList<>(); - public String toString() { - StringBuilder output = new StringBuilder(); + public ArrayList getBase() { + return mBase; + } - output.append("\n=== Base: "); - for (String value : mBase) { - output.append(value); - output.append(","); - } + public ArrayList getShift() { + return mShift; + } - output.append("\n=== Shift: "); - for (String value : mShift) { - output.append(value); - output.append(","); - } - - output.append("\n=== Alt: "); - for (String value : mAlt) { - output.append(value); - output.append(","); - } - - return output.toString(); + public ArrayList getAlt() { + return mAlt; } } } diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/MetaKeyManager.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/MetaKeyManager.java index 41cce55..c9d238a 100644 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/MetaKeyManager.java +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/MetaKeyManager.java @@ -23,31 +23,31 @@ import android.os.Vibrator; import android.view.KeyEvent; public class MetaKeyManager { - public MetaKey mShift = new MetaKey(); - public MetaKey mAlt = new MetaKey(); + public final MetaKey mShift = new MetaKey(); + public final MetaKey mAlt = new MetaKey(); - private Vibrator mVibrator; + private final Vibrator mVibrator; public MetaKeyManager(Vibrator vibrator) { mVibrator = vibrator; } - public void updateMetaStateDown(int keyCode, KeyEvent event) { + public void updateMetaStateDown(int keyCode) { switch (keyCode) { case KeyEvent.KEYCODE_ALT_LEFT: case KeyEvent.KEYCODE_ALT_RIGHT: - updateMetaKeyDown(mAlt, event); + updateMetaKeyDown(mAlt); break; case KeyEvent.KEYCODE_SHIFT_LEFT: case KeyEvent.KEYCODE_SHIFT_RIGHT: - updateMetaKeyDown(mShift, event); + updateMetaKeyDown(mShift); break; default: break; } } - void updateMetaKeyDown(MetaKey key, KeyEvent event) { + void updateMetaKeyDown(MetaKey key) { // Perhaps this function should be renamed to something... key.setUsed(false); key.setPressed(true); diff --git a/app/src/main/java/cfpi_fpsi/eu/titanboard/PreferencesActivity.java b/app/src/main/java/cfpi_fpsi/eu/titanboard/PreferencesActivity.java index b13c864..a3c82c5 100644 --- a/app/src/main/java/cfpi_fpsi/eu/titanboard/PreferencesActivity.java +++ b/app/src/main/java/cfpi_fpsi/eu/titanboard/PreferencesActivity.java @@ -23,12 +23,9 @@ import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; -import android.widget.RadioGroup; -import android.widget.SeekBar; public class PreferencesActivity extends Activity { SharedPreferences mPreferences; - SharedPreferences.Editor mPrefEditor; @Override protected void onCreate(Bundle savedInstanceState) { @@ -37,6 +34,5 @@ public class PreferencesActivity extends Activity { mPreferences = getBaseContext().getSharedPreferences(getString(R.string.preferences_key), Context.MODE_PRIVATE); - mPrefEditor = mPreferences.edit(); } } diff --git a/app/src/main/res/drawable/button.xml b/app/src/main/res/drawable/button.xml new file mode 100644 index 0000000..a628e6c --- /dev/null +++ b/app/src/main/res/drawable/button.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/input.xml b/app/src/main/res/layout/input.xml index ebe9705..354e856 100644 --- a/app/src/main/res/layout/input.xml +++ b/app/src/main/res/layout/input.xml @@ -1,51 +1,71 @@ - + android:layout_gravity="bottom"> - + android:layout_height="match_parent" + android:layout_alignTop="@id/input_state" + android:layout_alignBottom="@id/input_state" + android:layout_toStartOf="@id/input_state"> - - - - - + android:orientation="horizontal"> - - + - + - + - \ No newline at end of file + + + + + + + + + + + + + + + + + +