Basic visual keyboard using deprecated APIs, sticky shift and alt
This commit is contained in:
+10
-4
@@ -6,8 +6,14 @@ features a voice input key, a language change key, an emoji key, a menu, and ext
|
||||
This choice of symbols is strange, because all of those keys can be easily accessed using your right
|
||||
hand on the Alt key, and the left hand on any of those symbols (they are available on the left half
|
||||
of the keyboard). What is obstructed by the right hand though is the numbers. This is what the
|
||||
symbol bar should contain.
|
||||
symbol bar should contain, and it should look like this:
|
||||
|
||||
Additionally, it should contain some symbols that are unavailable on the physical keyboard. That is
|
||||
the symbols "$", "%", "&", "=". However, as those are not used as often as numbers, they should be
|
||||
hidden away in a collapsed menu along with more, less frequently used symbols.
|
||||
(1) (2) (3) (4) (5) (6) (7) (8) (9) (0)
|
||||
|
||||
When pressing the shift key, the number bar should change into a symbol bar. This will contain all
|
||||
the symbols not found on the physical keyboard. It'll look like this (likely the most needed symbols
|
||||
are in the middle):
|
||||
|
||||
(^) (\) (|) (=) (%) (&) ($) (<) (>) (MORE)
|
||||
|
||||
When pressing more, additional less-used symbols will be shown.
|
||||
+1
-2
@@ -12,8 +12,6 @@ android {
|
||||
targetSdk 34
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -28,3 +26,4 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<service
|
||||
android:name="TitanboardIME"
|
||||
android:directBootAware="true"
|
||||
android:exported="true"
|
||||
android:exported="false"
|
||||
android:label="@string/ime_label"
|
||||
android:permission="android.permission.BIND_INPUT_METHOD">
|
||||
<intent-filter>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package cfpi_fpsi.eu.titanboard;
|
||||
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.util.Log;
|
||||
import android.inputmethodservice.Keyboard;
|
||||
import android.inputmethodservice.KeyboardView;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
@@ -13,71 +13,68 @@ import org.xmlpull.v1.XmlPullParserException;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class TitanboardIME extends InputMethodService {
|
||||
private HashMap<Integer, int[]> keymap;
|
||||
public class TitanboardIME extends InputMethodService implements KeyboardView.OnKeyboardActionListener {
|
||||
private HashMap<Integer, int[]> mKeymap;
|
||||
|
||||
private boolean mShiftOn = false;
|
||||
private boolean mAltOn = false;
|
||||
|
||||
private KeyboardView mInputView;
|
||||
private Keyboard mKeyboard;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
keymap = new HashMap<>();
|
||||
// We load the keymap from the XML file into a variable
|
||||
XmlPullParser parser = getResources().getXml(getResources()
|
||||
.getIdentifier("keymap_titan", "xml", getPackageName()));
|
||||
int code = 0;
|
||||
int value = 0;
|
||||
int alt = 0;
|
||||
mKeymap = new HashMap<>();
|
||||
XmlPullParser parser = getResources().getXml(R.xml.keymap_titan);
|
||||
int code = 0, value = 0, valueAlt = 0;
|
||||
|
||||
try {
|
||||
while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
|
||||
switch (parser.getEventType()) {
|
||||
case XmlPullParser.START_TAG:
|
||||
if (parser.getName().equals("key")) {
|
||||
for (int i = 0; i < parser.getAttributeCount(); ++i) {
|
||||
switch (parser.getAttributeName(i)) {
|
||||
case "code":
|
||||
code = Integer.parseInt(parser.getAttributeValue(i));
|
||||
Log.d("STATE", "KeyCode: " + code);
|
||||
break;
|
||||
case "value":
|
||||
value = Integer.parseInt(String.valueOf(parser.getAttributeValue(i).codePointAt(0)));
|
||||
break;
|
||||
case "alt":
|
||||
alt = Integer.parseInt(String.valueOf(parser.getAttributeValue(i).codePointAt(0)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
int type = parser.getEventType();
|
||||
if (type == XmlPullParser.START_TAG && parser.getName().equals("key")) {
|
||||
for (int i = 0; i < parser.getAttributeCount(); ++i) {
|
||||
String attr = parser.getAttributeName(i);
|
||||
if (attr.equals("code")) {
|
||||
code = Integer.parseInt(parser.getAttributeValue(i));
|
||||
} else if (attr.equals("value")) {
|
||||
value = Integer.parseInt(String.valueOf(parser.getAttributeValue(i).codePointAt(0)));
|
||||
} else if (attr.equals("valueAlt")) {
|
||||
valueAlt = Integer.parseInt(String.valueOf(parser.getAttributeValue(i).codePointAt(0)));
|
||||
}
|
||||
break;
|
||||
case XmlPullParser.END_TAG:
|
||||
if (parser.getName().equals("key")) {
|
||||
Log.d("STATE", "Adding KeyCode " + code + " which corresponds to: " + value + " and " + alt);
|
||||
keymap.put(code, new int[] { value, alt });
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type == XmlPullParser.END_TAG && parser.getName().equals("key")) {
|
||||
mKeymap.put(code, new int[]{value, valueAlt});
|
||||
}
|
||||
|
||||
parser.next();
|
||||
}
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
} catch (XmlPullParserException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateInputView() {
|
||||
return getLayoutInflater().inflate(R.layout.input, null);
|
||||
public void onInitializeInterface() {
|
||||
mInputView = (KeyboardView) getLayoutInflater().inflate(R.layout.keyboard_symbol, null);
|
||||
mKeyboard = new Keyboard(this, R.xml.keylayout_symbol);
|
||||
mInputView.setKeyboard(mKeyboard);
|
||||
mInputView.setOnKeyboardActionListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEvaluateFullscreenMode() {
|
||||
// This is to override the default behaviour, which seems to do more than detect landscape
|
||||
// mode.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
InputConnection conn = getCurrentInputConnection();
|
||||
EditorInfo info = getCurrentInputEditorInfo();
|
||||
|
||||
if (conn == null || info == null) {
|
||||
if (conn == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -94,20 +91,37 @@ public class TitanboardIME extends InputMethodService {
|
||||
return false;
|
||||
// If it's the backspace key, we remove one character.
|
||||
case KeyEvent.KEYCODE_DEL:
|
||||
conn.deleteSurroundingText(1, 0);
|
||||
return true;
|
||||
// We suppress the alt keys so the system cannot use them.
|
||||
CharSequence selection = conn.getSelectedText(0);
|
||||
if (selection != null) {
|
||||
// This IME won't handle it, and in turn the whole selection gets deleted.
|
||||
return false;
|
||||
} else {
|
||||
conn.deleteSurroundingText(1, 0);
|
||||
return true;
|
||||
}
|
||||
case KeyEvent.KEYCODE_ALT_LEFT:
|
||||
case KeyEvent.KEYCODE_ALT_RIGHT:
|
||||
mAltOn = !mAltOn;
|
||||
mShiftOn = false;
|
||||
return true;
|
||||
case KeyEvent.KEYCODE_SHIFT_LEFT:
|
||||
case KeyEvent.KEYCODE_SHIFT_RIGHT:
|
||||
mShiftOn = !mShiftOn;
|
||||
mAltOn = false;
|
||||
return true;
|
||||
case KeyEvent.KEYCODE_SPACE:
|
||||
conn.commitText(" ", 1);
|
||||
return true;
|
||||
default:
|
||||
// And we send the character to the app.
|
||||
int[] key = keymap.get(keyCode);
|
||||
int[] key = mKeymap.get(keyCode);
|
||||
if (key != null) {
|
||||
if (event.isAltPressed()) {
|
||||
if (mAltOn) {
|
||||
conn.commitText(new String(Character.toChars(key[1])), 1);
|
||||
} else if (event.isShiftPressed()) {
|
||||
mAltOn = false;
|
||||
} else if (mShiftOn) {
|
||||
conn.commitText(new String(Character.toChars(key[0])).toUpperCase(), 1);
|
||||
mShiftOn = false;
|
||||
} else {
|
||||
conn.commitText(new String(Character.toChars(key[0])), 1);
|
||||
}
|
||||
@@ -117,4 +131,53 @@ public class TitanboardIME extends InputMethodService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateInputView() {
|
||||
return mInputView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPress(int primaryCode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRelease(int primaryCode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKey(int primaryCode, int[] keyCodes) {
|
||||
InputConnection conn = getCurrentInputConnection();
|
||||
|
||||
if (conn != null) {
|
||||
conn.commitText(String.valueOf((char) primaryCode), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onText(CharSequence text) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeLeft() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeRight() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeDown() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeUp() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="#E8EAF6"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button12"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Button" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button13"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Button" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button14"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Button" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button"
|
||||
style="@android:style/Widget.DeviceDefault.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:text="1"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button2"
|
||||
style="@android:style/Widget.DeviceDefault.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:text="2"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button3"
|
||||
style="@android:style/Widget.DeviceDefault.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:text="3"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button4"
|
||||
style="@android:style/Widget.DeviceDefault.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:text="4"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button5"
|
||||
style="@android:style/Widget.DeviceDefault.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:text="5"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button6"
|
||||
style="@android:style/Widget.DeviceDefault.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:text="6"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button7"
|
||||
style="@android:style/Widget.DeviceDefault.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:text="7"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button8"
|
||||
style="@android:style/Widget.DeviceDefault.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:text="8"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button9"
|
||||
style="@android:style/Widget.DeviceDefault.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:text="9"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button10"
|
||||
style="@android:style/Widget.DeviceDefault.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:text="0"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button11"
|
||||
style="@android:style/Widget.DeviceDefault.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:text="M"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.inputmethodservice.KeyboardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom" />
|
||||
@@ -1,4 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">Titanboard</string>
|
||||
<string name="ime_label">Titanboard Input Method</string>
|
||||
<string name="ime_label">Titanboard</string>
|
||||
<string name="more_label">More…</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:keyHeight="60dp"
|
||||
android:horizontalGap="0px"
|
||||
android:verticalGap="0px">
|
||||
<Row>
|
||||
<Key
|
||||
android:codes="94"
|
||||
android:keyLabel="^"
|
||||
android:keyEdgeFlags="left" />
|
||||
<Key
|
||||
android:codes="92"
|
||||
android:keyLabel="\\" />
|
||||
<Key
|
||||
android:codes="124"
|
||||
android:keyLabel="|" />
|
||||
<Key
|
||||
android:codes="61"
|
||||
android:keyLabel="=" />
|
||||
<Key
|
||||
android:codes="37"
|
||||
android:keyLabel="%" />
|
||||
<Key
|
||||
android:codes="38"
|
||||
android:keyLabel="&" />
|
||||
<Key
|
||||
android:codes="36"
|
||||
android:keyLabel="$" />
|
||||
<Key
|
||||
android:codes="60"
|
||||
android:keyLabel="<" />
|
||||
<Key
|
||||
android:codes="62"
|
||||
android:keyLabel=">" />
|
||||
<Key
|
||||
android:codes="59"
|
||||
android:keyLabel=";"
|
||||
android:keyEdgeFlags="right" />
|
||||
</Row>
|
||||
<Row>
|
||||
<Key
|
||||
android:codes="49"
|
||||
android:keyLabel="1"
|
||||
android:keyEdgeFlags="left" />
|
||||
<Key
|
||||
android:codes="50"
|
||||
android:keyLabel="2" />
|
||||
<Key
|
||||
android:codes="51"
|
||||
android:keyLabel="3" />
|
||||
<Key
|
||||
android:codes="52"
|
||||
android:keyLabel="4" />
|
||||
<Key
|
||||
android:codes="53"
|
||||
android:keyLabel="5" />
|
||||
<Key
|
||||
android:codes="54"
|
||||
android:keyLabel="6" />
|
||||
<Key
|
||||
android:codes="55"
|
||||
android:keyLabel="7" />
|
||||
<Key
|
||||
android:codes="56"
|
||||
android:keyLabel="8" />
|
||||
<Key
|
||||
android:codes="57"
|
||||
android:keyLabel="9" />
|
||||
<Key
|
||||
android:codes="48"
|
||||
android:keyLabel="0"
|
||||
android:keyEdgeFlags="right" />
|
||||
</Row>
|
||||
</Keyboard>
|
||||
@@ -1,29 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<keymap>
|
||||
<key code="29" value="a" alt="@"/>
|
||||
<key code="30" value="b" alt="7"/>
|
||||
<key code="31" value="c" alt=","/>
|
||||
<key code="32" value="d" alt="""/>
|
||||
<key code="33" value="e" alt="_"/>
|
||||
<key code="34" value="f" alt="+"/>
|
||||
<key code="35" value="g" alt="*"/>
|
||||
<key code="36" value="h" alt="#"/>
|
||||
<key code="37" value="i" alt="2"/>
|
||||
<key code="38" value="j" alt="4"/>
|
||||
<key code="39" value="k" alt="5"/>
|
||||
<key code="40" value="l" alt="6"/>
|
||||
<key code="41" value="m" alt="9"/>
|
||||
<key code="42" value="n" alt="8"/>
|
||||
<key code="43" value="o" alt="3"/>
|
||||
<key code="44" value="p" alt="0"/>
|
||||
<key code="45" value="q" alt=":"/>
|
||||
<key code="46" value="r" alt="-"/>
|
||||
<key code="47" value="s" alt="'"/>
|
||||
<key code="48" value="t" alt="("/>
|
||||
<key code="49" value="u" alt="1"/>
|
||||
<key code="50" value="v" alt="."/>
|
||||
<key code="51" value="w" alt="/"/>
|
||||
<key code="52" value="x" alt="?"/>
|
||||
<key code="53" value="y" alt=")"/>
|
||||
<key code="54" value="z" alt="!"/>
|
||||
<key
|
||||
code="29"
|
||||
value="a"
|
||||
valueAlt="@" />
|
||||
<key
|
||||
code="30"
|
||||
value="b"
|
||||
valueAlt="7" />
|
||||
<key
|
||||
code="31"
|
||||
value="c"
|
||||
valueAlt="," />
|
||||
<key
|
||||
code="32"
|
||||
value="d"
|
||||
valueAlt=""" />
|
||||
<key
|
||||
code="33"
|
||||
value="e"
|
||||
valueAlt="_" />
|
||||
<key
|
||||
code="34"
|
||||
value="f"
|
||||
valueAlt="+" />
|
||||
<key
|
||||
code="35"
|
||||
value="g"
|
||||
valueAlt="*" />
|
||||
<key
|
||||
code="36"
|
||||
value="h"
|
||||
valueAlt="#" />
|
||||
<key
|
||||
code="37"
|
||||
value="i"
|
||||
valueAlt="2" />
|
||||
<key
|
||||
code="38"
|
||||
value="j"
|
||||
valueAlt="4" />
|
||||
<key
|
||||
code="39"
|
||||
value="k"
|
||||
valueAlt="5" />
|
||||
<key
|
||||
code="40"
|
||||
value="l"
|
||||
valueAlt="6" />
|
||||
<key
|
||||
code="41"
|
||||
value="m"
|
||||
valueAlt="9" />
|
||||
<key
|
||||
code="42"
|
||||
value="n"
|
||||
valueAlt="8" />
|
||||
<key
|
||||
code="43"
|
||||
value="o"
|
||||
valueAlt="3" />
|
||||
<key
|
||||
code="44"
|
||||
value="p"
|
||||
valueAlt="0" />
|
||||
<key
|
||||
code="45"
|
||||
value="q"
|
||||
valueAlt=":" />
|
||||
<key
|
||||
code="46"
|
||||
value="r"
|
||||
valueAlt="-" />
|
||||
<key
|
||||
code="47"
|
||||
value="s"
|
||||
valueAlt="'" />
|
||||
<key
|
||||
code="48"
|
||||
value="t"
|
||||
valueAlt="(" />
|
||||
<key
|
||||
code="49"
|
||||
value="u"
|
||||
valueAlt="1" />
|
||||
<key
|
||||
code="50"
|
||||
value="v"
|
||||
valueAlt="." />
|
||||
<key
|
||||
code="51"
|
||||
value="w"
|
||||
valueAlt="/" />
|
||||
<key
|
||||
code="52"
|
||||
value="x"
|
||||
valueAlt="?" />
|
||||
<key
|
||||
code="53"
|
||||
value="y"
|
||||
valueAlt=")" />
|
||||
<key
|
||||
code="54"
|
||||
value="z"
|
||||
valueAlt="!" />
|
||||
</keymap>
|
||||
@@ -1,4 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<input-method>
|
||||
|
||||
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:supportsSwitchingToNextInputMethod="true">
|
||||
<subtype
|
||||
android:imeSubtypeMode="keyboard"
|
||||
android:isAsciiCapable="true"
|
||||
android:label="Default" />
|
||||
</input-method>
|
||||
Reference in New Issue
Block a user