Android 自定义安全软键盘 SafeKeyboard 开发详细说明 2.0
Android 自定义安全软键盘 SafeKeyboard 开发详细说明 2.0
源码地址:GitHub: https://github.com/SValence/SafeKeyboard
注意事项:SafeKeyboard 注意事项
一、Android 安全软键盘开发流程
1. 建立软键盘样式
即在项目
res 文件夹
下 新建xml 文件夹
, 并在该文件夹中创建所需要的各种软键盘的样式(比如说:字母、数字、符号 等)如下图所示:
2. 创建 layout
布局文件
- 在布局文件中给软键盘创建container,以便显示软键盘
3. 自定义 KeyboardView
- 自定义一个KeyboardView 并继承自KeyboardView,在自定义的KeyboardView中绘制特殊按键,包括按键的点击背景,图片,文字 等
4. 自定义一个普通 java
类,一般取名为 **Keyboard.java
把软键盘加载到container中,即在布局文件里预留的存放软键盘 的container
在类的内部实现软键盘的输入控制,键盘转换控制,软键盘的显示与隐藏控制 等
在需要用到软键盘的界面中实例化该
Keyboard
类,并传入必要的数据和信息
5. 效果图
- 如下图所示:
二、 Android
安全软键盘开发实例解析(仅作参考)
1. 创建项目后, 在 layout
布局文件中设计基本布局,参考如下
<!-- 详情请查看项目中 activity_main.xml 文件 --><?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/main_root"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><EditTextandroid:id="@+id/normalEditText"android:layout_width="match_parent"android:layout_height="50sp"android:layout_marginStart="10sp"android:layout_marginEnd="10sp"android:hint="@string/keyboard_system"android:inputType="text" /><EditTextandroid:id="@+id/safeEditText"android:layout_width="match_parent"android:layout_height="50sp"android:layout_marginStart="10sp"android:layout_marginEnd="10sp"android:hint="@string/keyboard_demo_new"android:inputType="textVisiblePassword" /><EditTextandroid:id="@+id/safeEditText2"android:layout_width="match_parent"android:layout_height="50sp"android:layout_marginStart="10sp"android:layout_marginEnd="10sp"android:hint="@string/keyboard_demo_new2"android:inputType="number" /><EditTextandroid:id="@+id/safeEditText3"android:layout_width="match_parent"android:layout_height="50sp"android:layout_marginStart="10sp"android:layout_marginEnd="10sp"android:hint="@string/keyboard_demo_new3" /></LinearLayout><LinearLayoutandroid:id="@+id/keyboardViewPlace"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:orientation="vertical" /></RelativeLayout>
这里使用一个线性布局作为存放自定义软键盘的容器,说明一下:
一般使用到自定义软键盘的页面的布局不会很复杂,无非就是想要在输入关键数据比如密码时才使用到软键盘,而软键盘一般都是在手机等移动设备屏幕的最下方显示,以方便输入,所以这里使用了
RelativeLayout
方便显示,当然也可以使用现在google
推行的ConstraintLayout
布局来做,这个根据个人喜好。所以在原有的项目里加入一个存放软键盘的容器,也不会给原有的项目带来很大的麻烦或者影响,所以这种做法,我个人认为还是可取的.
2. 在项目 res
文件夹下创建 xml
文件夹,并创建出自己需要的软键盘布局,比如说:数字,字母,符号等
- 字母键盘布局示例:
<!-- 详情及其他键盘布局请查看项目中 /res/xml 文件夹 --><?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"android:horizontalGap="1%p"android:keyHeight="@dimen/key_height"android:keyWidth="10%p"android:verticalGap="@dimen/key_vertical_gap"><Row><Key android:codes="113" android:keyEdgeFlags="left" android:keyLabel="q" android:keyWidth="8.9%p" /><Key android:codes="119" android:keyLabel="w" android:keyWidth="8.9%p" /><Key android:codes="101" android:keyLabel="e" android:keyWidth="8.9%p" /><Key android:codes="114" android:keyLabel="r" android:keyWidth="8.9%p" /><Key android:codes="116" android:keyLabel="t" android:keyWidth="8.9%p" /><Key android:codes="121" android:keyLabel="y" android:keyWidth="8.9%p" /><Key android:codes="117" android:keyLabel="u" android:keyWidth="8.9%p" /><Key android:codes="105" android:keyLabel="i" android:keyWidth="8.9%p" /><Key android:codes="111" android:keyLabel="o" android:keyWidth="8.9%p" /><Key android:codes="112" android:keyEdgeFlags="right" android:keyLabel="p" android:keyWidth="8.9%p" /></Row><Row><Key android:codes="97" android:horizontalGap="5.5%p" android:keyEdgeFlags="left" android:keyLabel="a" android:keyWidth="9%p" /><Key android:codes="115" android:keyLabel="s" android:keyWidth="9%p" /><Key android:codes="100" android:keyLabel="d" android:keyWidth="9%p" /><Key android:codes="102" android:keyLabel="f" android:keyWidth="9%p" /><Key android:codes="103" android:keyLabel="g" android:keyWidth="9%p" /><Key android:codes="104" android:keyLabel="h" android:keyWidth="9%p" /><Key android:codes="106" android:keyLabel="j" android:keyWidth="9%p" /><Key android:codes="107" android:keyLabel="k" android:keyWidth="9%p" /><Key android:codes="108" android:keyEdgeFlags="right" android:keyLabel="l" android:keyWidth="9%p" /></Row><Row><Key android:codes="-1" android:isModifier="true" android:isSticky="true" android:keyEdgeFlags="left" android:keyWidth="13%p" /><Key android:codes="122" android:horizontalGap="1.5%p" android:keyLabel="z" android:keyWidth="9%p" /><Key android:codes="120" android:keyLabel="x" android:keyWidth="9%p" /><Key android:codes="99" android:keyLabel="c" android:keyWidth="9%p" /><Key android:codes="118" android:keyLabel="v" android:keyWidth="9%p" /><Key android:codes="98" android:keyLabel="b" android:keyWidth="9%p" /><Key android:codes="110" android:keyLabel="n" android:keyWidth="9%p" /><Key android:codes="109" android:keyLabel="m" android:keyWidth="9%p" /><Key android:codes="-5" android:horizontalGap="1.5%p" android:isRepeatable="true" android:keyWidth="13%p" /></Row><Row android:rowEdgeFlags="bottom"><Key android:codes="-2" android:keyLabel="123" android:keyWidth="19%p" /><Key android:codes="32" android:isRepeatable="false" android:keyLabel="space" android:keyWidth="58%p" /><Key android:codes="100860" android:keyEdgeFlags="right" android:keyLabel="#+=" android:keyWidth="19%p" /></Row>
</Keyboard>
简单说明一下, 每个按键代表的字符的
keycode
一般来说都是固定的,android
系统会预先存储一些keycode
并占有这些数据我们在使用的时候直接拿来使用就可以,如果想自己来控制的话,就需要避过这些已经被系统占用的
code
比如说在符号键盘的最后一个
code
为100860
的按键,我在测试时曾经用过10086
作为code
,但是发现它的作用是输出一个图形字符,而不是切换到字母键盘的作用,说明10086
这个code
已经被系统占用,那code 10086
就不能继续使用, 这是开发者在使用的时候要注意的一个问题我甚至觉得, 如果只填写
android:codes
属性, 不填写android:keyLabel
, 如果系统已经占用的话, 会有个默认的文本输出 (纯猜测, 以后验证)以下为
Demo
中已有的多种键盘效果图:
3. 整个自定义软键盘布局文件(包括按键布局和点击输入完成隐藏输入法的布局) layout_keyboard_containor.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/keyboardBackColor"android:orientation="vertical"><RelativeLayoutandroid:id="@+id/keyboardHeader"android:layout_width="match_parent"android:layout_height="@dimen/keyboard_tip_height"android:background="@color/keyboardBackColor"><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="match_parent"android:layout_centerInParent="true"android:orientation="horizontal"tools:ignore="RelativeOverlap,UseCompoundDrawables"><ImageViewandroid:layout_width="25sp"android:layout_height="25sp"android:layout_gravity="center_vertical"android:contentDescription="@string/description"android:src="@drawable/shield" /><TextViewandroid:id="@+id/keyboardTip"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:text="@string/safe_keyboard"android:textColor="@color/lightGray"android:textSize="16sp" /></LinearLayout><FrameLayoutandroid:id="@+id/keyboardDone"android:layout_width="60sp"android:layout_height="match_parent"android:layout_alignParentEnd="true"android:layout_centerVertical="true"android:background="@drawable/bg_keyboard_done"><ImageViewandroid:layout_width="30sp"android:layout_height="30sp"android:layout_gravity="center"android:contentDescription="@null"android:scaleType="centerInside"android:src="@drawable/keyboard_done_"android:textColor="@color/white"android:textSize="16sp" /></FrameLayout></RelativeLayout><FrameLayoutandroid:id="@+id/keyboardLayer"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="2sp"android:layout_marginBottom="10sp"><com.safe.keyboard.SafeKeyboardViewandroid:id="@+id/safeKeyboardLetter"android:layout_width="match_parent"android:layout_height="wrap_content"android:animateLayoutChanges="true"android:background="@color/keyboardBackColor"android:focusable="true"android:focusableInTouchMode="true"android:keyBackground="@drawable/keyboard_press_bg"android:keyPreviewHeight="60dp"android:keyPreviewLayout="@layout/keyboard_preview_layout"android:keyPreviewOffset="0dp"android:keyTextColor="@color/white"app:random_digit="false"app:remember_last_type="true" /></FrameLayout>
</LinearLayout>
3.1 com.safe.keyboard.SafeKeyboardView
中的属性值得关注的有:
background="@color/keyboardBackColor"
background
设置了每个按键的点击背景变化, 这个是统一的设置的, 标签不支持单独设置背景, 当然有办法可以实现单独设置背景, 后面会继续介绍keyPreviewLayout="@layout/keyboard_preview_layout"
设置了keyPreviewLayout
属性后, 你点击按键时会显示出来当前点击a,以便提示用户是否点错,其内容也是一个布局文件,但是比较简单,一般来说就是一个设置了背景,字体大小和颜色的TextView
(下面会贴出样例的布局文件代码)与
keyPreview
相关的几个属性
需要注意的是keyPreviewOffset
这个属性,它决定了这个提示布局的显示位置,值越大显示位置越靠下,有兴趣的可以试一试这个属性,下面是keyboard_preview_layout.xml
字符提示预览布局文件<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="center"android:background="@drawable/keyboard_preview_bg"android:gravity="center_horizontal"android:textColor="@color/keyboardNormal"android:textSize="35sp"android:textStyle="bold" />
三、 Android
安全软键盘功能的 Java
逻辑 代码实现
- 划重点了
1. SafeKeyboardView.java
实现 (源码请查看 SafeKeyboardView.java
文件)
继承于 KeyboardView
,在这个自定义View中绘制一些特殊的按键,比如说 删除、大小写转换、切换键盘类型等等的按键,从而实现这些特殊按键的点击效果的转变。
删除、键盘切换、大小写切换 等按键需要区别于普通按键, 就不能使用统一设置的
background="@color/keyboardBackColor"
, 那么就需要重新绘制新的背景,同时由于重新绘制背景会覆盖原先设置的keyLabel
值, 所以同时需要重新绘制按键本, 即: 文件中的两个方法/*** @param id 背景资源 id* @param canvas Canvas* @param key 需要绘制的按键*/ drawKeyBackground(int id, Canvas canvas, Keyboard.Key key);/*** 该方法在绘制特殊按键图标时实现了: 保留图标原有的宽高比例, 保证图标不会被异常拉伸* 约定: 最终图标的宽度和高度都需要在按键的宽度和高度的二分之一以内* 如果: 图标的实际宽度和高度都在按键的宽度和高度的二分之一以内, 那就不需要变换, 否则就需要等比例缩小* 开发者可根据实际情况及个人喜好修改 此 `二分之一` 的约定* * @param canvas Canvas* @param key 需要绘制的按键* @param drawable 按键的图标* @param color 文字颜色*/ drawTextAndIcon(Canvas canvas, Keyboard.Key key, @Nullable Drawable drawable, int color)
2. SafeKeyboard.java
实现 (源码请查看 SafeKeyboard.java
文件)
SafeKeyboard
类是实现键盘输入等功能的核心,软键盘的输入、删除、显示、隐藏等等都需要在这里完成,其中最重要的有五个部分
SafeKeyboardView
要设置OnKeyboardActionListener
监听
- 隐藏系统默认输入法软键盘
- 支持多
EditText
共用一个SafeKeyboard
- 支持多
SafeKeyboard
的显示和隐藏动画
- 记住每个
EditText
上此所显示的键盘类型
- 记住每个
2.1 设置 OnKeyboardActionListener
监听详细介绍
这个地方我主要重写了 onKey(...)
, onPress(...)
两个方法
在
onPress(...)
中控制该类型的键盘开启按下按钮预览功能setPreviewEnabled(boolean)
在
onKey(...)
中控制键盘切换
、键盘隐藏
、英文大小写切换
、字符输入
等功能注意
正常的输入字符的时候,不能单纯的使用:
editable.insert(start, Character.toString((char) primaryCode));
要使用:
editable.replace(start, end, Character.toString((char) primaryCode));
因为这是默认不选中EditText
中文本情况,一旦选中文本就会造成最后的结果和期望的输入结果出现偏差,选中的文本没有被替换,只是纯粹的增加刚刚输入的字符,所以要获取EditText
中光标的开始和结束位置,并把输入的字符替换掉选中的文本部分. ( 这就是在效果图中有选中文本输入的原因 )
2.2 隐藏系统默认输入法软键盘
当我们需要显示自定义软键盘时, EditText
获取焦点后会弹出系统默认输入法键盘,这时,我们就需要强制隐藏默认键盘。需调用 private void hideSystemKeyBoard(EditText edit)
方法,(感谢网络上各位开发者的分享)
2.3 支持多 EditText
共用一个 SafeKeyboard
为实现此功能, 需要满足以下两点:
- 在
SafeKeyboard
中增加一个HashMap<Integer, EditText>
, 用于保存每个 需要使用SafeKeyboard
的EditText
- 在
- 将显示
SafeKeyboard
的布局文件根布局 id 传入并保存.
目的为: 设置全局焦点变化监听, 当焦点在页面中来回切换时决定对SafeKeyboard
进行适当的操作
详见 变量onGlobalFocusChangeListener
实现
- 将显示
2.4 SafeKeyboard
的显示和隐藏动画
如果我们对于输入法的显示和隐藏没有过多的要求,那么可以直接设置软键盘容器的 Visibility
为 GONE
或者 VISIBLE
,但是对于我这种有点强迫症的程序猿来说,能够把自己的项目的效果做的比较合情合理并给用户良好的体验,一直是我个人追求的事情。所以在上面的例子中增加了显示和隐藏动画,显示为从屏幕最下方滑动到固定位置,隐藏为从固定位置滑动到屏幕最下方,于是就多了 Animation
的使用。
当目标
EditText
被点击或者获得焦点的时候,如果SafeKeyboard
1 )SafeKeyboard
没有显示, 并且不处于正在显示过程 或者:
2 )SafeKeyboard
正在隐藏
那么强制隐藏系统默认键盘,显示SafeKeyboard
否则, 说明SafeKeyboard
处于显示状态, 这里根据对应的EditText
输入类型切换不同的键盘即可/** * 即调用此方法 * @param mEditText 目标输入框 */ private void keyboardPreShow(EditText mEditText)
当目标
EditText
失去焦点的时候,如果SafeKeyboard
1 )SafeKeyboard
已经显示,并不处于正在隐藏过程 或者:
2 )SafeKeyboard
正在显示
那么强制隐藏系统默认键盘,显示SafeKeyboard
否则, 说明SafeKeyboard
处于显示状态, 这里根据对应的EditText
输入类型切换不同的键盘即可/** * 即调用此方法 */ private void keyboardPreHide()
2.5 记住每个 EditText
上此所显示的键盘类型
记住每个 EditText
上此所显示的键盘类型, 并在其重新获得焦点显示 SafeKeyboard
时, 显示上次键盘
此功能可在布局文件中
app:remember_last_type="true"
或者直接调用
public void enableRememberLastKeyboardType(boolean enable)
进行指定
以上逻辑在代码中均有体现,实例项目源代码链接也会在文章结尾处贴出
感谢各位开发者的分享,参考项目:
1. https://www.cnblogs.com/liuyu0529/p/7793610.html , 因为本人不善于UI设计,所以键盘布局基本和这个项目区别不大,根据个人喜好作了一些必要的调整
2. https://github.com/StomHong/CustomizeKeyboard
因为一些项目需要,我在网上查了一些资料,参考已有项目,对开发 Android
自定义软键盘重新梳理和编程工作,并且增加和优化一些功能,有需要的开发者可以根据自己的项目需要进行参考或者修改。
源码地址:GitHub: https://github.com/SValence/SafeKeyboard
Android 自定义安全软键盘 SafeKeyboard 开发详细说明 2.0相关推荐
- Android自定义记账软键盘(仿鲨鱼记账的记账功能)
鲨鱼记账App效果: 本文实现的效果图: 本文 不是什么原理分析,属于使用工具,不再具体分析.直接贴图贴代码了 自定义软键盘的XML模版 注:android:codes的值,请参考ASCII < ...
- Android自定义输入法软键盘
1 功能描述 触屏设备主界面中有一个文本编辑框,底部区域固定显示一个数字键盘,键盘中除数字键外,还带有*和#键功能: 提供一个自定义的数字输入法,生成apk安装包文件,嵌入到img镜像文件中去. 2 ...
- android 自定义数字软键盘,Android自定义键盘的实现(数字键盘和字母键盘)
在项目中,产品对于输入方式会有特殊的要求,需要对输入方式增加特定的限制,这就需要采用自定义键盘.本文主要讲述数字键盘和字母键盘的自定义实现. 自定义键盘的实现步骤如下: 自定义CustomKeyboa ...
- android 键盘将底部视图顶起,android 弹出软键盘将底部视图顶起问题
今天要做一个搜索功能,搜索界面采用AutoCompleteTextView做搜索条,然后下面用listview来显示搜索结果,而我的主界面是在底 部用tab做了一个主界面导航,其中有一个搜索按钮,因为 ...
- Android 文本,软键盘使用指南
目录 TextView的基本使用 TextView的基本属性 图文混排的三种实现方式 drawableTop,DrawableBottom,DrawableLeft,drawableRight 通过I ...
- Android 监听软键盘的高度并解决其覆盖输入框的问题
1.前言 在某些项目中,我们常常需要自定义一个输入框,软键盘弹出时就把输入框顶上去,关闭时输入框再回到原位(比如下方的效果图,实际上各种 App 中的聊天界面和发布评论的界面大体都是这样).在这个过程 ...
- Android PopupWindow 隐藏软键盘的方法
今天,简单讲讲android里 PopupWindow 弹出在底部,被软键盘遮挡的问题. 之前,自己写一个PopupWindow 弹出在底部,可是如果软键盘显示时弹出,软键盘会遮挡PopupWi ...
- Android EditText将软键盘的回车改为搜索,并监听
需求为: 当用户在界面内点击输入框,弹出键盘,键盘右下角示意为"搜索"按钮 当用户输入内容后,点击搜索按钮将进行关键词搜索 当用户没有输入内容点击搜索按钮,将收起键盘,回到界面(这 ...
- android动态设置软键盘弹出模式,Android 弹出软键盘所遇到的坑及解决方法
重要代码: //1.此layout作为最外层的layout: //2.设置需要调整的view: setAdjustView(View view); //3.如果需要控制输入框的显示与隐藏,可以实现On ...
最新文章
- 简单的openssh自动升级脚本
- 【绝对干货】kafkastream广告
- android libc 有哪些函数_Android scudo功能介绍
- python读取pcd点云/转numpy(python2+python3,非ROS环境)
- dg修改归档目录 oracle_DG环境下ORACLE自动回收归档空间
- 单例模式访问mysql设计类图_如何应用策略设计模式分离JDBC数据库连接中的外部环境信息...
- 375. 猜数字大小 II leetcode java
- 三菱plcascll转换16进制_三菱ASCII码指令
- 51单片机LCD1602液晶屏调试工具
- Ubuntu安装Beyond Compare(五)
- APS系统是什么意思?起什么作用
- FCC Lifeline项目现已帮助美国低收入家庭接入高速互联网
- 105道 CSS 面试题,助你查漏补缺
- Opcua学习笔记1 opc介绍
- dmpython部署操作轨迹
- 《江畔独步寻花》教学设计
- 关于20年吉林电赛D题硬件电路的分享
- Html5 获取手机短信号码
- 网络编程经典好书推荐
- 1.3 URLify
热门文章
- 基因数据处理53之cs-bwamem集群版运行paird-end(1千万条100bp的reads)
- Apache Tomcat 7 HTTP连接器
- 【味觉模拟】重口味人士福利“智能咸味勺子”
- JavScript简介
- Open×××中虚拟ip地址的自定义分配
- 撑起个人信息安全“保护伞”
- pako的简单的使用
- 环形工频变压器线圈参数
- hao123网站需要服务器吗,我已经设置“www.hao123.com”为我的主页了,可是打开IE还是“http://www.k986.com/”这个网站,也查不出毒,怎么办?...
- mysql去除全角空格_PHP输出全角空格,导致页面布局混乱