Android自定义安全键盘
在银行APP里经常要自定义键盘,例如实现下面这样的效果
首先在xml文件里定义键盘
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android" android:keyWidth="30%p" android:horizontalGap="@dimen/keyboard_horizontalGap" android:verticalGap="@dimen/keyboard_verticalGap" android:keyHeight="47dp"> <Row> <Key android:codes="49" android:keyLabel="1" /> <Key android:codes="50" android:keyLabel="2" /> <Key android:codes="51" android:keyLabel="3" /> </Row> <Row> <Key android:codes="52" android:keyLabel="4" /> <Key android:codes="53" android:keyLabel="5" /> <Key android:codes="54" android:keyLabel="6" /> </Row> <Row> <Key android:codes="55" android:keyLabel="7" /> <Key android:codes="56" android:keyLabel="8" /> <Key android:codes="57" android:keyLabel="9" /> </Row> <Row> <Key android:codes="-2" android:keyLabel="ABC" /> <Key android:codes="48" android:keyLabel="0" /> <Key android:codes="-35" android:isRepeatable="true"/> </Row> </Keyboard>
keyWidth:每一个按钮的宽度
keyHeight:每一个按钮高度,可以设置百分比
horizontalGap:水平间隔
verticalGap:竖直间隔
Row:一行
每一个按键都将会有一个 codes 值,代表键盘上的按键
KhKeyboardView
public class KhKeyboardView { private Activity mContext; private View parentView; private KeyboardView mLetterView; //字母键盘view private KeyboardView mNumberView; //数字键盘View private Keyboard mNumberKeyboard; // 数字键盘 private Keyboard mLetterKeyboard; // 字母键盘 private Keyboard mSymbolKeyboard; // 符号键盘 private boolean isNumber = true; // 是否数字键盘 public static boolean isUpper = false; // 是否大写 private boolean isSymbol = false; // 是否是符号 private EditText mEditText; private View headerView; public void setEditText(EditText text) { mEditText = text; } public KhKeyboardView(Activity context, View view) { mContext = context; parentView = view; mNumberKeyboard = new Keyboard(mContext, R.xml.keyboard_numbers); mLetterKeyboard = new Keyboard(mContext, R.xml.keyboard_word); mSymbolKeyboard = new Keyboard(mContext, R.xml.keyboard_symbol); mNumberView = (KeyboardView) parentView.findViewById(R.id.keyboard_view); mLetterView = (KeyboardView) parentView.findViewById(R.id.keyboard_view_2); mNumberView.setKeyboard(mNumberKeyboard); mNumberView.setEnabled(true); mNumberView.setPreviewEnabled(false); mNumberView.setOnKeyboardActionListener(listener); mLetterView.setKeyboard(mLetterKeyboard); mLetterView.setEnabled(true); mLetterView.setPreviewEnabled(true); mLetterView.setOnKeyboardActionListener(listener); headerView = parentView.findViewById(R.id.keyboard_header); } private KeyboardView.OnKeyboardActionListener listener = new KeyboardView.OnKeyboardActionListener() { /** * 按下,在onKey之前,可以在这里做一些操作,这里让有的没有按下的悬浮提示 * @param primaryCode */ @Override public void onPress(int primaryCode) { Log.d("primaryCode","onPress--"+primaryCode); if (primaryCode == Keyboard.KEYCODE_SHIFT) { mLetterView.setPreviewEnabled(false); } else if (primaryCode == Keyboard.KEYCODE_DELETE) { mLetterView.setPreviewEnabled(false); } else if (primaryCode == 32) { mLetterView.setPreviewEnabled(false); } else { mLetterView.setPreviewEnabled(true); } } /** * 松开 * @param primaryCode */ @Override public void onRelease(int primaryCode) { Log.d("primaryCode","onRelease--"+primaryCode); } /** * 按下 * @param primaryCode * @param keyCodes */ @Override public void onKey(int primaryCode, int[] keyCodes) { Log.d("primaryCode","onKey--"+primaryCode); try { if (mEditText == null) return; Editable editable = mEditText.getText(); int start = mEditText.getSelectionStart(); if (primaryCode == Keyboard.KEYCODE_CANCEL) { // 隐藏键盘 hideKeyboard(); } else if (primaryCode == Keyboard.KEYCODE_DELETE || primaryCode == -35) { // 回退键,删除字符 if (editable != null && editable.length() > 0) { if (start > 0) { editable.delete(start - 1, start); } } } else if (primaryCode == Keyboard.KEYCODE_SHIFT) { // 大小写切换 changeKeyboart(); mLetterView.setKeyboard(mLetterKeyboard); } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) { // 数字与字母键盘互换 if (isNumber) { showLetterView(); showLetterView2(); } else { showNumberView(); } } else if (primaryCode == 90001) { // 字母与符号切换 if (isSymbol) { showLetterView2(); } else { showSymbolView(); } } else { // 输入键盘值 editable.insert(start, Character.toString((char) primaryCode)); } } catch (Exception e) { e.printStackTrace(); } } @Override public void onText(CharSequence text) { } @Override public void swipeLeft() { } @Override public void swipeRight() { } @Override public void swipeDown() { } @Override public void swipeUp() { } }; // 字母-符号,显示字母 private void showLetterView2() { if (mLetterView != null) { isSymbol = false; mLetterView.setKeyboard(mLetterKeyboard); } } // 字母-符号,显示符号 private void showSymbolView() { try { if (mLetterKeyboard != null) { isSymbol = true; mLetterView.setKeyboard(mSymbolKeyboard); } } catch (Exception e) { } } // 数字-字母,显示字母键盘 private void showLetterView() { try { if (mLetterView != null && mNumberView != null) { isNumber = false; mLetterView.setVisibility(View.VISIBLE); mNumberView.setVisibility(View.INVISIBLE); } } catch (Exception e) { e.printStackTrace(); } } // 数字-字母, 显示数字键盘 private void showNumberView() { try { if (mLetterView != null && mNumberView != null) { isNumber = true; mLetterView.setVisibility(View.INVISIBLE); mNumberView.setVisibility(View.VISIBLE); } } catch (Exception e) { e.printStackTrace(); } } /** * 切换大小写 */ private void changeKeyboart() { List<Keyboard.Key> keyList = mLetterKeyboard.getKeys(); if (isUpper) { // 大写切换小写 isUpper = false; for (Keyboard.Key key : keyList) { Drawable icon = key.icon; 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() { try { int visibility = mLetterView.getVisibility(); if (visibility == View.VISIBLE) { headerView.setVisibility(View.GONE); mLetterView.setVisibility(View.GONE); } visibility = mNumberView.getVisibility(); if (visibility == View.VISIBLE) { headerView.setVisibility(View.GONE); mNumberView.setVisibility(View.GONE); } } catch (Exception e) { e.printStackTrace(); } } /** * 显示键盘 * * @param editText */ public void showKeyboard(EditText editText) { try { this.mEditText = editText; int visibility = 0; int inputText = mEditText.getInputType(); headerView.setVisibility(View.VISIBLE); switch (inputText) { case InputType.TYPE_CLASS_NUMBER: showNumberView(); break; case InputType.TYPE_CLASS_PHONE: showNumberView(); break; case InputType.TYPE_NUMBER_FLAG_DECIMAL: showNumberView(); break; default: showLetterView(); break; } } catch (Exception e) { e.printStackTrace(); } } }
布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/rl_key" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#00000000" android:orientation="vertical"> <View android:id="@+id/keyboard_back_hide" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#7d7d7d" android:orientation="vertical"> <RelativeLayout android:id="@+id/keyboard_header" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="visible"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="智能安全加密键盘" android:textColor="#bfbfbf" android:textSize="15sp" /> <TextView android:id="@+id/keyboard_finish" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="10dp" android:padding="14dp" android:text="完成" android:textColor="#ffffff" android:textSize="15sp" /> </RelativeLayout> <ImageView android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginBottom="10dp" android:background="#555457" /> <FrameLayout android:id="@+id/keyboard_layer" android:layout_width="match_parent" android:layout_height="wrap_content"> <com.kh.keyboard.CustomKeyboardView android:id="@+id/keyboard_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#7d7d7d" android:focusable="true" android:focusableInTouchMode="true" android:keyBackground="@drawable/keyboard_number_selector_bg" android:keyPreviewLayout="@null" android:keyTextColor="#ffffff" android:visibility="gone" /> <com.kh.keyboard.CustomKeyboardView android:id="@+id/keyboard_view_2" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#7d7d7d" android:focusable="true" android:focusableInTouchMode="true" android:keyBackground="@drawable/keyboard_selector_bg" android:keyPreviewHeight="90dp" android:keyPreviewLayout="@layout/keyboard_key_preview_layout" android:keyPreviewOffset="45dp" android:keyTextColor="#ffffff" android:visibility="gone" /> </FrameLayout> </LinearLayout> </RelativeLayout>
public class CustomKeyboardView extends KeyboardView { private Context context; public CustomKeyboardView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); try { List<Keyboard.Key> keys = getKeyboard().getKeys(); for (Keyboard.Key key : keys) { // Log.e("KEY", "Drawing key with code " + key.codes[0]); if (key.codes[0] == -5) { Drawable dr = (Drawable) context.getResources().getDrawable(R.drawable.keyboard_word_del_layerlist); dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height); dr.draw(canvas); } else if (key.codes[0] == -35) { Drawable dr = (Drawable) context.getResources().getDrawable(R.drawable.keyboard_word_del_layerlist2); dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height); dr.draw(canvas); } else if (key.codes[0] == -1) { Drawable dr = (Drawable) context.getResources().getDrawable(R.drawable.keyboard_word_shift_layerlist); Drawable dr_da = (Drawable) context.getResources().getDrawable(R.drawable.keyboard_word_shift_layerlist_da); dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height); dr_da.setBounds(key.x, key.y, key.x + key.width, key.y + key.height); if (KhKeyboardView.isUpper) { dr_da.draw(canvas); } else { dr.draw(canvas); } } else if (key.codes[0] == -2 || key.codes[0] == 90001) { Drawable dr = (Drawable) context.getResources().getDrawable(R.drawable.keyboard_selector_blue_bg); dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height); dr.draw(canvas); drawText(canvas, key); } else { } } } catch (Exception e) { e.printStackTrace(); } } private void drawText(Canvas canvas, Keyboard.Key key) { try { 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); } } catch (Exception e) { e.printStackTrace(); } } }
public class KeyBoardDialogUtils implements View.OnClickListener { protected View view; protected Dialog popWindow; protected Activity mContext; private EditText contentView; private List<String> contentList; private KhKeyboardView keyboardUtil; public KeyBoardDialogUtils(Activity mContext) { try { this.mContext = mContext; if (contentList == null) { contentList = new ArrayList<>(); } if (popWindow == null) { view = LayoutInflater.from(mContext).inflate(R.layout.keyboard_key_board_popu, null); view.findViewById(R.id.keyboard_finish).setOnClickListener(this); view.findViewById(R.id.keyboard_back_hide).setOnClickListener(this); } popWindow.setContentView(view); popWindow.setCanceledOnTouchOutside(true); Window mWindow = popWindow.getWindow(); mWindow.setWindowAnimations(R.style.keyboard_popupAnimation); mWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); mWindow.setGravity(Gravity.BOTTOM | Gravity.FILL_HORIZONTAL); mWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); popWindow.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { if (contentView != null && contentView.isFocused()) { contentView.clearFocus(); } } }); initView(); } catch (Exception e) { e.printStackTrace(); } } private void initView() { try { if (keyboardUtil == null) keyboardUtil = new KhKeyboardView(mContext, view); } catch (Exception e) { e.printStackTrace(); } } public void show(final EditText editText) { editText.setFocusable(true); editText.setFocusableInTouchMode(true); editText.requestFocus(); popWindow.show(); keyboardUtil.showKeyboard(editText); } public void dismiss() { if (popWindow != null && popWindow.isShowing()) { popWindow.dismiss(); } } @Override public void onClick(View v) { try { int i = v.getId(); if (i == R.id.keyboard_finish) { keyboardUtil.hideKeyboard(); dismiss(); } else if (i == R.id.keyboard_back_hide) { keyboardUtil.hideKeyboard(); dismiss(); } } catch (Exception e) { e.printStackTrace(); } } }
使用
et = (EditText) findViewById(R.id.et); keyBoardDialogUtils = new KeyBoardDialogUtils(this); et.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { keyBoardDialogUtils.show(et); } });
Android自定义安全键盘的更多相关文章
- Android开发案例 - 自定义虚拟键盘
所有包含IM功能的App(如微信, 微博, QQ, 支付宝等)都提供了Emoji表情之类的虚拟键盘, 如下图: 本文只着重介绍如何实现输入法键盘和自定义虚拟键盘的流畅切换, 而不介绍如何实现虚 ...
- 关于在android手机中腾讯、阿里产品不自定义虚拟键盘的想法
1,自定义虚拟键盘,影响用户体验.你每个用户的喜好不一样,都有自己心仪的一款输入法.腾讯或是阿里设计出来的输入法很难满足上亿用户的喜好,到时候又是一场口水战,再说了就是专业的输入法肯定要比应用里嵌套的 ...
- (转)[原] Android 自定义View 密码框 例子
遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...
- Android 自定义View合集
自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...
- [原] Android 自定义View 密码框 例子
遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...
- android自定义view系列:认识activity结构
标签: android 自定义view activity 开发中虽然我们调用Activity的setContentView(R.layout.activity_main)方法显示View视图,但是vi ...
- android 自定义view 前的基础知识
本篇文章是自己自学自定义view前的准备,具体参考资料来自 Android LayoutInflater原理分析,带你一步步深入了解View(一) Android视图绘制流程完全解析,带你一步步深入了 ...
- 【朝花夕拾】Android自定义View篇之(八)多点触控(上)MotionEvent简介
前言 在前面的文章中,介绍了不少触摸相关的知识,但都是基于单点触控的,即一次只用一根手指.但是在实际使用App中,常常是多根手指同时操作,这就需要用到多点触控相关的知识了.多点触控是在Android2 ...
- 【朝花夕拾】Android自定义View篇之(六)Android事件分发机制(中)从源码分析事件分发逻辑及经常遇到的一些“诡异”现象
前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/11039252.html]谢谢! 在上一篇文章[[朝花夕拾]Android自定义View篇之(五 ...
随机推荐
- 查看SQL Server当前会话的隔离级别
查看SQL Server当前会话的隔离级别 DBCC USEROPTIONS
- iBATIS使用$和#的一些理解
我们在使用iBATIS时会经常用到#这个符号. 比如: sql 代码 select * from member where id =#id# 然后,我们会在程序中给id这个变量传递一个值,iBATIS ...
- Android项目实战(三十九):Android集成Unity3D项目(图文详解)
需求: Unity3D 一般用于做游戏 而且是跨平台的.原本设计是Android 应用端A(原生开发)进行一些业务处理,最后由A 打开Android 应用端B(Unity3D 游戏开发)进行游戏操作. ...
- 50、html补充
今天补充几个html标签 <body>内常用标签 1.<div>和<span> <div></div> : <div>只是一个块 ...
- MySQL锁总结
本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/78 MySQL 锁基础 参考了何登成老师文章的结构MySQL 加 ...
- StreamCQL编写jstorm拓扑任务入门
一,什么是 StreamCQL StreamCQL(Stream Continuous Query Language)是一个类似SQL的声明式语言, 目的是在流计算平台(目前也就是jstrom)的基础 ...
- MVC 框架
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码 ...
- windows上安装redis
The Redis project does not officially support Windows. However, the Microsoft Open Tech group develo ...
- Android真机安装sqlite3的方法
欢迎和大家交流技术相关问题: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://g ...
- java多线程(六)-线程的状态和常用的方法
一个线程可以处于以下几种状态之一: (1) 新建(new):当线程被创建时,它只会短暂的处于这种状态,此时它已经获得了必须的系统资源,并执行了初始化,该线程已经有资格获取cpu时间了,之后它将转化为可 ...