首页 文章

如何为Android开发软键盘? [关闭]

提问于
浏览
107

我想玩一些想法,并为Android开发一个软键盘来取代默认的键盘 .

  • 那里有关于Android软键盘开发的一般信息吗?任何最佳做法或指南?

  • 我可以用我的键盘应用程序做几乎我用普通Android应用程序做的事吗?

  • 我可以通过HTTP连接将键盘数据与 Cloud 数据库和我拥有的其他手机同步吗?

  • 我可以通过按键打开其他窗口/屏幕,例如显示与普通QWERTY不同的自定义输入界面 . 如果这不起作用,我可以使用弹出对话框吗?

4 回答

  • 11

    一些技巧:

    关于你的问题:

    一个inputMethod基本上是一个Android Service ,所以是的,你可以做HTTP和你可以在_837394中做的所有事情 .

    您可以从 InputMethod 打开 Activities 和对话框 . 再一次,它只是一个 Service .

    我一直在开发一个IME,所以再问一下你是否遇到了问题 .

  • 3

    为自己的EditText创建自定义键盘

    Download Entire Code

    在这篇文章我创建简单的键盘,其中包含一些特殊的键,如(法国键),它支持大写字母和小写字母和数字键和一些符号 .

    package sra.keyboard;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.WindowManager;
    import android.view.View.OnClickListener;
    import android.view.View.OnFocusChangeListener;
    import android.view.View.OnTouchListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.RelativeLayout;
    
    public class Main extends Activity implements OnTouchListener, OnClickListener,
      OnFocusChangeListener {
     private EditText mEt, mEt1; // Edit Text boxes
     private Button mBSpace, mBdone, mBack, mBChange, mNum;
     private RelativeLayout mLayout, mKLayout;
     private boolean isEdit = false, isEdit1 = false;
     private String mUpper = "upper", mLower = "lower";
     private int w, mWindowWidth;
     private String sL[] = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
       "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w",
       "x", "y", "z", "ç", "à", "é", "è", "û", "î" };
     private String cL[] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
       "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W",
       "X", "Y", "Z", "ç", "à", "é", "è", "û", "î" };
     private String nS[] = { "!", ")", "'", "#", "3", "$", "%", "&", "8", "*",
       "?", "/", "+", "-", "9", "0", "1", "4", "@", "5", "7", "(", "2",
       "\"", "6", "_", "=", "]", "[", "<", ">", "|" };
     private Button mB[] = new Button[32];
    
     @Override
     public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      try {
       setContentView(R.layout.main);
       // adjusting key regarding window sizes
       setKeys();
       setFrow();
       setSrow();
       setTrow();
       setForow();
       mEt = (EditText) findViewById(R.id.xEt);
       mEt.setOnTouchListener(this);
       mEt.setOnFocusChangeListener(this);
       mEt1 = (EditText) findViewById(R.id.et1);
    
       mEt1.setOnTouchListener(this);
       mEt1.setOnFocusChangeListener(this);
       mEt.setOnClickListener(this);
       mEt1.setOnClickListener(this);
       mLayout = (RelativeLayout) findViewById(R.id.xK1);
       mKLayout = (RelativeLayout) findViewById(R.id.xKeyBoard);
    
      } catch (Exception e) {
       Log.w(getClass().getName(), e.toString());
      }
    
     }
    
     @Override
     public boolean onTouch(View v, MotionEvent event) {
      if (v == mEt) {
       hideDefaultKeyboard();
       enableKeyboard();
    
      }
      if (v == mEt1) {
       hideDefaultKeyboard();
       enableKeyboard();
    
      }
      return true;
     }
    
     @Override
     public void onClick(View v) {
    
      if (v == mBChange) {
    
       if (mBChange.getTag().equals(mUpper)) {
        changeSmallLetters();
        changeSmallTags();
       } else if (mBChange.getTag().equals(mLower)) {
        changeCapitalLetters();
        changeCapitalTags();
       }
    
      } else if (v != mBdone && v != mBack && v != mBChange && v != mNum) {
       addText(v);
    
      } else if (v == mBdone) {
    
       disableKeyboard();
    
      } else if (v == mBack) {
       isBack(v);
      } else if (v == mNum) {
       String nTag = (String) mNum.getTag();
       if (nTag.equals("num")) {
        changeSyNuLetters();
        changeSyNuTags();
        mBChange.setVisibility(Button.INVISIBLE);
    
       }
       if (nTag.equals("ABC")) {
        changeCapitalLetters();
        changeCapitalTags();
       }
    
      }
    
     }
    
     @Override
     public void onFocusChange(View v, boolean hasFocus) {
      if (v == mEt && hasFocus == true) {
       isEdit = true;
       isEdit1 = false;
    
      } else if (v == mEt1 && hasFocus == true) {
       isEdit = false;
       isEdit1 = true;
    
      }
    
     }
    
     private void addText(View v) {
      if (isEdit == true) {
       String b = "";
       b = (String) v.getTag();
       if (b != null) {
        // adding text in Edittext
        mEt.append(b);
    
       }
      }
    
      if (isEdit1 == true) {
       String b = "";
       b = (String) v.getTag();
       if (b != null) {
        // adding text in Edittext
        mEt1.append(b);
    
       }
    
      }
    
     }
    
     private void isBack(View v) {
      if (isEdit == true) {
       CharSequence cc = mEt.getText();
       if (cc != null && cc.length() > 0) {
        {
         mEt.setText("");
         mEt.append(cc.subSequence(0, cc.length() - 1));
        }
    
       }
      }
    
      if (isEdit1 == true) {
       CharSequence cc = mEt1.getText();
       if (cc != null && cc.length() > 0) {
        {
         mEt1.setText("");
         mEt1.append(cc.subSequence(0, cc.length() - 1));
        }
       }
      }
     }
     private void changeSmallLetters() {
      mBChange.setVisibility(Button.VISIBLE);
      for (int i = 0; i < sL.length; i++)
       mB[i].setText(sL[i]);
      mNum.setTag("12#");
     }
     private void changeSmallTags() {
      for (int i = 0; i < sL.length; i++)
       mB[i].setTag(sL[i]);
      mBChange.setTag("lower");
      mNum.setTag("num");
     }
     private void changeCapitalLetters() {
      mBChange.setVisibility(Button.VISIBLE);
      for (int i = 0; i < cL.length; i++)
       mB[i].setText(cL[i]);
      mBChange.setTag("upper");
      mNum.setText("12#");
    
     }
    
     private void changeCapitalTags() {
      for (int i = 0; i < cL.length; i++)
       mB[i].setTag(cL[i]);
      mNum.setTag("num");
    
     }
    
     private void changeSyNuLetters() {
    
      for (int i = 0; i < nS.length; i++)
       mB[i].setText(nS[i]);
      mNum.setText("ABC");
     }
    
     private void changeSyNuTags() {
      for (int i = 0; i < nS.length; i++)
       mB[i].setTag(nS[i]);
      mNum.setTag("ABC");
     }
    
     // enabling customized keyboard
     private void enableKeyboard() {
    
      mLayout.setVisibility(RelativeLayout.VISIBLE);
      mKLayout.setVisibility(RelativeLayout.VISIBLE);
    
     }
    
     // Disable customized keyboard
     private void disableKeyboard() {
      mLayout.setVisibility(RelativeLayout.INVISIBLE);
      mKLayout.setVisibility(RelativeLayout.INVISIBLE);
    
     }
    
     private void hideDefaultKeyboard() {
      getWindow().setSoftInputMode(
        WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
    
     }
    
     private void setFrow() {
      w = (mWindowWidth / 13);
      w = w - 15;
      mB[16].setWidth(w);
      mB[22].setWidth(w + 3);
      mB[4].setWidth(w);
      mB[17].setWidth(w);
      mB[19].setWidth(w);
      mB[24].setWidth(w);
      mB[20].setWidth(w);
      mB[8].setWidth(w);
      mB[14].setWidth(w);
      mB[15].setWidth(w);
      mB[16].setHeight(50);
      mB[22].setHeight(50);
      mB[4].setHeight(50);
      mB[17].setHeight(50);
      mB[19].setHeight(50);
      mB[24].setHeight(50);
      mB[20].setHeight(50);
      mB[8].setHeight(50);
      mB[14].setHeight(50);
      mB[15].setHeight(50);
    
     }
    
     private void setSrow() {
      w = (mWindowWidth / 10);
      mB[0].setWidth(w);
      mB[18].setWidth(w);
      mB[3].setWidth(w);
      mB[5].setWidth(w);
      mB[6].setWidth(w);
      mB[7].setWidth(w);
      mB[26].setWidth(w);
      mB[9].setWidth(w);
      mB[10].setWidth(w);
      mB[11].setWidth(w);
      mB[26].setWidth(w);
    
      mB[0].setHeight(50);
      mB[18].setHeight(50);
      mB[3].setHeight(50);
      mB[5].setHeight(50);
      mB[6].setHeight(50);
      mB[7].setHeight(50);
      mB[9].setHeight(50);
      mB[10].setHeight(50);
      mB[11].setHeight(50);
      mB[26].setHeight(50);
     }
    
     private void setTrow() {
      w = (mWindowWidth / 12);
      mB[25].setWidth(w);
      mB[23].setWidth(w);
      mB[2].setWidth(w);
      mB[21].setWidth(w);
      mB[1].setWidth(w);
      mB[13].setWidth(w);
      mB[12].setWidth(w);
      mB[27].setWidth(w);
      mB[28].setWidth(w);
      mBack.setWidth(w);
    
      mB[25].setHeight(50);
      mB[23].setHeight(50);
      mB[2].setHeight(50);
      mB[21].setHeight(50);
      mB[1].setHeight(50);
      mB[13].setHeight(50);
      mB[12].setHeight(50);
      mB[27].setHeight(50);
      mB[28].setHeight(50);
      mBack.setHeight(50);
    
     }
    
     private void setForow() {
      w = (mWindowWidth / 10);
      mBSpace.setWidth(w * 4);
      mBSpace.setHeight(50);
      mB[29].setWidth(w);
      mB[29].setHeight(50);
    
      mB[30].setWidth(w);
      mB[30].setHeight(50);
    
      mB[31].setHeight(50);
      mB[31].setWidth(w);
      mBdone.setWidth(w + (w / 1));
      mBdone.setHeight(50);
    
     }
    
     private void setKeys() {
      mWindowWidth = getWindowManager().getDefaultDisplay().getWidth(); // getting
      // window
      // height
      // getting ids from xml files
      mB[0] = (Button) findViewById(R.id.xA);
      mB[1] = (Button) findViewById(R.id.xB);
      mB[2] = (Button) findViewById(R.id.xC);
      mB[3] = (Button) findViewById(R.id.xD);
      mB[4] = (Button) findViewById(R.id.xE);
      mB[5] = (Button) findViewById(R.id.xF);
      mB[6] = (Button) findViewById(R.id.xG);
      mB[7] = (Button) findViewById(R.id.xH);
      mB[8] = (Button) findViewById(R.id.xI);
      mB[9] = (Button) findViewById(R.id.xJ);
      mB[10] = (Button) findViewById(R.id.xK);
      mB[11] = (Button) findViewById(R.id.xL);
      mB[12] = (Button) findViewById(R.id.xM);
      mB[13] = (Button) findViewById(R.id.xN);
      mB[14] = (Button) findViewById(R.id.xO);
      mB[15] = (Button) findViewById(R.id.xP);
      mB[16] = (Button) findViewById(R.id.xQ);
      mB[17] = (Button) findViewById(R.id.xR);
      mB[18] = (Button) findViewById(R.id.xS);
      mB[19] = (Button) findViewById(R.id.xT);
      mB[20] = (Button) findViewById(R.id.xU);
      mB[21] = (Button) findViewById(R.id.xV);
      mB[22] = (Button) findViewById(R.id.xW);
      mB[23] = (Button) findViewById(R.id.xX);
      mB[24] = (Button) findViewById(R.id.xY);
      mB[25] = (Button) findViewById(R.id.xZ);
      mB[26] = (Button) findViewById(R.id.xS1);
      mB[27] = (Button) findViewById(R.id.xS2);
      mB[28] = (Button) findViewById(R.id.xS3);
      mB[29] = (Button) findViewById(R.id.xS4);
      mB[30] = (Button) findViewById(R.id.xS5);
      mB[31] = (Button) findViewById(R.id.xS6);
      mBSpace = (Button) findViewById(R.id.xSpace);
      mBdone = (Button) findViewById(R.id.xDone);
      mBChange = (Button) findViewById(R.id.xChange);
      mBack = (Button) findViewById(R.id.xBack);
      mNum = (Button) findViewById(R.id.xNum);
      for (int i = 0; i < mB.length; i++)
       mB[i].setOnClickListener(this);
      mBSpace.setOnClickListener(this);
      mBdone.setOnClickListener(this);
      mBack.setOnClickListener(this);
      mBChange.setOnClickListener(this);
      mNum.setOnClickListener(this);
    
     }
    
    }
    
  • 80

    一个好的起点是sample application provided on the developer docs .

    • 指南只是让它尽可能可用 . 看看市场上的其他产品,看看你的目标是什么

    • 是的,服务可以做大多数事情,包括互联网;只要您要求这些权限

    • 如果在键盘上做某些事情遇到问题,你可以打开活动并做任何你喜欢的事情 . 例如,HTC的键盘有一个用于打开设置活动的按钮,另一个用于打开一个用于更改语言的对话框 .

    看看其他IME,看看你应该瞄准什么 . 有些(像官方的)是开源的 .

  • 10

    首先,您应该定义.xml文件并在其中创建键盘UI:

    <?xml version="1.0" encoding="utf-8"?>
    <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="12.50%p"
    android:keyHeight="7%p">
    <!--
    android:horizontalGap="0.50%p"
    android:verticalGap="0.50%p"
    NOTE When we add a horizontalGap in pixels, this interferes with keyWidth in percentages adding up to 100%
    NOTE When we have a horizontalGap (on Keyboard level) of 0, this make the horizontalGap (on Key level) to move from after the key to before the key... (I consider this a bug) 
    -->
    <Row>
        <Key android:codes="-5" android:keyLabel="remove"  android:keyEdgeFlags="left" />
        <Key android:codes="48"    android:keyLabel="0" />
        <Key android:codes="55006" android:keyLabel="clear" />
    </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" />
    </Row>
    <Row>
        <Key android:codes="52"    android:keyLabel="4"  android:keyEdgeFlags="left" />
        <Key android:codes="53"    android:keyLabel="5" />
        <Key android:codes="54"    android:keyLabel="6" />
    </Row>
    
    <Row>
        <Key android:codes="55"    android:keyLabel="7"  android:keyEdgeFlags="left" />
        <Key android:codes="56"    android:keyLabel="8" />
        <Key android:codes="57"    android:keyLabel="9" />
    </Row>
    

    在此示例中,您有4行,每行有3个键 . 你也可以在你想要的每个键上放一个图标 .

    然后,您应该在活动UI中添加xml标记,如下所示:

    <android.inputmethodservice.KeyboardView
            android:id="@+id/keyboardview1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:visibility="visible" />
    

    同样在.java活动文件中,您应该定义键盘并将其分配给EditText:

    CustomKeyboard mCustomKeyboard1 = new CustomKeyboard(this,
                R.id.keyboardview1, R.xml.horizontal_keyboard);
        mCustomKeyboard1.registerEditText(R.id.inputSearch);
    

    此代码将inputSearch(它是EditText)作为键盘 .

    import android.app.Activity;
    import android.inputmethodservice.Keyboard;
    import android.inputmethodservice.KeyboardView;
    import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
    import android.text.Editable;
    import android.text.InputType;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.View.OnFocusChangeListener;
    import android.view.View.OnTouchListener;
    import android.view.WindowManager;
    import android.view.inputmethod.InputMethodManager;
    import android.widget.EditText;
    
    
    public class CustomKeyboard {
    
    /** A link to the KeyboardView that is used to render this CustomKeyboard. */
    private KeyboardView mKeyboardView;
    /** A link to the activity that hosts the {@link #mKeyboardView}. */
    private Activity mHostActivity;
    
    /** The key (code) handler. */
    private OnKeyboardActionListener mOnKeyboardActionListener = new OnKeyboardActionListener() {
    
        public final static int CodeDelete = -5; // Keyboard.KEYCODE_DELETE
        public final static int CodeCancel = -3; // Keyboard.KEYCODE_CANCEL
        public final static int CodePrev = 55000;
        public final static int CodeAllLeft = 55001;
        public final static int CodeLeft = 55002;
        public final static int CodeRight = 55003;
        public final static int CodeAllRight = 55004;
        public final static int CodeNext = 55005;
        public final static int CodeClear = 55006;
    
        @Override
        public void onKey(int primaryCode, int[] keyCodes) {
            // NOTE We can say '<Key android:codes="49,50" ... >' in the xml
            // file; all codes come in keyCodes, the first in this list in
            // primaryCode
            // Get the EditText and its Editable
            View focusCurrent = mHostActivity.getWindow().getCurrentFocus();
            if (focusCurrent == null
                    || focusCurrent.getClass() != EditText.class)
                return;
            EditText edittext = (EditText) focusCurrent;
            Editable editable = edittext.getText();
            int start = edittext.getSelectionStart();
            // Apply the key to the edittext
            if (primaryCode == CodeCancel) {
                hideCustomKeyboard();
            } else if (primaryCode == CodeDelete) {
                if (editable != null && start > 0)
                    editable.delete(start - 1, start);
            } else if (primaryCode == CodeClear) {
                if (editable != null)
                    editable.clear();
            } else if (primaryCode == CodeLeft) {
                if (start > 0)
                    edittext.setSelection(start - 1);
            } else if (primaryCode == CodeRight) {
                if (start < edittext.length())
                    edittext.setSelection(start + 1);
            } else if (primaryCode == CodeAllLeft) {
                edittext.setSelection(0);
            } else if (primaryCode == CodeAllRight) {
                edittext.setSelection(edittext.length());
            } else if (primaryCode == CodePrev) {
                View focusNew = edittext.focusSearch(View.FOCUS_BACKWARD);
                if (focusNew != null)
                    focusNew.requestFocus();
            } else if (primaryCode == CodeNext) {
                View focusNew = edittext.focusSearch(View.FOCUS_FORWARD);
                if (focusNew != null)
                    focusNew.requestFocus();
            } else { // insert character
                editable.insert(start, Character.toString((char) primaryCode));
            }
        }
    
        @Override
        public void onPress(int arg0) {
        }
    
        @Override
        public void onRelease(int primaryCode) {
        }
    
        @Override
        public void onText(CharSequence text) {
        }
    
        @Override
        public void swipeDown() {
        }
    
        @Override
        public void swipeLeft() {
        }
    
        @Override
        public void swipeRight() {
        }
    
        @Override
        public void swipeUp() {
        }
    };
    
    /**
     * Create a custom keyboard, that uses the KeyboardView (with resource id
     * <var>viewid</var>) of the <var>host</var> activity, and load the keyboard
     * layout from xml file <var>layoutid</var> (see {@link Keyboard} for
     * description). Note that the <var>host</var> activity must have a
     * <var>KeyboardView</var> in its layout (typically aligned with the bottom
     * of the activity). Note that the keyboard layout xml file may include key
     * codes for navigation; see the constants in this class for their values.
     * Note that to enable EditText's to use this custom keyboard, call the
     * {@link #registerEditText(int)}.
     * 
     * @param host
     *            The hosting activity.
     * @param viewid
     *            The id of the KeyboardView.
     * @param layoutid
     *            The id of the xml file containing the keyboard layout.
     */
    public CustomKeyboard(Activity host, int viewid, int layoutid) {
        mHostActivity = host;
        mKeyboardView = (KeyboardView) mHostActivity.findViewById(viewid);
        mKeyboardView.setKeyboard(new Keyboard(mHostActivity, layoutid));
        mKeyboardView.setPreviewEnabled(false); // NOTE Do not show the preview
                                                // balloons
        mKeyboardView.setOnKeyboardActionListener(mOnKeyboardActionListener);
        // Hide the standard keyboard initially
        mHostActivity.getWindow().setSoftInputMode(
                WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
    }
    
    /** Returns whether the CustomKeyboard is visible. */
    public boolean isCustomKeyboardVisible() {
        return mKeyboardView.getVisibility() == View.VISIBLE;
    }
    
    /**
     * Make the CustomKeyboard visible, and hide the system keyboard for view v.
     */
    public void showCustomKeyboard(View v) {
        mKeyboardView.setVisibility(View.VISIBLE);
        mKeyboardView.setEnabled(true);
        if (v != null)
            ((InputMethodManager) mHostActivity
                    .getSystemService(Activity.INPUT_METHOD_SERVICE))
                    .hideSoftInputFromWindow(v.getWindowToken(), 0);
    }
    
    /** Make the CustomKeyboard invisible. */
    public void hideCustomKeyboard() {
        mKeyboardView.setVisibility(View.GONE);
        mKeyboardView.setEnabled(false);
    }
    
    /**
     * Register <var>EditText<var> with resource id <var>resid</var> (on the
     * hosting activity) for using this custom keyboard.
     * 
     * @param resid
     *            The resource id of the EditText that registers to the custom
     *            keyboard.
     */
    public void registerEditText(int resid) {
        // Find the EditText 'resid'
        EditText edittext = (EditText) mHostActivity.findViewById(resid);
        // Make the custom keyboard appear
        edittext.setOnFocusChangeListener(new OnFocusChangeListener() {
            // NOTE By setting the on focus listener, we can show the custom
            // keyboard when the edit box gets focus, but also hide it when the
            // edit box loses focus
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus)
                    showCustomKeyboard(v);
                else
                    hideCustomKeyboard();
            }
        });
        edittext.setOnClickListener(new OnClickListener() {
            // NOTE By setting the on click listener, we can show the custom
            // keyboard again, by tapping on an edit box that already had focus
            // (but that had the keyboard hidden).
            @Override
            public void onClick(View v) {
                showCustomKeyboard(v);
            }
        });
        // Disable standard keyboard hard way
        // NOTE There is also an easy way:
        // 'edittext.setInputType(InputType.TYPE_NULL)' (but you will not have a
        // cursor, and no 'edittext.setCursorVisible(true)' doesn't work )
        edittext.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                EditText edittext = (EditText) v;
                int inType = edittext.getInputType(); // Backup the input type
                edittext.setInputType(InputType.TYPE_NULL); // Disable standard
                                                            // keyboard
                edittext.onTouchEvent(event); // Call native handler
                edittext.setInputType(inType); // Restore input type
                return true; // Consume touch event
            }
        });
        // Disable spell check (hex strings look like words to Android)
        edittext.setInputType(edittext.getInputType()
                | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
    }
    
    }
    
    // NOTE How can we change the background color of some keys (like the
    // shift/ctrl/alt)?
    // NOTE What does android:keyEdgeFlags do/mean
    

相关问题