Chinese (Traditional) (中文(繁體)) translation by Fuhuan (you can also view the original English article)

大多數安卓設備是沒有物理鍵盤的,又不是十年前的半智能機,略略略。 用戶多靠虛擬或軟鍵盤來輸入文字信息。 如果你很喜歡玩機,知道如何構建自定義的虛擬鍵盤的話,會有一大群人膜拜你的水平。
使用Android SDK,你可以快速創建一個虛擬鍵盤,其代碼行數很少,因爲SDK可以處理許多低級任務,例如識別鍵盤觸摸,繪制鍵盤以及建立鍵盤和鍵盤之間的連接輸入字段。
在本教程中,你將學習如何編寫可用作Android設備默認鍵盤的全功能虛擬鍵盤。
1.首提條件
你將需要安裝Eclipse ADT Bundle。 你可以從Android Developer網站下載。
2.創建一個新項目
啓動Eclipse並創建一個新的Android APP。 調用這個應用程序,SimpleKeyboard。 再來一個獨特的命名。 將所需的最低SDK版本設置爲Android 2.2,並將目標SDK版本設置爲Android 4.4。

因爲此應用程序將沒有運行,因此取消選擇“下一部”並單擊“ 完成”。

3.編輯清單
Android操作系統將軟鍵盤視爲輸入法編輯器(IME)。 IME 在AndroidManifest.xml中聲明爲Service,它使用BIND_INPUT_METHOD權限並響應動作android.view.InputMethod。
將以下行代碼添加到清單的應用程序標記中:
<service android:name=".SimpleIME" android:label="@string/simple_ime" android:permission="android.permission.BIND_INPUT_METHOD" > <meta-data android:name="android.view.im" android:resource="@xml/method"/> <intent-filter> <action android:name="android.view.InputMethod" /> </intent-filter> </service>
4.創建method.xml
清單文件中的服務標簽包含一個引用名爲method.xml的XML文件的元數據標簽。 如果沒有此文件,Android 系統將無法將我們的服務識別爲有效的IME服務。 該文件包含有關輸入法及其子類型的詳細信息。 對于我們的鍵盤,我們爲en_US語言環境定義了一個子類型。 如果res / xml不存在,則創建目錄res / xml,並將文件method.xml添加到它。 該文件的內容應該是:
<?xml version="1.0" encoding="utf-8"?> <input-method xmlns:android="https://schemas.android.com/apk/res/android"> <subtype android:label="@string/subtype_en_US" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" /> </input-method>
5.編輯strings.xml
該應用使用的字符串在res / values / strings.xml文件中定義。 我們將需要三個字符串:
- 應用程序的名稱
- IME的標簽
- IME子類型的標簽
更新你的strings.xml,使其具有以下內容:
<resources> <string name="app_name">SimpleKeyboard</string> <string name="simple_ime">Simple IME</string> <string name="subtype_en_US">English (US)</string> </resources>
6.選擇鍵盤布局
我們的鍵盤布局只包含一個KeyboardView。 該layout_alignParentBottom屬性設置爲真,這樣鍵盤會出現在屏幕的底部。
創建一個名爲res / layout / keyboard.xml的文件,並將其內容替換爲以下內容:
<?xml version="1.0" encoding="UTF-8"?> <android.inputmethodservice.KeyboardView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/keyboard" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:keyPreviewLayout ="@layout/preview" />
該keyPreviewLayout是每當按下鍵盤上的鍵時暫時彈出顯示的一種布局。 它包含一個單獨的TextView。 創建一個名爲res / layout / preview.xml的文件並添加以下內容:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:background="#ffff00" android:textStyle="bold" android:textSize="30sp" > </TextView>
6.定義鍵盤按鍵
鍵盤按鍵及其位置的詳細信息在XML文件中指定。 每個鍵都有以下屬性:
- keyLabel:該屬性包含鍵上顯示的文本。
- keyLabel:該屬性包含鍵上顯示的文本。
例如,以限定用于字母的關鍵甲,所述代碼屬性的值應爲97和keyLabel屬性應設置爲甲。
如果多個代碼與一個密鑰相關聯,那麽該密鑰所代表的字符將取決于密鑰所接收的數量。 例如,如果一個鍵具有代碼63,33,和58:
- 在關鍵字上點擊一下就會輸出63?
- 快速連續兩次敲擊就會輸出33!
- 快速連續三次敲擊就會輸出58!
一個密鑰也可以有一些可選的屬性:
- keyEdgeFlags:該屬性可以將值左側或右側。 該屬性通常被添加到行的最左邊和最右邊的鍵上。
- keyWidth:這個屬性定義了一個鍵的寬度。 通常將其定義爲百分比值。
- isRepeatable:如果此屬性設置爲true,長按該鍵將多次重複該鍵的操作 。對于刪除鍵和空格鍵通常設置爲true。
鍵盤的鍵被分組爲行。 最好將一行上的按鍵數量限制爲最多十個,每個按鍵的寬度等于鍵盤的10%。 本教程中鍵的高度設置爲60dp。 該值可以調整,但不推薦使用小于48dp的值。 我們的鍵盤將有五行鍵。
我們現在可以繼續設計鍵盤。 創建一個名爲res / xml / qwerty.xml的新文件,並將其內容替換爲以下內容:
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android" android:keyWidth="10%p" android:horizontalGap="0px" android:verticalGap="0px" android:keyHeight="60dp" > <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> <Row> <Key android:codes="113" android:keyLabel="q" android:keyEdgeFlags="left"/> <Key android:codes="119" android:keyLabel="w"/> <Key android:codes="101" android:keyLabel="e"/> <Key android:codes="114" android:keyLabel="r"/> <Key android:codes="116" android:keyLabel="t"/> <Key android:codes="121" android:keyLabel="y"/> <Key android:codes="117" android:keyLabel="u"/> <Key android:codes="105" android:keyLabel="i"/> <Key android:codes="111" android:keyLabel="o"/> <Key android:codes="112" android:keyLabel="p" android:keyEdgeFlags="right"/> </Row> <Row> <Key android:codes="97" android:keyLabel="a" android:keyEdgeFlags="left"/> <Key android:codes="115" android:keyLabel="s"/> <Key android:codes="100" android:keyLabel="d"/> <Key android:codes="102" android:keyLabel="f"/> <Key android:codes="103" android:keyLabel="g"/> <Key android:codes="104" android:keyLabel="h"/> <Key android:codes="106" android:keyLabel="j"/> <Key android:codes="107" android:keyLabel="k"/> <Key android:codes="108" android:keyLabel="l"/> <Key android:codes="35,64" android:keyLabel="\# \@" android:keyEdgeFlags="right"/> </Row> <Row> <Key android:codes="-1" android:keyLabel="CAPS" android:keyEdgeFlags="left"/> <Key android:codes="122" android:keyLabel="z"/> <Key android:codes="120" android:keyLabel="x"/> <Key android:codes="99" android:keyLabel="c"/> <Key android:codes="118" android:keyLabel="v"/> <Key android:codes="98" android:keyLabel="b"/> <Key android:codes="110" android:keyLabel="n"/> <Key android:codes="109" android:keyLabel="m"/> <Key android:codes="46" android:keyLabel="."/> <Key android:codes="63,33,58" android:keyLabel="\? ! :" android:keyEdgeFlags="right"/> </Row> <Row android:rowEdgeFlags="bottom"> <Key android:codes="44" android:keyLabel="," android:keyWidth="10%p" android:keyEdgeFlags="left"/> <Key android:codes="47" android:keyLabel="/" android:keyWidth="10%p" /> <Key android:codes="32" android:keyLabel="SPACE" android:keyWidth="40%p" android:isRepeatable="true"/> <Key android:codes="-5" android:keyLabel="DEL" android:keyWidth="20%p" android:isRepeatable="true"/> <Key android:codes="-4" android:keyLabel="DONE" android:keyWidth="20%p" android:keyEdgeFlags="right"/> </Row> </Keyboard>
你可能已經注意到某些鍵對于codes屬性具有負值。 負值等于Keyboard類中的預定義常量。 例如,值-5等于Keyboard.KEYCODE_DELETE的值。
7.創建一個服務類
創建一個新的Java類並將其稱爲SimpleIME.java。 該類應該擴展InputMethodService類並實現OnKeyboardActionListener接口。 該OnKeyboardActionListener接口包含在軟鍵盤的按鍵敲擊或按下時調用的方法。
該SimpleIME類應該有三個變量:
- 一個KeyboardView引用布局中定義的視圖
- 一個分配給KeyboardView的鍵盤實例
- 一個布爾值告訴我們是否啓用了大寫字母鎖定
在聲明這些變量並添加OnKeyboardActionListener接口的方法之後,SimpleIME類應如下所示:
public class SimpleIME extends InputMethodService implements OnKeyboardActionListener{ private KeyboardView kv; private Keyboard keyboard; private boolean caps = false; @Override public void onKey(int primaryCode, int[] keyCodes) { } @Override public void onPress(int primaryCode) { } @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() { } }
當鍵盤被創建時,onCreateInputView方法被調用。 所有成員變量服務都可以在這裏初始化。 更新onCreateInputView方法的實現,如下所示:
@Override public View onCreateInputView() { kv = (KeyboardView)getLayoutInflater().inflate(R.layout.keyboard, null); keyboard = new Keyboard(this, R.xml.qwerty); kv.setKeyboard(keyboard); kv.setOnKeyboardActionListener(this); return kv; }
接下來,我們創建一個按下按鍵時播放聲音的方法。 我們使用AudioManager類播放聲音。 Android SDK包含一些按鍵的默認聲音效果,以及playClick方法中使用的聲音效果。
private void playClick(int keyCode){ AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE); switch(keyCode){ case 32: am.playSoundEffect(AudioManager.FX_KEYPRESS_SPACEBAR); break; case Keyboard.KEYCODE_DONE: case 10: am.playSoundEffect(AudioManager.FX_KEYPRESS_RETURN); break; case Keyboard.KEYCODE_DELETE: am.playSoundEffect(AudioManager.FX_KEYPRESS_DELETE); break; default: am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD); } }
Android SDK包含一些按鍵的默認聲音效果,以及playClick方法中使用的聲音效果。
該getCurrentInputConnection方法用于獲取到另一個應用程序的輸入字段中的連接。 一旦我們有了連接,我們可以使用以下方法:
- commitText將一個或多個字符添加到輸入字段
- deleteSurroundingText刪除輸入字段的一個或多個字符
- sendKeyEvent將事件(如KEYCODE_ENTER)發送到外部應用程序
只要用戶按下軟鍵盤上的某個鍵,就會使用該鍵的unicode值作爲其參數之一調用onKey方法。 根據此值,鍵盤執行以下操作之一:
- 如果代碼爲KEYCODE_DELETE,則使用deleteSurroundingText方法刪除光標左側的一個字符。
- 如果代碼是KEYCODE_DONE,則觸發KEYCODE_ENTER鍵事件。
- 如果代碼是KEYCODE_SHIFT,則caps變量的值將更改,並且使用setShifted方法更新鍵盤的移位狀態。 當狀態改變時鍵盤需要重新繪制,以便更新鍵的標簽。 該invalidateAllKeys方法用于重繪所有密鑰。
- 對于所有其他代碼,代碼僅轉換爲字符並發送到輸入字段。 如果代碼表示字母表中的字母,並且caps變量設置爲true,則該字符將轉換爲大寫字母。
更新onKey方法,使其看起來像這樣:
@Override public void onKey(int primaryCode, int[] keyCodes) { InputConnection ic = getCurrentInputConnection(); playClick(primaryCode); switch(primaryCode){ case Keyboard.KEYCODE_DELETE : ic.deleteSurroundingText(1, 0); break; case Keyboard.KEYCODE_SHIFT: caps = !caps; keyboard.setShifted(caps); kv.invalidateAllKeys(); break; case Keyboard.KEYCODE_DONE: ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)); break; default: char code = (char)primaryCode; if(Character.isLetter(code) && caps){ code = Character.toUpperCase(code); } ic.commitText(String.valueOf(code),1); } }
8.測試鍵盤
軟鍵盤現在已准備好進行測試。 編譯並在Android設備上運行它。 此應用沒有“ 正在運行”,這意味著它不會顯示在啓動器中。 要使用它,應首先在設備的設置中激活它。

激活簡單IME後,打開任何允許輸入文本的應用程序(例如,任何消息應用程序),然後單擊其中一個輸入字段。 你應該在通知區域看到一個鍵盤圖標。 根據你的設備,你可以單擊該圖標或向下拖動通知欄,然後選擇簡單輸入法作爲輸入法。 你現在應該可以使用新鍵盤輸入。

結論
在本教程中,你學習了如何從頭開始創建自定義鍵盤應用程序。 要改變鍵盤的外觀和感覺,你只需在res / layout / keyboard.xml和res / layout / preview.xml文件中添加額外的樣式。 要更改密鑰的位置,請更新res / xml / qwerty.xml文件。 要向鍵盤添加更多功能,請參閱開發者文檔。
Envato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post