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篇之(五 ...
随机推荐
- 《程序设计方法》【PDF】下载
内容简介 <程序设计方法>主要以方法为主导,结合C语言,把程序设计方法学研究中若干成熟的理论和方法用通俗易懂的语言描述出来.<程序设计方法>还选取趣味性强.技巧性高.能够启发学 ...
- 字符串输入时的strlen()与\0
在做串的数据结构时,被字符串printf %s输出时的结尾判断.strlen();长度.自定义StrCopy();字符串复制函数.StrAssign();字符串赋值函数卡了一下,固写此博巩固相关知识点 ...
- puppet配置问题统计
一. [root@client puppet]# puppetd --test --server master.test.cominfo: Creating a new SSL key for cli ...
- ABP前端使用阿里云angular2 UI框架NG-ZORRO分享
一.前言 前段时间写博客分享和介绍了阿里云的UI框架NG-ZORRO(博客请查看:http://www.cnblogs.com/donaldtdz/p/7892960.html),结合近段时间对.Ne ...
- Say Hello to ConstraintLayout
ConstraintLayout介绍 ConstraintLayout让你可以在很平的view结构(没有多层布局嵌套)中构建一个复杂的布局结构. 有点像RelativeLayout, 所有的view都 ...
- 如何用jQuery实现五星好评
jQuery是js的一个库,封装了我们开发过程中常用的一些功能,方便我们来调用,提高了我们的开发效率. Js库是把我们常用的功能放到一个单独的文件中,我们用的时候,直接引用到页面里面来就可以了. 接下 ...
- bzoj 4898: [Apio2017]商旅
Description 在广阔的澳大利亚内陆地区长途跋涉后,你孤身一人带着一个背包来到了科巴.你被这个城市发达而美丽的市场所 深深吸引,决定定居于此,做一个商人.科巴有个集市,集市用从1到N的整数编号 ...
- jmeter中一次运行多条sql语句
操作比较简单,主要就分两步: 第一步:在JDBC Connection Configuration中设置,主要见下图标注部分增加:?allowMultiQueries=true 第二步:在JDBC R ...
- springBoot系列教程03:redis的集成及使用
1.为了高可用,先安装redis集群 参考我的另一篇文章 http://www.cnblogs.com/xiaochangwei/p/7993065.html 2.POM中引入redis <de ...
- php+中文分词scws+sphinx+mysql打造千万级数据全文搜索
转载自:http://blog.csdn.net/nuli888/article/details/51892776 Sphinx是由俄罗斯人Andrew Aksyonoff开发的一个全文检索引擎.意图 ...