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篇之(五 ...
随机推荐
- intellij idea svn使用一 导入、更新、提交、解决冲突
大体上是转载,针对版本14有一些特殊的添加. 查看svn的资源库: 下面的多出了一个svn的窗口,在左边有加号可以添加一个svn的库 输入svn的地址,我用的是本地的测试,所以地址为svn://127 ...
- python_web----------数据可视化从0到1的过程
一.数据可视化项目配置 1. django + Echarts 2. 服务器(linux:Ubuntu 17.04 (GNU/Linux 4.10.0-40-generic x86_64)) 3. I ...
- 使用canvas实现绚丽的时钟特效
源码 https://github.com/2016Messi/Gorgeous-clock 效果展示 https://2016messi.github.io/Gorgeous-clock/ 如果各位 ...
- 一次对象过大引起的gc性能问题的分析与定位
现象:一个接口在4C的机器上跑最大只有7TPS,CPU使用率就已经90%多. 定位: 1. 使用top命令查看CPU使用情况,找到进程号 2. 使用top -H -pid命令,查看进程信息,看到有 ...
- Python进阶之迭代器和生成器
可迭代对象 Python中任意的对象,只要它定义了可以返回一个迭代器的__iter__方法,或者定义了可以支持下标索引的__getitem__方法,那么它就是一个可迭代对象.简单来说,可迭代对象就是能 ...
- Python学习日记:day7-----集合
1.基础数据类型汇总补充 1,list: 在循环一个列表是,最好不能删除列表中的元素. 2,bool 空列表.int:0.空str.空dict.空set--->bool:false 其余为tru ...
- 在IntelliJ IDEA里创建简单的基于Maven的SpringMVC项目
后来发现了一种更加方便的创建方式,即第一步不选择Create from archetype,创建完毕后打开Project Structure-Modules,然后添加Web,但是注意添加的Web里面的 ...
- Memcached的简介和使用
缘起: 在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加了数据库负载.缓存是解决这个问题的好办法.但是ASP.NET中的虽然已经可以实现对页面局部进行缓存,但还是不够灵 ...
- window下mysql数据备份
今天我有个朋友让我帮他在windowServer服务器上备份一下mysql的数据库,于是花了一天的时间完成了一个每天定时备份数据库的功能,小编在这里为大家记录一下: 首先对于mysql命令行的导入导出 ...
- AdaBoost对实际数据分类的Julia实现
写在前面 AdaBoost是机器学习领域一个很重要很流行的算法,而Julia是一门新兴的发展迅速的科学计算语言.本文将从一个实际例子出发,展示如何用Julia语言实现AdaBoost算法. 什么是Ad ...