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篇之(五 ...
随机推荐
- 浅析JavaScript的字符串查找函数:indexOf和search
语法 ①indexOf:方法可返回某个指定的字符串值在长字符串中首次出现的位置.如果被查找字符串没有找到,返回-1. indexOf 说明:该方法将从头到尾地检索字符串 stringObject,看它 ...
- PHP成长之路之PHP连接MySql数据库(一)
PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言.语法吸收了C语言.Java和Perl的特点,利于学习,使用广泛,主要适用于W ...
- iOS OC利用imageview属性切出类似圆柱图形
效果一: 效果二: 上边的图形我也数不出来名字,,暂称圆柱正切图形吧,看到这样的需求似不似在想各种插件,各种切图方法了呢... UIImageView的属性可以轻松搞定 UIViewContentMo ...
- go defer (go延迟函数)
go defer (go延迟函数) Go语言的defer算是一个语言的新特性,至少对比当今主流编程语言如此.根据GO LANGUAGE SPEC的说法: A "defer" sta ...
- java中可变长参数
** * Created by Lenovo on 2017/12/10. * java中可变长参数 */ public class reflect04 { //m1有一个int类型的可比变长参数 / ...
- lumen安装后输出hello world
1.安装composer,具体请百度 2.composer 切换中国镜像,好处自己体会,命令如下 composer config -g repo.packagist composer https:// ...
- Java NIO (三) 通道(Channel)
通道(Channel):由 java.nio.channels 包定义的,Channel 表示 IO 源与目标打开的连接.Channel 类似于传统的"流",只不过 Channel ...
- java-FFmpeg(一) 实现视频的转码和截图功能
FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视频的完整解决方案.它包含了非常先进的音频/视频编解码库l ...
- Jmeter非GUI模式运行
非GUI模式,即命令行模式,运行 JMeter 测试脚本能够大大缩减所需要的系统资源. 使用的命令: jmeter -n -t 脚本文件路径 -l 结果输出文件路径 -j 日志文 ...
- PHP array_map()
PHP array_map() 函数 将函数作用到数组中的每个值上,每个值都乘以本身,并返回带有新值的数组: <?php function myfunction($v) { return($v* ...