Android自定义数字键盘(支持随机数字)

前言 也是最近想写个demo玩玩,不知道写哪个方面的好,就随便写了一个自定义的键盘,比较简单,但是做了封装,支持jitpack库依赖(这也是我第一次开源自己的库,比较水的一个开源项目,仅供学习使用)。
概述 主要完成了以下功能:
1.自定义数字键盘
2.切换到随机数字键盘
3.自定义确定和删除等键(向外抛出接口,感觉设计的挺好)
下面先看下运行效果吧
Android自定义数字键盘(支持随机数字)
文章图片
效果图片 使用方法 1.在项目build.gradle文件中添加jitpack,添加jitpcak就够了。

allprojects { repositories { jcenter() maven { url 'https://jitpack.io' } } }

2.在module 的build.gradle文件添加依赖
compile 'com.github.Simon986793021:NumberKeyboard:v1.0'

3.在布局文件中添加布局

4.在MainActivity调用。
editText= (EditText) findViewById(R.id.et_numberplate); changebutton= (Button) findViewById(R.id.bt_change_keyboard); final OfoKeyboard keyboard = new OfoKeyboard(MainActivity.this); //获取到keyboard对象 changebutton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { keyboard.attachTo(editText,true); //eiditext绑定keyboard,true表示随机数字 } }); editText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { keyboard.attachTo(editText,false); //eiditext绑定keyboard,false表示普通数字键盘} }); /* 确定按钮 */ keyboard.setOnOkClick(new OfoKeyboard.OnOkClick() { @Override public void onOkClick() { Log.i(">>>>>>","点击了确定"); Toast.makeText(MainActivity.this,editText.getText().toString(),Toast.LENGTH_SHORT).show(); } }); //隐藏键盘按钮 keyboard.setOnCancelClick(new OfoKeyboard.OnCancelClcik() { @Override public void onCancelClick() { Toast.makeText(MainActivity.this,"隐藏键盘",Toast.LENGTH_SHORT).show(); } });

只需要这些简单的代码就能够实现一个自己定义的键盘了。
实现过程 1.新建一个keyboard布局 在看这个代码之前需要了解keyboard的属性:
不清楚属性,怎么画页面,不懂的请移步这篇博客
Android键盘属性
在 res 新建一个xml文件,然后在xml新建一个keyboard.xml
里面代码如下

这个布局就是自己自定义键盘的布局实现,有了布局,显然是不够的。
2.自定义KeyboardView
package com.wind.keyboard; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.inputmethodservice.Keyboard; import android.inputmethodservice.KeyboardView; import android.util.AttributeSet; import android.util.Log; import java.lang.reflect.Field; import java.util.List; /** * Created by zhangcong on 2017/8/24. */public class OfoKeyboardView extends KeyboardView { private Context context; private Keyboard keyboard; public OfoKeyboardView(Context context, AttributeSet attrs) { super(context, attrs); this.context=context; Log.i(">>>>>","构造函数被调用了"); } /** * 重新画一些按键 */ @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); keyboard = this.getKeyboard(); List keys = null; if (keyboard != null) { keys = keyboard.getKeys(); }if (keys != null) { for (Keyboard.Key key : keys) { // 数字键盘的处理 if (key.codes[0] == -4) { drawKeyBackground(R.drawable.bg_keyboardview_yes, canvas, key); drawText(canvas, key); } } } }private void drawKeyBackground(int drawableId, Canvas canvas, Keyboard.Key key) { Drawable npd = context.getResources().getDrawable( drawableId); int[] drawableState = key.getCurrentDrawableState(); if (key.codes[0] != 0) { npd.setState(drawableState); } npd.setBounds(key.x, key.y, key.x + key.width, key.y + key.height); npd.draw(canvas); }private void drawText(Canvas canvas, Keyboard.Key key) { Rect bounds = new Rect(); Paint paint = new Paint(); paint.setTextAlign(Paint.Align.CENTER); paint.setAntiAlias(true); paint.setColor(Color.WHITE); if (key.label != null) { String label = key.label.toString(); Field field; if (label.length() > 1 && key.codes.length < 2) { int labelTextSize = 0; try { field = KeyboardView.class.getDeclaredField("mLabelTextSize"); field.setAccessible(true); labelTextSize = (int) field.get(this); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } paint.setTextSize(labelTextSize); paint.setTypeface(Typeface.DEFAULT_BOLD); } else { int keyTextSize = 0; try { field = KeyboardView.class.getDeclaredField("mLabelTextSize"); field.setAccessible(true); keyTextSize = (int) field.get(this); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } paint.setTextSize(keyTextSize); paint.setTypeface(Typeface.DEFAULT); }paint.getTextBounds(key.label.toString(), 0, key.label.toString() .length(), bounds); canvas.drawText(key.label.toString(), key.x + (key.width / 2), (key.y + key.height / 2) + bounds.height() / 2, paint); } else if (key.icon != null) { key.icon.setBounds(key.x + (key.width - key.icon.getIntrinsicWidth()) / 2, key.y + (key.height - key.icon.getIntrinsicHeight()) / 2, key.x + (key.width - key.icon.getIntrinsicWidth()) / 2 + key.icon.getIntrinsicWidth(), key.y + (key.height - key.icon.getIntrinsicHeight()) / 2 + key.icon.getIntrinsicHeight()); key.icon.draw(canvas); }} }

3.KeyBoard的对象的创建:
package com.wind.keyboard; import android.app.Activity; import android.content.Context; import android.inputmethodservice.Keyboard; import android.inputmethodservice.KeyboardView; import android.os.Build; import android.text.Editable; import android.text.InputType; import android.util.Log; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Random; /** * Created by zhangcong on 2017/8/28. */public classOfoKeyboard { private Activity activity; private Keyboard keyboard; private OfoKeyboardView keyboardView; private EditText editText; private boolean isRandom=false; publicOfoKeyboard (Activity activity ) { this.activity=activity; keyboardView= (OfoKeyboardView) activity.findViewById(R.id.keyboard_view); } //点击事件触发 public void attachTo(EditText editText,boolean isRandom){/* 切换键盘需要重新new Keyboard对象,否则键盘不会改变,keyboardView放到构造函数里面,避免每次点击重新new 对象,提高性能 */ keyboard=new Keyboard(activity,R.xml.keyboard); this.isRandom=isRandom; Log.i(">>>>>","attachTo"); this.editText=editText; hideSystemSofeKeyboard(activity,editText); showSoftKeyboard(); }private void showSoftKeyboard() { if (keyboard == null) { keyboard = new Keyboard(activity, R.xml.keyboard); } if(keyboardView==null) { keyboardView= (OfoKeyboardView) activity.findViewById(R.id.keyboard_view); } if (isRandom) { randomKeyboardNumber(); } else { keyboardView.setKeyboard(keyboard); } keyboardView.setEnabled(true); keyboardView.setPreviewEnabled(false); keyboardView.setVisibility(View.VISIBLE); keyboardView.setOnKeyboardActionListener(listener); }private KeyboardView.OnKeyboardActionListener listener=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=editText.getText(); int start =editText.getSelectionStart(); if (primaryCode==Keyboard.KEYCODE_DELETE)//keycodes 为-5 { if (editable!=null&&editable.length()>0) { if (start>0) { editable.delete(start-1,start); } } } else if (primaryCode==Keyboard.KEYCODE_CANCEL) { hideKeyBoard(); if (mCancelClick!=null) { mCancelClick.onCancelClick(); } } else if (primaryCode==Keyboard.KEYCODE_DONE) { hideKeyBoard(); if (mOkClick!=null) { mOkClick.onOkClick(); } } else { Log.i(">>>>>>",primaryCode+"1"); Log.i(">>>>>>",(char) primaryCode+"2"); 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() {} }; public interface OnOkClick { void onOkClick(); } public interface OnCancelClcik{ void onCancelClick(); } public OnOkClick mOkClick; public OnCancelClcik mCancelClick; public void setOnOkClick(OnOkClick onOkClick) { this.mOkClick=onOkClick; } public void setOnCancelClick (OnCancelClcik onCancelClick) { this.mCancelClick=onCancelClick; } private void hideKeyBoard() { int visibility=keyboardView.getVisibility(); if (visibility==KeyboardView.VISIBLE) { keyboardView.setVisibility(KeyboardView.GONE); } } private boolean isNumber(String str) { String wordstr = "0123456789"; return wordstr.contains(str); }private void randomKeyboardNumber() { List keyList = keyboard.getKeys(); // 查找出0-9的数字键 List newkeyList = new ArrayList(); for (int i = 0; i < keyList.size(); i++) { if (keyList.get(i).label != null && isNumber(keyList.get(i).label.toString())) { newkeyList.add(keyList.get(i)); } } // 数组长度 int count = newkeyList.size(); // 结果集 List resultList = new ArrayList(); // 用一个LinkedList作为中介 LinkedList temp = new LinkedList(); // 初始化temp for (int i = 0; i < count; i++) { temp.add(new KeyModel(48 + i, i + "")); } // 取数 Random rand = new Random(); for (int i = 0; i < count; i++) { int num = rand.nextInt(count - i); resultList.add(new KeyModel(temp.get(num).getCode(), temp.get(num).getLable())); temp.remove(num); } for (int i = 0; i < newkeyList.size(); i++) { newkeyList.get(i).label = resultList.get(i).getLable(); newkeyList.get(i).codes[0] = resultList.get(i) .getCode(); } //hideKeyBoard(); keyboardView.setKeyboard(keyboard); }/** * 隐藏系统键盘 * * @param editText */ public static void hideSystemSofeKeyboard(Context context, EditText editText) { Log.i(">>>>>","hide"); int sdkInt = Build.VERSION.SDK_INT; if (sdkInt >= 11) { try { Class cls = EditText.class; Method setShowSoftInputOnFocus; setShowSoftInputOnFocus = cls.getMethod("setShowSoftInputOnFocus", boolean.class); setShowSoftInputOnFocus.setAccessible(true); setShowSoftInputOnFocus.invoke(editText, false); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } else { editText.setInputType(InputType.TYPE_NULL); } // 如果软键盘已经显示,则隐藏 InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(editText.getWindowToken(), 0); } }

到这里,自定义键盘就全部完成了。
总结 自定义键盘就是通过自定义一个键盘布局,然后通过keyboardView来展示出来。个人感觉没什么需要掌握的,不过可以学习一下代码的封装技巧。
Github地址
【Android自定义数字键盘(支持随机数字)】自定义键盘是比较简单的,但是个人感觉可以看看里面的一些代码封装的技巧,如果你觉得对你有帮助,麻烦来个star吧。

    推荐阅读