I'm developing my own android keyboard. I have two xml files which are two different keyboard layouts: "english_lower.xml" and "symbols.xml". I need the user to be able to click on a button that switches layout "english_lower.xml" to a layout "symbols.xml".
File "english_lower.xml":
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:horizontalGap="2dp"
android:verticalGap="2dp"
android:background="@drawable/keybutton"
android:keyHeight="48dp"
android:keyWidth="12%p">
<Row>
<Key android:keyLabel="1" android:keyEdgeFlags="left"/>
<Key android:keyLabel="2"/>
<Key android:keyLabel="3"/>
<Key android:keyLabel="4"/>
<Key android:keyLabel="5"/>
<Key android:keyLabel="6"/>
<Key android:keyLabel="7"/>
<Key android:keyLabel="8"/>
<Key android:keyLabel="9"/>
<Key android:keyLabel="0" android:keyEdgeFlags="right"/>
</Row>
<Row>
<Key android:keyLabel="q" android:keyEdgeFlags="left"/>
<Key android:keyLabel="w"/>
<Key android:keyLabel="e"/>
<Key android:keyLabel="r"/>
<Key android:keyLabel="t"/>
<Key android:keyLabel="y"/>
<Key android:keyLabel="u"/>
<Key android:keyLabel="i"/>
<Key android:keyLabel="o"/>
<Key android:keyLabel="p" android:keyEdgeFlags="right"/>
</Row>
<Row>
<Key android:keyLabel="a" android:keyEdgeFlags="left"/>
<Key android:keyLabel="s"/>
<Key android:keyLabel="d"/>
<Key android:keyLabel="f"/>
<Key android:keyLabel="g"/>
<Key android:keyLabel="h"/>
<Key android:keyLabel="j"/>
<Key android:keyLabel="k"/>
<Key android:keyLabel="l" android:keyEdgeFlags="right"/>
</Row>
<Row>
<Key android:keyLabel="z"/>
<Key android:keyLabel="x"/>
<Key android:keyLabel="c"/>
<Key android:keyLabel="v"/>
<Key android:keyLabel="b"/>
<Key android:keyLabel="n"/>
<Key android:keyLabel="m"/>
<Key
android:codes="-5"
android:isRepeatable="true"
android:keyWidth="12%p"
android:textSize="20dp"
android:keyLabel="❮" android:keyEdgeFlags="right"/>
</Row>
<Row>
<Key
android:codes="0"
android:keyLabel="!1#"/>
<Key android:keyLabel=","/>
<Key
android:codes="32"
android:keyWidth="64%p"
android:keyLabel="Space"/>
<Key android:keyLabel="."/>
<Key
android:codes="10"
android:keyEdgeFlags="right"
android:textSize="20dp"
android:keyLabel="↵"/>
</Row>
</Keyboard>
File "symbols.xml":
<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:horizontalGap="2dp"
android:verticalGap="2dp"
android:background="@drawable/keybutton"
android:keyHeight="48dp"
android:keyWidth="12%p">
<Row>
<Key android:keyLabel="1" android:keyEdgeFlags="left"/>
<Key android:keyLabel="2"/>
<Key android:keyLabel="3"/>
<Key android:keyLabel="4"/>
<Key android:keyLabel="5"/>
<Key android:keyLabel="6"/>
<Key android:keyLabel="7"/>
<Key android:keyLabel="8"/>
<Key android:keyLabel="9"/>
<Key android:keyLabel="0" android:keyEdgeFlags="right"/>
</Row>
<Row>
<Key android:keyLabel="\u0040" android:keyEdgeFlags="left"/>
<Key android:keyLabel="#"/>
<Key android:keyLabel="$"/>
<Key android:keyLabel="_"/>
<Key android:keyLabel="\u0026"/>
<Key android:keyLabel="-"/>
<Key android:keyLabel="+"/>
<Key android:keyLabel="("/>
<Key android:keyLabel=")"/>
<Key android:keyLabel="/" android:keyEdgeFlags="right"/>
</Row>
<Row>
<Key android:keyLabel="*" android:keyEdgeFlags="left"/>
<Key android:keyLabel="\u0022"/>
<Key android:keyLabel="'"/>
<Key android:keyLabel=":"/>
<Key android:keyLabel=";"/>
<Key android:keyLabel="!"/>
<Key android:keyLabel="\u003f" android:keyEdgeFlags="right"/>
<Key
android:codes="-5"
android:isRepeatable="true"
android:keyWidth="12%p"
android:textSize="20dp"
android:keyLabel="❮" android:keyEdgeFlags="right"/>
</Row>
<Row>
<Key
android:codes="0"
android:keyLabel="ABC"/>
<Key android:keyLabel=","/>
<Key
android:codes="32"
android:keyWidth="64%p"
android:keyLabel="Space"/>
<Key android:keyLabel="."/>
<Key
android:codes="10"
android:keyEdgeFlags="right"
android:textSize="20dp"
android:keyLabel="↵"/>
</Row>
</Keyboard>
File "Custom_keyboard_app.java":
...
public class CustomKeyboardApp extends InputMethodService
implements KeyboardView.OnKeyboardActionListener {
int symbols = 1;
@Override
public View onCreateInputView() {
KeyboardView keyboardView;
Keyboard keyboard;
keyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.custom_keyboard_layout, null);
keyboard = new Keyboard(this, R.xml.symbols);
keyboardView.setKeyboard(keyboard);
keyboardView.invalidateAllKeys();
keyboardView.setOnKeyboardActionListener(this);
return keyboardView;
}
...
@Override
public void onKey(int primaryCode, int[] keyCodes) {
KeyboardView keyboardView;
Keyboard keyboard;
keyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.custom_keyboard_layout, null);
InputConnection inputConnection = getCurrentInputConnection();
if (inputConnection != null) {
switch (primaryCode) {
case Keyboard.KEYCODE_DELETE:
CharSequence selectedText = inputConnection.getSelectedText(0);
if (TextUtils.isEmpty(selectedText)) {
inputConnection.deleteSurroundingText(1, 0);
} else {
inputConnection.commitText("", 1);
}
break;
case 0:
if (symbols == 1) {
keyboard = new Keyboard(this, R.xml.custom_keypad);
symbols = 2;
inputConnection.commitText(" True", 1);
} else {
keyboard = new Keyboard(this, R.xml.custom_lowers);
symbols = 1;
inputConnection.commitText(" False", 1);
}
keyboardView.setKeyboard(keyboard);
keyboardView.invalidateAllKeys();
keyboardView.setOnKeyboardActionListener(this);
break;
default:
char code = (char) primaryCode;
inputConnection.commitText(String.valueOf(code), 1);
}
}
}
...
}
I tried to solve the problem using
if (symbols == 1) {
keyboard = new Keyboard(this, R.xml.custom_keypad);
symbols = 2;
inputConnection.commitText(" True", 1);
} else {
keyboard = new Keyboard(this, R.xml.custom_lowers);
symbols = 1;
inputConnection.commitText(" False", 1);
}
, but the layout always remains the same, although the words " True" and " False" are written alternately when the button is clicked.
Seems like you are doing a small mistake. onKey
function is inflating the new KeyboardView
and keyboard
each time a key is pressed.
You can follow below steps to resolve this :
onCreateInputView
and onKey
member variables should be declared as variables outside keyboardView
and keyboard
functions.
Inside onKey
function, set value of symbols
variable accordingly and update the keyboard object, without creating a new key
or keyboard
object.
complete code :
public class CustomKeyboardApp extends InputMethodService implements KeyboardView.OnKeyboardActionListener {
private int symbols = 1;
private KeyboardView keyboardView;
private Keyboard keyboard;
@Override
public View onCreateInputView() {
keyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.custom_keyboard_layout, null);
keyboard = new Keyboard(this, R.xml.symbols); // Initial keyboard
keyboardView.setKeyboard(keyboard);
keyboardView.invalidateAllKeys();
keyboardView.setOnKeyboardActionListener(this);
return keyboardView;
}
@Override
public void onKey(int primaryCode, int[] keyCodes) {
if (primaryCode == Keyboard.KEYCODE_DELETE) {
CharSequence selectedText = getCurrentInputConnection().getSelectedText(0);
if (TextUtils.isEmpty(selectedText)) {
getCurrentInputConnection().deleteSurroundingText(1, 0);
} else {
getCurrentInputConnection().commitText("", 1);
}
return;
}
if (primaryCode == 0) {
if (symbols == 1) {
keyboard = new Keyboard(this, R.xml.custom_keypad);
symbols = 2;
} else {
keyboard = new Keyboard(this, R.xml.custom_lowers);
symbols = 1;
}
keyboardView.setKeyboard(keyboard); // Update existing keyboard
keyboardView.invalidateAllKeys(); // Redraw keys
}
char code = (char) primaryCode;
getCurrentInputConnection().commitText(String.valueOf(code), 1);
}
}
You can read more details from here :