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);
+    }
 }

 
posted @ 2018-06-14 16:29  mail181  阅读(58)  评论(0编辑  收藏  举报