700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Android 实现自定义安全数字键盘(仿微信)

Android 实现自定义安全数字键盘(仿微信)

时间:2023-04-22 22:24:38

相关推荐

Android 实现自定义安全数字键盘(仿微信)

背景

大部分的金融App会对默认的数字键盘进行处理,以实现自定义的数字安全键盘。基于此,本文对对微信数字键盘样式进行了仿写,实现了一套自定义的数字安全键盘(支持随机数字分布)。

一.图示效果

二.需要考虑的问题

布局的实现方式;

demo中使用了popupwindow,通过xml文件进行Tablayout布局。禁掉EditText默认软键盘的弹出,替换为自定义的数字键盘及与其它EditText切换焦点时的弹出效果;删除和增加字符时需要同步更新光标的位置;随机数字分布的实现;

三.实现代码

1.MainActivity调用处代码:

public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";private EditText numberEt;private KeyboardPopupWindow keyboardPopupWindow;private boolean isUiCreated = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initView() {numberEt = findViewById(R.id.numberEt);keyboardPopupWindow = new KeyboardPopupWindow(MainActivity.this, getWindow().getDecorView(), numberEt,true);// numberEt.setInputType(InputType.TYPE_NULL);//该设置会导致光标不可见numberEt.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (keyboardPopupWindow != null) {keyboardPopupWindow.show();}}});numberEt.setOnFocusChangeListener(new View.OnFocusChangeListener() {@Overridepublic void onFocusChange(View v, boolean hasFocus) {if (keyboardPopupWindow != null && isUiCreated) {//isUiCreated 很重要,Unable to add window -- token null is not valid; is your activity running?keyboardPopupWindow.refreshKeyboardOutSideTouchable(!hasFocus);// 需要等待页面创建完成后焦点变化才去显示自定义键盘}if (hasFocus) {//隐藏系统软键盘InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);imm.hideSoftInputFromWindow(numberEt.getWindowToken(), 0);}}});}@Overridepublic void onWindowFocusChanged(boolean hasFocus) {super.onWindowFocusChanged(hasFocus);isUiCreated = true;}@Overrideprotected void onDestroy() {if (keyboardPopupWindow != null) {keyboardPopupWindow.releaseResources();}super.onDestroy();}}

可以看到,这块的代码实现很简单,主要是通过KeyboardPopupWindow这个自定义的View来实现键盘弹出及按键点击效果。需要注意的是isUiCreated 这个标志位,需要通过onWindowFocusChanged等方法来确定当前页面加载完毕后去刷新自定义键盘的状态,否则会报错。

2.自定义数字键盘的代码:

public class KeyboardPopupWindow extends PopupWindow {private static final String TAG = "KeyboardPopupWindow";private Context context;private View anchorView;private View parentView;private EditText editText;private boolean isRandomSort = false;//数字是否随机排序private List<Integer> list = new ArrayList<>();private int[] commonButtonIds = new int[]{R.id.button00, R.id.button01, R.id.button02, R.id.button03,R.id.button04, R.id.button05, R.id.button06, R.id.button07, R.id.button08, R.id.button09};/*** @param context* @param anchorView* @param editText* @param isRandomSort 数字是否随机排序*/public KeyboardPopupWindow(Context context, View anchorView, EditText editText, boolean isRandomSort) {this.context = context;this.anchorView = anchorView;this.editText = editText;this.isRandomSort = isRandomSort;if (context == null || anchorView == null) {return;}initConfig();initView();}private void initConfig() {setOutsideTouchable(false);setFocusable(false);setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));forbidDefaultSoftKeyboard();}/*** 禁止系统默认的软键盘弹出*/private void forbidDefaultSoftKeyboard() {if (editText == null) {return;}if (android.os.Build.VERSION.SDK_INT > 10) {//4.0以上,使用反射的方式禁止系统自带的软键盘弹出try {Class<EditText> cls = EditText.class;Method setShowSoftInputOnFocus;setShowSoftInputOnFocus = cls.getMethod("setShowSoftInputOnFocus", boolean.class);setShowSoftInputOnFocus.setAccessible(true);setShowSoftInputOnFocus.invoke(editText, false);} catch (Exception e) {e.printStackTrace();}}}/*** 刷新自定义的popupwindow是否outside可触摸反应:如果是不可触摸的,则显示该软键盘view** @param isTouchable*/public void refreshKeyboardOutSideTouchable(boolean isTouchable) {setOutsideTouchable(isTouchable);if (!isTouchable) {show();} else {dismiss();}}private void initView() {parentView = LayoutInflater.from(context).inflate(R.layout.keyboadview, null);initKeyboardView(parentView);setWidth(ViewGroup.LayoutParams.MATCH_PARENT);setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);setContentView(parentView);}private void initKeyboardView(View view) {LinearLayout dropdownLl = view.findViewById(R.id.dropdownLl);dropdownLl.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {dismiss();}});//①给数字键设置点击监听for (int i = 0; i < commonButtonIds.length; i++) {final Button button = view.findViewById(commonButtonIds[i]);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int curSelection = editText.getSelectionStart();int length = editText.getText().toString().length();if (curSelection < length) {String content = editText.getText().toString();editText.setText(content.substring(0, curSelection) + button.getText() + content.subSequence(curSelection, length));editText.setSelection(curSelection + 1);} else {editText.setText(editText.getText().toString() + button.getText());editText.setSelection(editText.getText().toString().length());}}});}//②给小数点按键设置点击监听view.findViewById(R.id.buttonDot).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int curSelection = editText.getSelectionStart();int length = editText.getText().toString().length();if (curSelection < length) {String content = editText.getText().toString();editText.setText(content.substring(0, curSelection) + "." + content.subSequence(curSelection, length));editText.setSelection(curSelection + 1);} else {editText.setText(editText.getText().toString() + ".");editText.setSelection(editText.getText().toString().length());}}});//③给叉按键设置点击监听view.findViewById(R.id.buttonCross).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {int length = editText.getText().toString().length();int curSelection = editText.getSelectionStart();if (length > 0 && curSelection > 0 && curSelection <= length) {String content = editText.getText().toString();editText.setText(content.substring(0, curSelection - 1) + content.subSequence(curSelection, length));editText.setSelection(curSelection - 1);}}});}public void show() {if (!isShowing() && anchorView != null) {doRandomSortOp();this.showAtLocation(anchorView, Gravity.BOTTOM, 0, 0);}}/*** 随机分布数字*/private void doRandomSortOp() {if (parentView == null) {return;}if (!isRandomSort) {for (int i = 0; i < commonButtonIds.length; i++) {final Button button = parentView.findViewById(commonButtonIds[i]);button.setText("" + i);}} else {list.clear();Random ran = new Random();while (list.size() < commonButtonIds.length) {int n = ran.nextInt(commonButtonIds.length);if (!list.contains(n))list.add(n);}for (int i = 0; i < commonButtonIds.length; i++) {final Button button = parentView.findViewById(commonButtonIds[i]);button.setText("" + list.get(i));}}}public void releaseResources() {this.dismiss();context = null;anchorView = null;if (list != null) {list.clear();list = null;}}}

代码实现的逻辑相对简单:

通过给popupwindow设置contentView、弹出位置、边界外触摸参数等数值,实现大体样式上的效果;给contentView中的每个button设置点击事件,并处理传递的EditText数值及焦点变化情况;设置随机标志位,进行数值键盘数值随机的分布;forbidDefaultSoftKeyboard中处理:禁止EditText默认的软键盘弹出。因为要实现EditText焦点仍旧可见的效果,目前试过的其它集中方式仍有较大的缺陷,所以是通过反射的方法来达到目的。

四.小结

当然,除了以上方式,还可以使用系统的KeyboardView和Keyboard来实现相应的效果。

在仿写的过程中会发现,实现这一效果会涉及到一些体验性的细节点,而微信正是做到了这一点,所以在使用层面上会很方便。有些细节点会可能会比实现整个大致效果更为麻烦,但有时候恰巧这些很容易被忽视的小九九是与众不同的地方。

最后附上GitHub的源码地址:点击此处链接>>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。