现在很多场景需要使用自定义键盘,比如银行app的乱序密码键盘。现在做个demo,用最快的速度、最少的代码做出一个数字键盘,有基本的操作按键,效果如下图:
自定义键盘
自定义键盘的实现,需要用到系统Keyboard和KeybaordView两个类。
Keyboard
Keybard类可以加载一个描述键盘按键的xml文件,demo里的按键布局如下:
android:horizontalGap="1dp"
android:verticalGap="1dp"
android:keyWidth="20%p"
android:keyHeight="50dp">
android:keyEdgeFlags="left"/>
android:keyEdgeFlags="right"/>
android:keyEdgeFlags="left"
android:keyHeight="100.5dp"/>
android:keyEdgeFlags="right"
android:keyHeight="100.5dp"/>
android:keyEdgeFlags="right"
android:isRepeatable="true"/>
要注意的地方是:
键盘布局放在/res/xml
输出字符按键的android:codes需要是对应的ASCII码
有预定义常用操作,比如取消、完成、删除,可以直接用
比较折腾的是不知道如何让按键跨行跨列,文档里没有找到任何span方法。跨列容易解决,单独修改keyWidth就可以。跨行的话,现在的实现是让上一行key的height双倍,下一行的height为0,最终实现demo的效果,求更好的方法。
KeyboardView
KeyboardView处理了键盘的绘制、触摸、滑动等动作,加进Activity的布局里。
android:id="@+id/custom_keyboard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:background="@color/lightgray"
android:keyBackground="@drawable/btn_keyboard_key"
android:keyTextColor="@color/black"
android:keyTextSize="20dp"
android:paddingTop="1px"
android:shadowRadius="0"
android:visibility="gone"/>
具体属性参考官方文档,到这里,自定义键盘的ui已经定义好,下面看怎样跑起来。
键盘初始化
private void initKeyboard() {
Keyboard keyboard = new Keyboard(this, R.xml.number_input_keyboard);
mBinding.customKeyboard.setKeyboard(keyboard);
mBinding.customKeyboard.setEnabled(true);
mBinding.customKeyboard.setPreviewEnabled(false);
mBinding.customKeyboard.setOnKeyboardActionListener(new KeyboardView.OnKeyboardActionListener() {
@Override
public void onPress(int primaryCode) {
}
@Override
public void onRelease(int primaryCode) {
}
@Override
public void onKey(int primaryCode, int[] keyCodes) {
doCustomKeyboardKey(primaryCode, keyCodes);
}
@Override
public void onText(CharSequence text) {
}
@Override
public void swipeLeft() {
}
@Override
public void swipeRight() {
}
@Override
public void swipeDown() {
}
@Override
public void swipeUp() {
}
});
}
Keyboard和KeyboardView的初始化很简单,最重要的是实现OnKeyboardActionListener,提供了多个动作的回调,demo简单实现按键点击的处理。
private void doCustomKeyboardKey(int primaryCode, int[] keyCodes) {
Editable editable;
int selectionStart;
if (mBinding.et1.isFocused()) {
editable = mBinding.et1.getText();
selectionStart = mBinding.et1.getSelectionStart();
} else {
editable = mBinding.et2.getText();
selectionStart = mBinding.et2.getSelectionStart();
}
if (primaryCode == Keyboard.KEYCODE_CANCEL) {
hideKeyboard();
} else if (primaryCode == Keyboard.KEYCODE_DELETE) {
if (editable.length() > 0 && selectionStart > 0) {
editable.delete(selectionStart - 1, selectionStart);
}
} else if (primaryCode == -10) {
if (editable.length() > 0) {
editable.clear();
}
} else if (primaryCode == -11) {
mBinding.et1.requestFocus();
} else if (primaryCode == -12) {
mBinding.et2.requestFocus();
} else if (primaryCode == -99) {
//do nothing
} else {
editable.insert(selectionStart, Character.toString((char) primaryCode));
}
}
根据xml文件里预定好的primaryCode,根据实际情况处理各个按键的效果。
自定义EditText
使用自定义键盘的EditText需要增加处理系统键盘,最简单的方法就是直接隐藏。
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
requestFocus();
requestFocusFromTouch();
hideSysInput();
return true;
}
自定义键盘的打开
mBinding.et1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mBinding.customKeyboard.setVisibility(View.VISIBLE);
}
});
EditText增加监听onClick事件,直接让键盘显示。为什么不用OnFocusChangeListener呢,因为主动收起键盘,EditText的焦点没有改变,只有onClick才能再触发键盘打开。
几段代码就实现了一个自定义键盘,挺简单的。在此基础上,根据实际业务,我们可以扩展做出更复杂的效果。最后附上demo地址,谢谢观看。