安卓開發(fā) 自定義軟鍵盤 從原理到應用 可更改個別鍵顏色等

前言

這個是富文本寫的霍殴,代碼看起來很亂,請移步http://www.reibang.com/p/b1973de976e4

正文

對于自定義鍵盤匆瓜,官方提供了兩個玩意(再簡單的鍵盤也都要用到):KeyboardKeyboardView,當然,為了方便我們會定義一個util:KeyboardUtil

Keyboard

Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard consists of rows of keys.

加載鍵盤的XML描述并存儲鍵的屬性章姓。鍵盤由一行鍵組成。(還有翻譯识埋,我真貼心)

第一個重點就在這凡伊,你的鍵只能按官方指示一行一行進行放置。為什么窒舟?沒有為什么不信看下去系忙。

keyboard是一個xml文件,下面有個例子:


具體描述如下:

實例為三列四行標準格式惠豺,接下來聊一聊標準:最標準的莫過于每個鍵同樣的高度同樣的寬度银还,當然這是很理想的一種形式风宁。我們一般會得到UI強制規(guī)定的個性化鍵盤


不同顏色的自定義鍵下面說別著急,對于上面這樣的不規(guī)則鍵盤蛹疯,因為只能一行一行放置鍵戒财,

所以首先keyWidth我們設置為25%p我們一行最多要放四個鍵,一三行我們放四個鍵二四行放三個鍵捺弦,第一三行最后一個鍵高度為其他鍵高度的兩倍需要在<key />里面單獨寫keyHeight宋渔,同理如果鍵寬不一樣的話單獨設置即可川梅。

KeyboardView

A view that renders a virtual Keyboard. It handles rendering of keys and detecting key presses and touch movements.

呈現(xiàn)虛擬鍵盤的視圖蝇更。它處理按鍵的渲染和檢測按鍵和觸摸動作遵蚜。

這個東西就是寫在布局里的view了

示例如下:

這是我重寫掉的,后面會講寞钥。

具體屬性如下:

android:shadowRadius="0.0"? android:shadowColor="背景色"

這兩個屬性可以解決鍵盤上顯示的文字糊的問題慌申。

KeyboardUtil


public class KeyboardUtil {

????private Viewll_jianpan;

????private KeyboardViewmKeyboardView;

????private KeyboardmNumberKeyboard;// 數(shù)字鍵盤

? ? private KeyboardmLetterKeyboard;// 字母鍵盤

? ? private ContextmContext;

????private boolean isNumber =false;// 是否數(shù)字鍵盤

? ? private boolean isUpper =false;// 是否大寫

? ? private EditTextmEditText;

? ? public KeyboardUtil(Context context, View view, EditText editText,int type) {

? ? ????mContext=context;

????????mEditText = editText;

????????mLetterKeyboard =new Keyboard(context, R.xml.keyboard_qwerty);

????????mKeyboardView = (KeyboardView) view.findViewById(R.id.keyboard_view);

????????ll_jianpan= view.findViewById(R.id.ll_jianpan);

????????ImageView iv_close= (ImageView)ll_jianpan.findViewById(R.id.iv_close);

????????iv_close.setOnClickListener(new View.OnClickListener() {

????????????@Override

? ? ? ? ? ? public void onClick(View view) {

????????????????hideKeyboard();

????????????}

????????});

????????if (type==0){

????????mNumberKeyboard =new Keyboard(context, R.xml.keyboard_numbers_blank);

????????}else if (type==1){

????????mNumberKeyboard =new Keyboard(context, R.xml.keyboard_numbers);

????????}else if (type==2){

????????mNumberKeyboard =new Keyboard(context, R.xml.keyboard_numbers_realname);

????????}else if (type==66299){

????????mNumberKeyboard =new Keyboard(context, R.xml.keyboard_numbers_blank);

????????iv_close.setVisibility(View.GONE);

????????}

????????mKeyboardView.setKeyboard(mNumberKeyboard);

????????mKeyboardView.setEnabled(true);

????????mKeyboardView.setPreviewEnabled(false);

????????mKeyboardView.setOnKeyboardActionListener(listener);

}

public KeyboardUtil(Context context, Activity activity, EditText editText,int type) {

????mContext=context;

????mEditText = editText;

????if (type==0){

????????mNumberKeyboard =new Keyboard(context, R.xml.keyboard_numbers_blank);

????}else if (type==1){

????????mNumberKeyboard =new Keyboard(context, R.xml.keyboard_numbers);

????}else if (type==2){

????????mNumberKeyboard =new Keyboard(context, R.xml.keyboard_numbers_realname);

????}

????????mLetterKeyboard =new Keyboard(context, R.xml.keyboard_qwerty);

????????mKeyboardView = (KeyboardView) activity.findViewById(R.id.keyboard_view);

????????ll_jianpan= activity.findViewById(R.id.ll_jianpan);

????????mKeyboardView.setKeyboard(mNumberKeyboard);

????????mKeyboardView.setEnabled(true);

????????mKeyboardView.setPreviewEnabled(false);

????????mKeyboardView.setOnKeyboardActionListener(listener);

????????ImageView iv_close= (ImageView)ll_jianpan.findViewById(R.id.iv_close);

????????iv_close.setOnClickListener(new View.OnClickListener() {

????????????@Override

? ? ? ? ? ? public void onClick(View view) {

????????????????hideKeyboard();

????????}

????});

}

????private KeyboardView.OnKeyboardActionListenerlistener =new KeyboardView.OnKeyboardActionListener() {

????@Override

? ? ? ? public void onPress(int primaryCode) {}

????@Override

? ? ? ? public void onRelease(int primaryCode) {}

????@Override

? ? ? ? public void onKey(int primaryCode,int[] keyCodes) {

????????????Editable editable =mEditText.getText();

????????????int start =mEditText.getSelectionStart();

? ? ? ? ? ? if (primaryCode == Keyboard.KEYCODE_CANCEL||primaryCode ==66299) ????????????{// cancel

? ? ? ? ? ? ? ? hideKeyboard();

????????????}else if (primaryCode == Keyboard.KEYCODE_DELETE) {// 回退

? ? ? ? ? ? ? ? if (editable !=null && editable.length() >0) {

????????????????????if (start >0) {

????????????????????editable.delete(start -1, start);

????????????????}

????????????}

????}else if (primaryCode == Keyboard.KEYCODE_SHIFT) {// 大小寫切換

? ? ? ? ? ? ? ? changeKeyboart();

mKeyboardView.setKeyboard(mLetterKeyboard);

}else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {// 數(shù)字與字母鍵盤互換

? ? ? ? ? ? ? ? if (isNumber) {

isNumber =false;

mKeyboardView.setKeyboard(mLetterKeyboard);

}else {

isNumber =true;

mKeyboardView.setKeyboard(mNumberKeyboard);

}

}else if (primaryCode ==57419) {// 左移

? ? ? ? ? ? ? ? if (start >0) {

mEditText.setSelection(start -1);

}

}else if (primaryCode ==57419) {// 右移

? ? ? ? ? ? ? ? if (start >mEditText.length()) {

mEditText.setSelection(start +1);

}

}else {// 輸入鍵盤值

? ? ? ? ? ? ? ? editable.insert(start, Character.toString((char) primaryCode));

}

}

@Override

? ? ? ? public void onText(CharSequence text) {}

@Override

? ? ? ? public void swipeLeft() {}

@Override

? ? ? ? public void swipeRight() {}

@Override

? ? ? ? public void swipeDown() {}

@Override

? ? ? ? public void swipeUp() {}

};

private void changeKeyboart() {

List keyList =mLetterKeyboard.getKeys();

if (isUpper) {// 大寫切換小寫

? ? ? ? ? ? isUpper =false;

for (Keyboard.Key key : keyList) {

if (key.label !=null && isLetter(key.label.toString())) {

key.label = key.label.toString().toLowerCase();

key.codes[0] = key.codes[0] +32;

}}}else {// 小寫切換成大寫

? ? ? ? ? ? isUpper =true;

for (Keyboard.Key key : keyList) {

if (key.label !=null && isLetter(key.label.toString())) {

key.label = key.label.toString().toUpperCase();

key.codes[0] = key.codes[0] -32;}}}}

/**

* 判斷是否是字母

*/

? ? private boolean isLetter(String str) {

String wordStr ="abcdefghijklmnopqrstuvwxyz";

return wordStr.contains(str.toLowerCase());

}

public void hideKeyboard() {

int visibility =ll_jianpan.getVisibility();

if (visibility == View.VISIBLE) {

ll_jianpan.startAnimation(AnimationUtils.loadAnimation(mContext,R.anim.anim_bottom_out));

ll_jianpan.setVisibility(View.GONE);

}}

public void showKeyboard() {

int visibility =ll_jianpan.getVisibility();

if (visibility == View.GONE || visibility == View.INVISIBLE) {

ll_jianpan.startAnimation(AnimationUtils.loadAnimation(mContext,R.anim.anim_bottom_in));

ll_jianpan.setVisibility(View.VISIBLE);}}}

有點亂將就看。理郑。蹄溉。ll_jianpan其實就是一個包含keyboradview的線性布局

在這里比較重要的就是實現(xiàn)鍵盤的監(jiān)聽OnKeyboardActionListener

下面有一張對應表code對應ASCII值? 然后輸出的就是控制字符?

當然我們肯定需要自定義一些功能,如關閉鍵盤切換數(shù)字字母鍵盤左移右移等您炉,這些都放在了OnKeyboardActionListener的onKey中柒爵。其實就是根據(jù)不同的code處理不同的事件,自定義code盡量個性點防止跟已占用code發(fā)生沖突邻吭。

既然是自定義鍵盤餐弱,我們當然要阻攔系統(tǒng)鍵盤,方法如下

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

????你的輸入框.setShowSoftInputOnFocus(false);

}else {

????你的輸入框.setInputType(InputType.TYPE_NULL);

}

PS:setInputType(InputType.TYPE_NULL)會讓輸入框失去光標囱晴,但是沒辦法21以下的沒有setShowSoftInputOnFocus(false)這方法膏蚓。

至于打開鍵盤,可以在觸摸輸入框的時候觸發(fā)也可直接觸發(fā)

輸入框.setOnTouchListener(new View.OnTouchListener() {

????@Override

? ? public boolean onTouch(View view, MotionEvent motionEvent) {

? ? ? new KeyboardUtil(context,Activity.this,輸入框,0).showKeyboard();

????????return false;

????}

});

最后畸写,重寫的Keyboradview

public class MyKeyboredViewextends KeyboardView {

????public MyKeyboredView(Context context, AttributeSet attrs) {

????????super(context, attrs);

????}

????public MyKeyboredView(Context context, AttributeSet attrs,int defStyleAttr) {

????????super(context, attrs, defStyleAttr);

????}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)

????public MyKeyboredView(Context context, AttributeSet attrs,int defStyleAttr,int ????defStyleRes) {

????????super(context, attrs, defStyleAttr, defStyleRes);

????}

@Override

? ? public void onDraw(Canvas canvas) {

????????super.onDraw(canvas);

????????List keys = getKeyboard().getKeys();

????????for (Keyboard.Key key : keys) {

????????if (key.codes[0] ==66299) {

????????Log.e("KEY","Drawing key with code " + key.codes[0]);

????????Drawable dr = (Drawable)? ????????getInstance().getResources().getDrawable(R.drawable.jianpan_sure);

????????dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);

????????dr.draw(canvas);

}else {}}}}

重寫onDraw()根據(jù)code把點九圖充滿指定的鍵即可

下圖的確認鍵:

后記

看到這你可能在找demo源碼驮瞧,不好意思沒有的,如果你的時間確實很緊請移步枯芬,如果你還有點時間论笔,一天自己學完寫完沒什么問題的,歡迎提出問題千所,我們一起學習狂魔。


最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市淫痰,隨后出現(xiàn)的幾起案子最楷,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件籽孙,死亡現(xiàn)場離奇詭異烈评,居然都是意外死亡,警方通過查閱死者的電腦和手機犯建,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門讲冠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人适瓦,你說我怎么就攤上這事竿开。” “怎么了犹菇?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵德迹,是天一觀的道長芽卿。 經(jīng)常有香客問我揭芍,道長,這世上最難降的妖魔是什么卸例? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任称杨,我火速辦了婚禮,結果婚禮上筷转,老公的妹妹穿的比我還像新娘姑原。我一直安慰自己,他們只是感情好呜舒,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布锭汛。 她就那樣靜靜地躺著,像睡著了一般袭蝗。 火紅的嫁衣襯著肌膚如雪唤殴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天到腥,我揣著相機與錄音朵逝,去河邊找鬼。 笑死乡范,一個胖子當著我的面吹牛配名,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晋辆,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼渠脉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了瓶佳?” 一聲冷哼從身側響起芋膘,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后索赏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盼玄,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年潜腻,在試婚紗的時候發(fā)現(xiàn)自己被綠了埃儿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡融涣,死狀恐怖童番,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情威鹿,我是刑警寧澤剃斧,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站忽你,受9級特大地震影響幼东,放射性物質發(fā)生泄漏。R本人自食惡果不足惜科雳,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一根蟹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧糟秘,春花似錦简逮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至凌净,卻和暖如春悲龟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泻蚊。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工躲舌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人性雄。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓没卸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親秒旋。 傳聞我的和親對象是個殘疾皇子约计,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Android 中自定義軟鍵盤 \ \ \ 圖一為搜狗輸入法、圖二為自定義密碼鍵盤迁筛、圖三為自定義密碼鍵盤 java...
    來來來來看天上閱讀 758評論 0 0
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程煤蚌,因...
    小菜c閱讀 6,365評論 0 17
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器尉桩,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些閱讀 2,028評論 0 2
  • 下載 點擊官網(wǎng)下載界面筒占。如下圖,在download欄選擇對應版本進入相應下載界面(我選擇的是清者自清的7版本): ...
    valentizx閱讀 229評論 0 1