工作中遇到了自定义软键盘的场景,虽然简单很快就实现了,但对个别的细节不太满意。
因为细节决定成败,所以细节之处也不能忽视。
先来张效果图吧:
key的相关属性:
row的相关属性:
KeyboardView的相关属性:
ASCII码对应表:
我对这个自定义软键盘做了个简单的封装,使用起来也很简单。以下是我的自定义软键盘View类:
package com.newcapec.visitorsystem.diyview; import android.app.Activity; import android.inputmethodservice.Keyboard; import android.inputmethodservice.KeyboardView; import android.text.Editable; import android.text.InputType; import android.util.Log; import android.view.View; import android.view.WindowManager; import android.widget.EditText; import com.newcapec.cardliarbry.VistorCardController; import com.newcapec.visitorsystem.R; import com.newcapec.visitorsystem.interf.OnFinishListener; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.List; /** * @author : xieqinzhong * @date :2020/6/16 14:52 * @description: **/ public class AbcNumberView extends View { private Activity mActivity; private MyKeyboardView mKeyboardView; private EditText mEdit; /** * 数字与大写字母键盘 */ private Keyboard numberKeyboard; /* * 确认回调 */ private OnFinishListener finishListener; private KeyboardView keyboardView; /* * id: 布局id * */ public AbcNumberView(int viewId,Activity activity,boolean includeNumber, EditText edit,OnFinishListener finishListener) { super(activity); mActivity = activity; mEdit = edit; this.finishListener = finishListener;//R.xml.abc_and_number if (includeNumber) { numberKeyboard = new Keyboard(activity, R.xml.abc_and_number); }else { numberKeyboard = new Keyboard(activity, R.xml.abc_key); } mKeyboardView = (MyKeyboardView) activity.findViewById(viewId); mKeyboardView.setKeyboard(numberKeyboard); mKeyboardView.setEnabled(true); mKeyboardView.setPreviewEnabled(false); mKeyboardView.setOnKeyboardActionListener(listener); mKeyboardView.bringToFront(); } private KeyboardView.OnKeyboardActionListener listener = new KeyboardView.OnKeyboardActionListener() { @Override public void swipeUp() { } @Override public void swipeRight() { } @Override public void swipeLeft() { } @Override public void swipeDown() { } @Override public void onText(CharSequence text) { } @Override public void onRelease(int primaryCode) { } @Override public void onPress(int primaryCode) { } @Override public void onKey(int primaryCode, int[] keyCodes) { Editable editable = mEdit.getText(); int start = mEdit.getSelectionStart(); //判定是否是中文的正则表达式 [\\u4e00-\\u9fa5]判断一个中文 [\\u4e00-\\u9fa5]+多个中文 if (primaryCode == -1) {// 确定键 hideKeyboard(); beginSearch(finishListener,mEdit.getText().toString()); } else if (primaryCode == -3) {//删除键 if (editable != null && editable.length() > 0) { if (start > 0) { editable.delete(start - 1, start); } } }else { editable.insert(start, Character.toString((char) primaryCode)); } } }; private void beginSearch(final OnFinishListener onFinishListener, String value) { finishListener.search(value); } /** * 软键盘展示状态 */ public boolean isShow() { return mKeyboardView.getVisibility() == View.VISIBLE; } /** * 软键盘展示 */ public void showKeyboard() { int visibility = mKeyboardView.getVisibility(); if (visibility == View.GONE || visibility == View.INVISIBLE) { mKeyboardView.setVisibility(View.VISIBLE); } } /** * 软键盘隐藏 */ public void hideKeyboard() { int visibility = mKeyboardView.getVisibility(); if (visibility == View.VISIBLE) { mKeyboardView.setVisibility(View.INVISIBLE); } } /** * 禁掉系统软键盘 */ public void hideSoftInputMethod() { mActivity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); int currentVersion = android.os.Build.VERSION.SDK_INT; String methodName = null; if (currentVersion >= 16) { // 4.2 methodName = "setShowSoftInputOnFocus"; } else if (currentVersion >= 14) { // 4.0 methodName = "setSoftInputShownOnFocus"; } if (methodName == null) { mEdit.setInputType(InputType.TYPE_NULL); } else { Class<EditText> cls = EditText.class; Method setShowSoftInputOnFocus; try { setShowSoftInputOnFocus = cls.getMethod(methodName, boolean.class); setShowSoftInputOnFocus.setAccessible(true); setShowSoftInputOnFocus.invoke(mEdit, false); } catch (NoSuchMethodException e) { mEdit.setInputType(InputType.TYPE_NULL); e.printStackTrace(); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } } } }
布局文件如下:
<?xml version="1.0" encoding="UTF-8"?> <Keyboard xmlns:android="http://schemas.android.com/apk/res/android" android:horizontalGap="10px" android:keyWidth="160dp" android:keyHeight="90dp" android:verticalGap="1%p"> <!--第一行--> <Row> <Key android:codes="49" android:keyLabel="1" /> <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:keyEdgeFlags="right" android:keyLabel="0" /> </Row> <!--第二行--> <Row> <Key android:codes="81" android:keyLabel="Q" /> <Key android:codes="87" android:keyLabel="W" /> <Key android:codes="69" android:keyLabel="E" /> <Key android:codes="82" android:keyLabel="R" /> <Key android:codes="84" android:keyLabel="T" /> <Key android:codes="89" android:keyLabel="Y" /> <Key android:codes="85" android:keyLabel="U" /> <Key android:codes="73" android:keyLabel="I" /> <Key android:codes="79" android:keyLabel="O" /> <Key android:codes="80" android:keyLabel="P" /> </Row> <!--第三行--> <Row> <Key android:codes="65" android:keyLabel="A" /> <Key android:codes="83" android:keyLabel="S" /> <Key android:codes="68" android:keyLabel="D" /> <Key android:codes="70" android:keyLabel="F" /> <Key android:codes="71" android:keyLabel="G" /> <Key android:codes="72" android:keyLabel="H" /> <Key android:codes="74" android:keyLabel="J" /> <Key android:codes="75" android:keyLabel="K" /> <Key android:codes="76" android:keyLabel="L" /> <Key android:codes="-1" android:keyIcon="@drawable/btn_ok" android:keyHeight="190dp" /> </Row> <!--第四行--> <Row> <Key android:codes="90" android:keyLabel="Z" /> <Key android:codes="88" android:keyLabel="X" /> <Key android:codes="67" android:keyLabel="C" /> <Key android:codes="86" android:keyLabel="V" /> <Key android:codes="66" android:keyLabel="B" /> <Key android:codes="78" android:keyLabel="N" /> <Key android:codes="77" android:keyLabel="M" /> <Key android:codes="-3" android:isRepeatable="false" android:keyIcon="@drawable/btn_del" android:keyWidth="330dp"/> </Row> </Keyboard>
使用也很简单:
mainBinding.includeBackscreenSearchLayout.edtInputPhone.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_UP) { abcNumberViewb.setOkListener(edtInputPhoneOkListener); abcNumberViewb.setmEdit( mainBinding.includeBackscreenSearchLayout.edtInputPhone); if(!abcNumberViewb.isShow()){ abcNumberViewb.showKeyboard(); } } return false; } });