android 原生输入法修改适配无TP设备实战
初衷
由于项目需求,当前的设备没有TP,因此系统默认软键盘输入法无法点击输入,考虑0费用下,我将android原生的Soft Keyboard输入法进行了改造,让其可以通过物理按键获取到焦点,从而进行按键输入。
下面是本次修改所作出的全部patch,请参考。
diff --git a/samples/SoftKeyboard/res/xml/qwerty.xml b/samples/SoftKeyboard/res/xml/qwerty.xml
index 936c977..568a4c4 100755
--- a/samples/SoftKeyboard/res/xml/qwerty.xml
+++ b/samples/SoftKeyboard/res/xml/qwerty.xml
@@ -70,17 +70,18 @@
<Row android:rowEdgeFlags="bottom">
<Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done"
android:keyWidth="15%p" android:keyEdgeFlags="left"/>
- <Key android:codes="-2" android:keyLabel="123" android:keyWidth="10%p"/>
+ <Key android:codes="-2" android:keyLabel="123" android:keyWidth="15%p"/>
<!--
android:codes: -101 is not a framework-defined key code but a key code that is
privately defined in com.example.android.softkeyboard.LatinKeyboardView.
- -->
+
<Key android:codes="-101" android:keyIcon="@drawable/sym_keyboard_language_switch"
android:keyWidth="10%p"/>
+ -->
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
android:keyWidth="30%p" android:isRepeatable="true"/>
<Key android:codes="46,44" android:keyLabel=". ,"
- android:keyWidth="15%p"/>
+ android:keyWidth="20%p"/>
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
android:keyWidth="20%p" android:keyEdgeFlags="right"/>
</Row>
diff --git a/samples/SoftKeyboard/res/xml/symbols.xml b/samples/SoftKeyboard/res/xml/symbols.xml
index 225ea08..23848d6 100755
--- a/samples/SoftKeyboard/res/xml/symbols.xml
+++ b/samples/SoftKeyboard/res/xml/symbols.xml
@@ -70,16 +70,17 @@
<Row android:rowEdgeFlags="bottom">
<Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done"
android:keyWidth="15%p" android:keyEdgeFlags="left" />
- <Key android:codes="-2" android:keyLabel="ABC" android:keyWidth="10%p" />
+ <Key android:codes="-2" android:keyLabel="ABC" android:keyWidth="15%p" />
<!--
android:codes: -101 is not a framework-defined key code but a key code that is
privately defined in com.example.android.softkeyboard.LatinKeyboardView.
- -->
+
<Key android:codes="-101" android:keyIcon="@drawable/sym_keyboard_language_switch"
android:keyWidth="10%p" />
+ -->
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" android:keyWidth="30%p"
android:isRepeatable="true"/>
- <Key android:codes="44" android:keyLabel="," android:keyWidth="15%p" />
+ <Key android:codes="44" android:keyLabel="," android:keyWidth="20%p" />
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
android:keyWidth="20%p" android:keyEdgeFlags="right"
/>
diff --git a/samples/SoftKeyboard/res/xml/symbols_shift.xml b/samples/SoftKeyboard/res/xml/symbols_shift.xml
index fa551f2..c3ea4f1 100755
--- a/samples/SoftKeyboard/res/xml/symbols_shift.xml
+++ b/samples/SoftKeyboard/res/xml/symbols_shift.xml
@@ -70,16 +70,17 @@
<Row android:rowEdgeFlags="bottom">
<Key android:codes="-3" android:keyIcon="@drawable/sym_keyboard_done"
android:keyWidth="15%p" android:keyEdgeFlags="left" />
- <Key android:codes="-2" android:keyLabel="ABC" android:keyWidth="10%p" />
+ <Key android:codes="-2" android:keyLabel="ABC" android:keyWidth="15%p" />
<!--
android:codes: -101 is not a framework-defined key code but a key code that is
privately defined in com.example.android.softkeyboard.LatinKeyboardView.
- -->
+
<Key android:codes="-101" android:keyIcon="@drawable/sym_keyboard_language_switch"
android:keyWidth="10%p" />
+ -->
<Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" android:keyWidth="30%p"
android:isRepeatable="true"/>
- <Key android:codes="8230" android:keyLabel="…" android:keyWidth="15%p" />
+ <Key android:codes="8230" android:keyLabel="…" android:keyWidth="20%p" />
<Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
android:keyWidth="20%p" android:keyEdgeFlags="right" />
</Row>
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java
old mode 100644
new mode 100755
index abfa2f2..fae08e3
--- a/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/LatinKeyboardView.java
@@ -22,6 +22,12 @@ import android.inputmethodservice.Keyboard.Key;
import android.inputmethodservice.KeyboardView;
import android.util.AttributeSet;
import android.view.inputmethod.InputMethodSubtype;
+import java.util.List;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import java.util.ArrayList;
+import android.graphics.Color;
public class LatinKeyboardView extends KeyboardView {
@@ -29,6 +35,12 @@ public class LatinKeyboardView extends KeyboardView {
// TODO: Move this into android.inputmethodservice.Keyboard
static final int KEYCODE_LANGUAGE_SWITCH = -101;
+ private Keyboard currentKeyboard;
+ private List<Key> keys = new ArrayList<Key>();
+ private int lastKeyIndex = 0;
+ private Key focusedKey;
+ private Rect rect;
+
public LatinKeyboardView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -52,4 +64,35 @@ public class LatinKeyboardView extends KeyboardView {
keyboard.setSpaceIcon(getResources().getDrawable(subtype.getIconResId()));
invalidateAllKeys();
}
+
+ /**
+ * modified onDraw method(Overriding)
+ */
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ currentKeyboard = this.getKeyboard();
+ keys = currentKeyboard.getKeys();
+ Paint p = new Paint();
+ p.setColor(Color.CYAN);
+ p.setStyle(Paint.Style.STROKE);
+ p.setStrokeWidth(3.75f);
+ focusedKey = keys.get(lastKeyIndex);
+ rect = new Rect(
+ focusedKey.x, focusedKey.y + 4,
+ focusedKey.x + focusedKey.width,
+ focusedKey.y + focusedKey.height
+ );
+ canvas.drawRect(rect, p);
+ }
+
+ /** provide lastKeyIndex access */
+ public int getLastKeyIndex() {
+ return lastKeyIndex;
+ }
+
+ /** set key index */
+ public void setLastKeyIndex(int index) {
+ this.lastKeyIndex = index;
+ }
}
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
old mode 100644
new mode 100755
index cdebde5..04eb79a
--- a/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
@@ -36,6 +36,13 @@ import android.view.inputmethod.InputMethodSubtype;
import java.util.ArrayList;
import java.util.List;
+import android.content.Context;
+import android.inputmethodservice.Keyboard.Key;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.Log;
+
/**
* Example of writing an input method for a soft keyboard. This code is
* focused on simplicity over completeness, so it should in no way be considered
@@ -79,6 +86,14 @@ public class SoftKeyboard extends InputMethodService
private String mWordSeparators;
+ private int nCurKeyboardKeyNums;
+ private Keyboard nCurrentKeyboard;
+ private List<Keyboard.Key> nKeys;
+ private int nLastKeyIndex = 0;
+ private Rect rect;
+ private boolean shortPress = false;
+ private static final String TAG = "SoftKeyboard";
+
/**
* Main initialization of the input method component. Be sure to call
* to super class.
@@ -124,7 +139,7 @@ public class SoftKeyboard extends InputMethodService
private void setLatinKeyboard(LatinKeyboard nextKeyboard) {
final boolean shouldSupportLanguageSwitchKey =
mInputMethodManager.shouldOfferSwitchingToNextInputMethod(getToken());
- nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey);
+ //nextKeyboard.setLanguageSwitchKeyVisibility(shouldSupportLanguageSwitchKey);
mInputView.setKeyboard(nextKeyboard);
}
@@ -145,6 +160,7 @@ public class SoftKeyboard extends InputMethodService
* about the target of our edits.
*/
@Override public void onStartInput(EditorInfo attribute, boolean restarting) {
+ Log.d(TAG,"onStartInput,inputtype: "+attribute.inputType);
super.onStartInput(attribute, restarting);
// Reset our state. We want to do this even if restarting, because
@@ -229,6 +245,10 @@ public class SoftKeyboard extends InputMethodService
// Update the label on the enter key, depending on what the application
// says it will do.
mCurKeyboard.setImeOptions(getResources(), attribute.imeOptions);
+ //when get focus in edittext, show ime.
+ if(attribute.inputType != 0){
+ showWindow(true);
+ }
}
/**
@@ -265,7 +285,8 @@ public class SoftKeyboard extends InputMethodService
@Override
public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
- mInputView.setSubtypeOnSpaceKey(subtype);
+ if (null!=mInputView)
+ mInputView.setSubtypeOnSpaceKey(subtype);
}
/**
@@ -355,7 +376,7 @@ public class SoftKeyboard extends InputMethodService
* We get first crack at them, and can either resume them or let them
* continue to the app.
*/
- @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
+ /*@Override public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
// The InputMethodService already takes care of the back
@@ -415,14 +436,14 @@ public class SoftKeyboard extends InputMethodService
}
return super.onKeyDown(keyCode, event);
- }
+ }*/
/**
* Use this to monitor key events being delivered to the application.
* We get first crack at them, and can either resume them or let them
* continue to the app.
*/
- @Override public boolean onKeyUp(int keyCode, KeyEvent event) {
+ /*@Override public boolean onKeyUp(int keyCode, KeyEvent event) {
// If we want to do transformations on text being entered with a hard
// keyboard, we need to process the up events to update the meta key
// state we are tracking.
@@ -434,7 +455,7 @@ public class SoftKeyboard extends InputMethodService
}
return super.onKeyUp(keyCode, event);
- }
+ }*/
/**
* Helper function to commit any text being composed in to the editor.
@@ -717,4 +738,233 @@ public class SoftKeyboard extends InputMethodService
public void onRelease(int primaryCode) {
}
+
+ private void setFields() {
+ if (null == mInputView) return;
+
+ nCurrentKeyboard = mInputView.getKeyboard();
+ nKeys = nCurrentKeyboard.getKeys();
+ nCurKeyboardKeyNums = nKeys.size();
+ nLastKeyIndex = mInputView.getLastKeyIndex();
+ }
+
+ @Override public boolean onKeyUp(int keyCode, KeyEvent event) {
+ switch(keyCode){
+ case KeyEvent.KEYCODE_DPAD_DOWN://we will change to right
+ if(!shortPress){ //long press
+ setFields();
+ if (nLastKeyIndex >= nCurKeyboardKeyNums - 1) {
+ if (null == mInputView || !mInputView.isClickable()|| !mInputView.isShown()){
+ Log.w(TAG,"mInputView not visable, do not deal the keyevent in KEYCODE_DPAD_DOWN long press");
+ return false;
+ }
+ mInputView.setLastKeyIndex(0);
+ } else {
+ int[] nearestKeyIndices = nCurrentKeyboard.getNearestKeys(
+ nKeys.get(nLastKeyIndex).x, nKeys.get(nLastKeyIndex).y);
+ for (int index : nearestKeyIndices) {
+ if (nLastKeyIndex < index) {
+ Key nearKey = nKeys.get(index);
+ Key lastKey = nKeys.get(nLastKeyIndex);
+ if ( ((lastKey.x >= nearKey.x) // left side compare
+ && (lastKey.x < (nearKey.x + nearKey.width)))
+ || (((lastKey.x + lastKey.width) > nearKey.x) // right side compare
+ && ((lastKey.x + lastKey.width) <= (nearKey.x + nearKey.width)))
+ ) {
+ mInputView.setLastKeyIndex(index);
+ break;
+ }
+ }
+ }// end for loop
+ }
+ mInputView.invalidate();
+ shortPress = false;
+ return true;
+ } else{ // short press for down
+ setFields();
+ if (nLastKeyIndex >= nCurKeyboardKeyNums - 1) {
+ if (null == mInputView || !mInputView.isShown()){
+ Log.w(TAG,"mInputView not visable, do not deal the keyevent in keyup short press");
+ return false;
+ }
+ mInputView.setLastKeyIndex(0);
+ } else {
+ nLastKeyIndex++;
+ mInputView.setLastKeyIndex(nLastKeyIndex);
+ }
+ mInputView.invalidate();
+ return true;
+ }
+ case KeyEvent.KEYCODE_DPAD_UP://short press we will change to left
+ if(!shortPress){
+ setFields();
+ if (nLastKeyIndex <= 0) {
+ if (null == mInputView || !mInputView.isShown()){
+ Log.w(TAG,"mInputView not visable, do not deal the keyevent");
+ return false;
+ }
+ mInputView.setLastKeyIndex(nCurKeyboardKeyNums - 1);
+ } else {
+ int[] nearestKeyIndices = nCurrentKeyboard.getNearestKeys(
+ nKeys.get(nLastKeyIndex).x, nKeys.get(nLastKeyIndex).y);
+ for (int i = nearestKeyIndices.length - 1; i >= 0; i--) {
+ int index = nearestKeyIndices[i];
+ if (nLastKeyIndex > index) {
+ Key nearKey = nKeys.get(index);// get the next key
+ Key nextNearKey = nKeys.get(index + 1);
+ Key lastKey = nKeys.get(nLastKeyIndex);// get current displayed
+ if (((lastKey.x >= nearKey.x) &&
+ (lastKey.x < (nearKey.x + nearKey.width)) &&
+ (((lastKey.x + lastKey.width) <= (nextNearKey.x + nextNearKey.width))
+ || ((lastKey.x + lastKey.width) > nextNearKey.x)))
+ ) {
+ mInputView.setLastKeyIndex(index);
+ break;
+ }
+ }
+ }// end for loop
+ }
+ mInputView.invalidate();
+ shortPress = false;
+ return true;
+ } else{ // short press for up
+ if (null == mInputView || !mInputView.isShown()){
+ Log.w(TAG,"mInputView not visable, do not deal the KEYCODE_DPAD_UP short press");
+ return false;
+ }
+ setFields();
+ if (nLastKeyIndex <= 0) {
+ if (null == mInputView || !mInputView.isShown()){
+ Log.w(TAG,"mInputView not visable, do not deal the KEYCODE_DPAD_UP short press");
+ return false;
+ }
+ mInputView.setLastKeyIndex(nCurKeyboardKeyNums - 1);
+ } else {
+ nLastKeyIndex--;
+ mInputView.setLastKeyIndex(nLastKeyIndex);
+ }
+ mInputView.invalidate();
+ return true;
+ }
+ // Enter key
+ case KeyEvent.KEYCODE_ENTER:
+ if (null == mInputView || !mInputView.isShown()){
+ Log.w(TAG,"mInputView not visable, do not deal the keyevent up longpress");
+ if(getCurrentInputEditorInfo().inputType != 0){
+ showWindow(true);
+ return true;
+ }
+ return false;
+ }
+ setFields();
+ int curKeyCode = nKeys.get(nLastKeyIndex).codes[0];
+ switch (curKeyCode) {
+ case Keyboard.KEYCODE_MODE_CHANGE:
+ case Keyboard.KEYCODE_CANCEL:
+ case Keyboard.KEYCODE_DELETE:
+ case Keyboard.KEYCODE_SHIFT:
+ case LatinKeyboardView.KEYCODE_OPTIONS:
+ /*case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE:
+ case LatinKeyboardView.KEYCODE_PREV_LANGUAGE:
+ */
+ onKey(curKeyCode, null);
+ return true;
+ case 9 :
+ onKey(9, null);
+ return true;
+ case 10:
+ onKey(Keyboard.KEYCODE_CANCEL, null);
+ return true;
+ default:
+ if(getCurrentInputConnection()==null) {
+ Log.w(TAG,"getCurrentInputConnection return null");
+ return false;
+ }
+ if (mInputView.isShifted()) {
+ getCurrentInputConnection().commitText(String.valueOf((char) curKeyCode).toUpperCase(), 1);
+ } else {
+ getCurrentInputConnection().commitText(String.valueOf((char) curKeyCode), 1);
+ }
+ return true;
+ }
+ // Re-direct back long press behavior for EditText cusor op
+ case KeyEvent.KEYCODE_BACK:
+ {
+ if (!shortPress && mInputView != null && mInputView.isShown()) {
+ return false;
+ }
+ }
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_BACK:
+ // Re-direct back long press behavior for EditText cusor op
+ if (mInputView != null && mInputView.isShown() && event.getAction() == KeyEvent.ACTION_DOWN) {
+ event.startTracking();
+ shortPress = event.getRepeatCount() == 0;
+ return true;
+ }
+
+ if (event.getRepeatCount() == 0 && mInputView != null) {
+ if (mInputView.handleBack()) {
+ return true;
+ }
+ }
+ break;
+ // down direction
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (null == mInputView || !mInputView.isShown()){
+ return false;
+ }
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ event.startTracking();
+ shortPress = event.getRepeatCount() == 0;
+ return true;
+ }
+ // up direction
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (null == mInputView || !mInputView.isShown()){
+ Log.w(TAG,"mInputView not visable, do not deal the keyevent");
+ return false;
+ }
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ event.startTracking();
+ shortPress = event.getRepeatCount() == 0;
+ return true;
+ }
+ // left direction
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ setFields();
+ if (nLastKeyIndex <= 0) {
+ if (null == mInputView || !mInputView.isShown()){
+ return false;
+ }
+ mInputView.setLastKeyIndex(nCurKeyboardKeyNums - 1);
+ } else {
+ nLastKeyIndex--;
+ mInputView.setLastKeyIndex(nLastKeyIndex);
+ }
+ mInputView.invalidate();
+ return true;
+ // right direction
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ setFields();
+ if (nLastKeyIndex >= nCurKeyboardKeyNums - 1) {
+ if (null == mInputView || !mInputView.isShown()){
+ return false;
+ }
+ mInputView.setLastKeyIndex(0);
+ } else {
+ nLastKeyIndex++;
+ mInputView.setLastKeyIndex(nLastKeyIndex);
+ }
+ mInputView.invalidate();
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
}