概述

突然发现好多软件都使用了自己定义的软键盘。自己就想着先把这块坑先踩踩把,以后掉坑的时候不至于帅的太惨。言归正传,对于自定义软键盘。需要用到系统提供的两个类:Keyboard和KeyboardView。

Keyboard

设计键盘的布局文件,官方上对Keyboard是这么解释的

Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard consists of rows of keys.The layout file for
a keyboard contains XML that looks like the following snippet:

也就是说这个Keyboard是一个xml文件,可以用来进行键盘的布局,格式如下:

<Keyboardandroid:keyWidth="%10p"android:keyHeight="50px"android:horizontalGap="2px"android:verticalGap="2px" ><Row android:keyWidth="32px" ><Keyandroid:codes="44"android:keyLabel=","android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/>...</Row>...</Keyboard>

下面是Keyboard描述键盘时的一些常用属性介绍

属性 描述
codes 按键对应的输出值,可以为unicode值或则逗号(,)分割的多个值,也可以为一个字 符串。在字符串中通过“\”来转义特殊字符,例如 ‘\n’ 或则 ‘\uxxxx’ 。Codes通常用来定义该键的键码,例如上图中的数字按键1对应的为49;如果提供的是逗号分割的多个值则和普通手机输入键盘一样在多个值之间切换
keyLabel 按键显示的文本内容
keyIcon 按键显示的图标内容,如果指定了该值则在显示的时候显示为图片不显示文本
keyWidth 按键的宽度,可以为精确值或则相对值,对于精确值支持多种单位,例如:像素,英寸 等;相对值为相对于基础取值的百分比,为以% 或则%p 结尾,其中%p表示相对于父容器
keyHeight 按键的高度,取值同keyWidth
horizontalGap 按键前的间隙(水平方向),取值取值同keyWidth
isSticky 按键是否为sticky的。例如Shift大小写切换按键,具有两种状态,按下状态和正常状态,取值为true或则false
isModifier 按键是否为功能键( modifier key ) ,例如 Alt 或则 Shift 。取值为true或则false
keyOutputText 按键输出的文本内容,取值为字符串
isRepeatable 按键是否是可重复的,如果长按该键可以触发重复按键事件则为true,否则为false
keyEdgeFlags 按键的对齐指令,取值为left或则right

KeyboardView

处理绘制,检测按键,触摸动作等

A view that renders a virtual Keyboard. It handles rendering of keys and detecting key presses and touch movements.

在这里渲染虚拟键盘的视图,并且处理按键的触摸和移动等操作。在Activity的布局文件中可以这样定义

<android.inputmethodservice.KeyboardViewandroid:id="@+id/keyboard_view"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:background="@color/gray"android:focusable="true"android:focusableInTouchMode="true"android:keyBackground="@drawable/bg_keyboard_selector"android:keyPreviewLayout="@layout/key_preview_layout"android:keyTextColor="@color/keyTextColor"android:visibility="gone"/>

下面介绍一些KeyboardView的属性

属性 描述
android:keyBackground 键的背景图
android:keyPreviewLayout 击键盘上的某个键时,短暂弹出的提示布局文件
android:keyPreviewOffset 击键盘上的某个键时,短暂弹出布局的垂直偏移量
android:keyTextColor 按键中的keyLabel的颜色
android:keyTextSize 按键中的keyLabel的大小
android:labelTextSize 如果有图片时,按键中的keyLabel的大小
android:popupLayout 弹出键盘的布局文件
android:verticalCorrection 补偿触摸Y坐标的偏移量,用于偏移校正

基本实现

一、定义键盘的键

自己定义的xml键盘布局位于res–>xml文件目录下

键盘上键的细节和它的位置我们指定在一个xml文件中,每一个键都有自己的属性。

  • keyLabel 这个属性是指每个键显示的文本
  • codes 这个属性是指这个键代表的字符的unicode

比如我们自己定义一个数字1,则他的codes属性的值是49,keyLabel属性的值就是1。

如果一个code对应多个key,这个key代表的字符取决于这个key接受到的点击数taps,例如,一个键具有49,50,51编码:

  • 一次点击就是 1
  • 两次点击就是 2
  • 三次点击就是 3

每个键都可以设置自己的属性,这里就不一一赘述了。当然,一般情况下键盘上每行的按键尽量都控制10个或10个以内,要不然影响用户体验,每行都使用进行分行。

一般自己定义的code都为负数,比如-5代表删除,-1代表shift切换等。

数字键盘number.xml

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"android:keyHeight="40dip"android:keyWidth="8.33334444%p"android:verticalGap="6dp"><Row><Key android:codes="49" android:horizontalGap="2dp" android:keyEdgeFlags="left"android:keyLabel="1"/><Key android:codes="50" android:horizontalGap="6dp" android:keyLabel="2"/><Key android:codes="51" android:horizontalGap="6dp" android:keyLabel="3"/><Key android:codes="52" android:horizontalGap="6dp" android:keyLabel="4"/><Key android:codes="53" android:horizontalGap="6dp" android:keyLabel="5"/><Key android:codes="54" android:horizontalGap="6dp" android:keyLabel="6"/><Key android:codes="55" android:horizontalGap="6dp" android:keyLabel="7"/><Key android:codes="56" android:horizontalGap="6dp" android:keyLabel="8"/><Key android:codes="57" android:horizontalGap="6dp" android:keyLabel="9"/><Key android:codes="48" android:horizontalGap="6dp" android:keyEdgeFlags="right"android:keyLabel="0"/></Row><Row><Key android:codes="45" android:keyEdgeFlags="left" android:horizontalGap="2dp"android:keyLabel="-"/><Key android:codes="47" android:horizontalGap="6dp" android:keyLabel="/"/><Key android:codes="58" android:horizontalGap="6dp" android:keyLabel=":"/><Key android:codes="59" android:horizontalGap="6dp" android:keyLabel=";"/><Key android:codes="40" android:horizontalGap="6dp" android:keyLabel="("/><Key android:codes="41" android:horizontalGap="6dp" android:keyLabel=")"/><Key android:codes="165" android:horizontalGap="6dp" android:keyLabel="¥"/><Key android:codes="64" android:horizontalGap="6dp" android:keyLabel="\@"/><Key android:codes="8220" android:horizontalGap="6dp" android:keyLabel="“"/><Key android:codes="8221" android:horizontalGap="6dp" android:keyEdgeFlags="right"android:keyLabel="”"/></Row><Row><Key android:codes="-7" android:keyEdgeFlags="left" android:horizontalGap="2dp"android:keyLabel="#+="android:keyWidth="11.000002%p"/><Key android:codes="12290" android:horizontalGap="14dp" android:keyLabel="。"android:keyWidth="8.33334444%p"/><Key android:codes="65292" android:keyLabel="," android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/><Key android:codes="65311" android:keyLabel="?" android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/><Key android:codes="65281" android:keyLabel="!" android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/><Key android:codes="46" android:keyLabel="." android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/><Key android:codes="96" android:keyLabel="`" android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/><Key android:codes="36" android:keyLabel="$" android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/><Key android:codes="-5"android:keyEdgeFlags="right"android:horizontalGap="14dp"android:keyIcon="@drawable/delete"android:keyWidth="11.000002%p"/></Row><Row android:rowEdgeFlags="bottom"><Key android:codes="-2" android:keyLabel="abc" android:keyEdgeFlags="left"android:horizontalGap="2dp"android:keyWidth="11.000002%p"/><Key android:codes="44" android:keyLabel="," android:horizontalGap="6dp"android:keyWidth="8.999998%p"/><Key android:codes="-11" android:keyLabel="←" android:horizontalGap="6dp"android:keyWidth="8.999998%p"/><Key android:codes="32" android:isRepeatable="true" android:horizontalGap="6dp"android:keyIcon="@drawable/space"android:keyWidth="20.999996%p"/><Key android:codes="-12" android:horizontalGap="6dp" android:keyLabel="→"android:keyWidth="8.999998%p"/><Key android:codes="46" android:keyLabel="." android:horizontalGap="6dp"android:keyWidth="8.999998%p"/><Key android:codes="-3" android:keyEdgeFlags="right" android:keyLabel="完成"android:horizontalGap="6dp"android:keyWidth="20.000002%p"/></Row>
</Keyboard>

英文键盘letter.xml

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"android:keyHeight="40dip"android:keyWidth="8.33334444%p"android:verticalGap="6dp"><Row><Key android:codes="113" android:horizontalGap="2dp"android:keyEdgeFlags="left" android:keyLabel="q"/><Key android:codes="119" android:horizontalGap="6dp" android:keyLabel="w"/><Key android:codes="101" android:horizontalGap="6dp" android:keyLabel="e"/><Key android:codes="114" android:horizontalGap="6dp" android:keyLabel="r"/><Key android:codes="116" android:horizontalGap="6dp" android:keyLabel="t"/><Key android:codes="121" android:horizontalGap="6dp" android:keyLabel="y"/><Key android:codes="117" android:horizontalGap="6dp" android:keyLabel="u"/><Key android:codes="105" android:horizontalGap="6dp" android:keyLabel="i"/><Key android:codes="111" android:horizontalGap="6dp" android:keyLabel="o"/><Key android:codes="112" android:horizontalGap="6dp" android:keyEdgeFlags="right"android:keyLabel="p"/></Row><Row><Key android:codes="97" android:horizontalGap="4.999995%p"android:keyEdgeFlags="left" android:keyLabel="a"/><Key android:codes="115" android:horizontalGap="6dp" android:keyLabel="s"/><Key android:codes="100" android:horizontalGap="6dp" android:keyLabel="d"/><Key android:codes="102" android:horizontalGap="6dp" android:keyLabel="f"/><Key android:codes="103" android:horizontalGap="6dp" android:keyLabel="g"/><Key android:codes="104" android:horizontalGap="6dp" android:keyLabel="h"/><Key android:codes="106" android:horizontalGap="6dp" android:keyLabel="j"/><Key android:codes="107" android:horizontalGap="6dp" android:keyLabel="k"/><Key android:codes="108" android:horizontalGap="6dp"android:keyEdgeFlags="right" android:keyLabel="l"/></Row><Row><Key android:codes="-1" android:keyEdgeFlags="left" android:horizontalGap="2dp"android:keyIcon="@drawable/shift" android:keyWidth="11.000002%p"/><Key android:codes="122" android:horizontalGap="14dp"android:keyLabel="z" android:keyWidth="8.33334444%p"/><Key android:codes="120" android:keyLabel="x"android:horizontalGap="6dp" android:keyWidth="8.33334444%p"/><Key android:codes="33" android:keyLabel="c"android:horizontalGap="6dp" android:keyWidth="8.33334444%p"/><Key android:codes="118" android:keyLabel="v"android:horizontalGap="6dp" android:keyWidth="8.33334444%p"/><Key android:codes="98" android:keyLabel="b"android:horizontalGap="6dp" android:keyWidth="8.33334444%p"/><Key android:codes="110" android:keyLabel="n"android:horizontalGap="6dp" android:keyWidth="8.33334444%p"/><Key android:codes="109" android:keyLabel="m"android:horizontalGap="6dp" android:keyWidth="8.33334444%p"/><Key android:codes="-5" android:keyEdgeFlags="right" android:horizontalGap="14dp"android:keyIcon="@drawable/delete" android:keyWidth="11.000002%p"/></Row><Row android:rowEdgeFlags="bottom"><Key android:codes="-2" android:keyLabel="123" android:keyEdgeFlags="left"android:horizontalGap="2dp" android:keyWidth="11.000002%p"/><Key android:codes="44" android:keyLabel=","android:horizontalGap="6dp" android:keyWidth="8.999998%p"/><Key android:codes="-11" android:keyLabel="←"android:horizontalGap="6dp" android:keyWidth="8.999998%p"/><Key android:codes="32" android:isRepeatable="true" android:horizontalGap="6dp"android:keyIcon="@drawable/space" android:keyWidth="20.999996%p"/><Key android:codes="-12" android:horizontalGap="6dp"android:keyLabel="→" android:keyWidth="8.999998%p"/><Key android:codes="46" android:keyLabel="."android:horizontalGap="6dp" android:keyWidth="8.999998%p"/><Key android:codes="-3" android:keyEdgeFlags="right" android:keyLabel="完成"android:horizontalGap="6dp" android:keyWidth="20.000002%p"/></Row>
</Keyboard>

符号键盘symbol.xml

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"android:keyHeight="40dip"android:keyWidth="8.33334444%p"android:verticalGap="6dp"><Row><Key android:codes="12304" android:horizontalGap="2dp" android:keyEdgeFlags="left"android:keyLabel="【"/><Key android:codes="12305" android:horizontalGap="6dp" android:keyLabel="】"/><Key android:codes="123" android:horizontalGap="6dp" android:keyLabel="{"/><Key android:codes="125" android:horizontalGap="6dp" android:keyLabel="}"/><Key android:codes="35" android:horizontalGap="6dp" android:keyLabel="#"/><Key android:codes="37" android:horizontalGap="6dp" android:keyLabel="%"/><Key android:codes="94" android:horizontalGap="6dp" android:keyLabel="^"/><Key android:codes="42" android:horizontalGap="6dp" android:keyLabel="*"/><Key android:codes="43" android:horizontalGap="6dp" android:keyLabel="+"/><Key android:codes="61" android:horizontalGap="6dp" android:keyEdgeFlags="right"android:keyLabel="="/></Row><Row><Key android:codes="95" android:keyEdgeFlags="left" android:horizontalGap="2dp"android:keyLabel="_"/><Key android:codes="-9" android:horizontalGap="6dp" android:keyLabel="——"/><Key android:codes="92" android:horizontalGap="6dp" android:keyLabel="\"/><Key android:codes="124" android:horizontalGap="6dp" android:keyLabel="|"/><Key android:codes="126" android:horizontalGap="6dp" android:keyLabel="~"/><Key android:codes="12298" android:horizontalGap="6dp" android:keyLabel="《"/><Key android:codes="12299" android:horizontalGap="6dp" android:keyLabel="》"/><Key android:codes="36" android:horizontalGap="6dp" android:keyLabel="$"/><Key android:codes="38" android:horizontalGap="6dp" android:keyLabel="&amp;"/><Key android:codes="46" android:horizontalGap="6dp" android:keyEdgeFlags="right"android:keyLabel="·"/></Row><Row><Key android:codes="-7" android:keyEdgeFlags="left" android:horizontalGap="2dp"android:keyLabel="123"android:keyWidth="11.000002%p"/><Key android:codes="-8" android:horizontalGap="14dp" android:keyLabel="..."android:keyWidth="8.33334444%p"/><Key android:codes="44" android:keyLabel="," android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/><Key android:codes="-10" android:keyLabel="^_^" android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/><Key android:codes="63" android:keyLabel="\?" android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/><Key android:codes="33" android:keyLabel="!" android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/><Key android:codes="-13" android:keyLabel="^o^" android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/><Key android:codes="-14" android:keyLabel="&gt;_&lt;" android:horizontalGap="6dp"android:keyWidth="8.33334444%p"/><Key android:codes="-5" android:keyEdgeFlags="right" android:horizontalGap="14dp"android:keyIcon="@drawable/delete"android:keyWidth="11.000002%p"/></Row><Row android:rowEdgeFlags="bottom"><Key android:codes="-2" android:keyLabel="abc" android:keyEdgeFlags="left"android:horizontalGap="2dp"android:keyWidth="11.000002%p"/><Key android:codes="44" android:keyLabel="," android:horizontalGap="6dp"android:keyWidth="8.999998%p"/><Key android:codes="-11" android:keyLabel="←" android:horizontalGap="6dp"android:keyWidth="8.999998%p"/><Key android:codes="32" android:isRepeatable="true" android:horizontalGap="6dp"android:keyIcon="@drawable/space"android:keyWidth="20.999996%p"/><Key android:codes="-12" android:horizontalGap="6dp" android:keyLabel="→"android:keyWidth="8.999998%p"/><Key android:codes="46" android:keyLabel="." android:horizontalGap="6dp"android:keyWidth="8.999998%p"/><Key android:codes="-3" android:keyEdgeFlags="right" android:keyLabel="完成"android:horizontalGap="6dp"android:keyWidth="20.000002%p"/></Row>
</Keyboard>

二、处理按键

OnKeyboardActionListener

在KeyboardView类里面有专门处理Keyboard的监听类OnKeyboardActionListener

public class KeyboardView extends View implements View.OnClickListener {....../*** Listener for virtual keyboard events.*/public interface OnKeyboardActionListener {/*** 当用户按下一个键时调用。 这是在调用onKey之前。* 对于重复的键,此键仅调用一次。* @param primaryCode被按下的键的unicode。如果触摸不在有效范围内,值将为零。*/void onPress(int primaryCode);/*** 当用户释放键时调用。 这是在调用onKey之后。* 对于重复的键,此键仅调用一次。* @param primaryCode被释放的键的unicode*/void onRelease(int primaryCode);/*** 发送一个按键到监听器* @ param primaryCode这是按下的键* @ param keyCodes所有可能的替代键的代码,*/void onKey(int primaryCode, int[] keyCodes);/*** 向侦听器发送一系列字符。* @param text 要显示的字符序列。*/void onText(CharSequence text);/*** 当用户从右向左快速移动手指时调用。*/void swipeLeft();/*** 当用户从左向右快速移动手指时调用。*/void swipeRight();/*** 当用户从上到下快速移动手指时调用。*/void swipeDown();/*** 当用户快速将手指从下向上移动时调用。*/void swipeUp();}......}

我们自己实现OnKeyboardActionListener接口,即可处理对键盘的操作。主要实现了onKey方法。在这个方法里通过传入的primaryCode进行相应的操作,如

  • 如果code是 KEYCODE_DELETE 使用Editable.delete方法删除光标左边的字符
  • 如果code是 KEYCODE_SHIFT boolean类型的isUpper的值会被改变,并且使用 setShifted() 方法改变键盘的换档状态(shift state),当状态改变时,键盘需要重绘,所以的键的label被更新了,invalidateAllKeys() 方法用来重绘所有的键
  • 对于其他所有的codes,只是简单的将unicode转化为字符并且使用Editable.insert()方法插入到输入框里即可,如果这个code代表了字母表里的一个字母,并且isUpper变量为true,那么还需要将字母转化为大写
  • 若code为负数的话,只需要根据自己的定义,进行相应的处理即可,例如-8代表省略号,-10代表笑脸等。
public class KeyboardUtil {...private static final int SYMBOL_CODE = -7;//符号键盘private static final int ELLIPSES_CODE = -8;//省略号private static final int CHINESE_HORIZONTAL_LINE_CODE = -9;//中文横线private static final int SMILING_FACE_CODE = -10;//笑脸private static final int LEFT_CODE = -11;//中文横线private static final int RIGHT_CODE = -12;//中文横线private static final int HEE_CODE = -13;//哈哈private static final int AWKWARD_CODE = -14;//尴尬OnKeyboardActionListener onKeyboardActionListener = new OnKeyboardActionListener() {@Overridepublic void swipeUp() {}@Overridepublic void swipeRight() {}@Overridepublic void swipeLeft() {}@Overridepublic void swipeDown() {}@Overridepublic void onText(CharSequence text) {}@Overridepublic void onRelease(int primaryCode) {}@Overridepublic void onPress(int primaryCode) {}@Overridepublic void onKey(int primaryCode, int[] keyCodes) {Editable editable = ed.getText();int start = ed.getSelectionStart();if (primaryCode == Keyboard.KEYCODE_CANCEL) {// 完成hideKeyboard();} else if (primaryCode == Keyboard.KEYCODE_DELETE) {// 回退if (editable != null && editable.length() > 0) {if (start > 0) {editable.delete(start - 1, start);}}} else if (primaryCode == Keyboard.KEYCODE_SHIFT) {// 大小写切换isUpper = !isUpper;k1.setShifted(isUpper);keyboardView.invalidateAllKeys();} else if (primaryCode == SYMBOL_CODE) {// 符号键盘if (isSymbol) {isSymbol = false;keyboardView.setKeyboard(k2);} else {isSymbol = true;keyboardView.setKeyboard(k3);}} else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {// 数字键盘切换if (isNum) {isNum = false;keyboardView.setKeyboard(k1);} else {isNum = true;keyboardView.setKeyboard(k2);}} else if (primaryCode == LEFT_CODE) { //向左if (start > 0) {ed.setSelection(start - 1);}} else if (primaryCode == RIGHT_CODE) { // 向右if (start < ed.length()) {ed.setSelection(start + 1);}} else if (primaryCode == ELLIPSES_CODE) { //省略号editable.insert(start, "...");} else if (primaryCode == CHINESE_HORIZONTAL_LINE_CODE) {editable.insert(start, "——");} else if (primaryCode == SMILING_FACE_CODE) {editable.insert(start, "^_^");} else if (primaryCode == HEE_CODE) {editable.insert(start, "^o^");} else if (primaryCode == AWKWARD_CODE) {editable.insert(start, ">_<");} else {String str = Character.toString((char) primaryCode);if (isWord(str)) {if (isUpper) {str = str.toUpperCase();} else {str = str.toLowerCase();}}editable.insert(start, str);}}};...}

KeyboardUtil

这里自定义了一个键盘的工具类KeyboardUtil

import android.app.Activity;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
import android.text.Editable;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.RelativeLayout;public class KeyboardUtil {private KeyboardView keyboardView;private Keyboard k1;// 字母键盘private Keyboard k2;// 数字键盘private Keyboard k3;// 符号键盘private boolean isNum = false;// 是否数据键盘private boolean isUpper = false;// 是否大写private boolean isSymbol = false;// 是否符号private static final int SYMBOL_CODE = -7;//符号键盘private static final int ELLIPSES_CODE = -8;//省略号private static final int CHINESE_HORIZONTAL_LINE_CODE = -9;//中文横线private static final int SMILING_FACE_CODE = -10;//笑脸private static final int LEFT_CODE = -11;//中文横线private static final int RIGHT_CODE = -12;//中文横线private static final int HEE_CODE = -13;//哈哈private static final int AWKWARD_CODE = -14;//尴尬private ViewGroup rootView;private EditText ed;private KeyboardUtil(Activity activity, EditText edit) {this.ed = edit;k1 = new Keyboard(activity, R.xml.letter);k2 = new Keyboard(activity, R.xml.number);k3 = new Keyboard(activity, R.xml.symbol);keyboardView = new KeyboardView(activity, null);keyboardView.setKeyboard(k1);keyboardView.setEnabled(true);keyboardView.setPreviewEnabled(false);keyboardView.setOnKeyboardActionListener(onKeyboardActionListener);rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);}OnKeyboardActionListener onKeyboardActionListener = new OnKeyboardActionListener() {@Overridepublic void swipeUp() {}@Overridepublic void swipeRight() {}@Overridepublic void swipeLeft() {}@Overridepublic void swipeDown() {}@Overridepublic void onText(CharSequence text) {}@Overridepublic void onRelease(int primaryCode) {}@Overridepublic void onPress(int primaryCode) {}@Overridepublic void onKey(int primaryCode, int[] keyCodes) {Editable editable = ed.getText();int start = ed.getSelectionStart();if (primaryCode == Keyboard.KEYCODE_CANCEL) {// 完成hideKeyboard();} else if (primaryCode == Keyboard.KEYCODE_DELETE) {// 回退if (editable != null && editable.length() > 0) {if (start > 0) {editable.delete(start - 1, start);}}} else if (primaryCode == Keyboard.KEYCODE_SHIFT) {// 大小写切换isUpper = !isUpper;k1.setShifted(isUpper);keyboardView.invalidateAllKeys();} else if (primaryCode == SYMBOL_CODE) {// 符号键盘if (isSymbol) {isSymbol = false;keyboardView.setKeyboard(k2);} else {isSymbol = true;keyboardView.setKeyboard(k3);}} else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {// 数字键盘切换if (isNum) {isNum = false;keyboardView.setKeyboard(k1);} else {isNum = true;keyboardView.setKeyboard(k2);}} else if (primaryCode == LEFT_CODE) { //向左if (start > 0) {ed.setSelection(start - 1);}} else if (primaryCode == RIGHT_CODE) { // 向右if (start < ed.length()) {ed.setSelection(start + 1);}} else if (primaryCode == ELLIPSES_CODE) { //省略号editable.insert(start, "...");} else if (primaryCode == CHINESE_HORIZONTAL_LINE_CODE) {editable.insert(start, "——");} else if (primaryCode == SMILING_FACE_CODE) {editable.insert(start, "^_^");} else if (primaryCode == HEE_CODE) {editable.insert(start, "^o^");} else if (primaryCode == AWKWARD_CODE) {editable.insert(start, ">_<");} else {String str = Character.toString((char) primaryCode);if (isWord(str)) {if (isUpper) {str = str.toUpperCase();} else {str = str.toLowerCase();}}editable.insert(start, str);}}};private boolean isShow = false;public void showKeyboard() {if (!isShow) {RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);layoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, RelativeLayout.TRUE);rootView.addView(keyboardView, layoutParams);isShow = true;}}private void hideKeyboard() {if (rootView != null && keyboardView != null && isShow) {isShow = false;rootView.removeView(keyboardView);}mInstance = null;}private boolean isWord(String str) {return str.matches("[a-zA-Z]");}private static KeyboardUtil mInstance;public static KeyboardUtil shared(Activity activity, EditText edit) {if (mInstance == null) {mInstance = new KeyboardUtil(activity, edit);}mInstance.ed = edit;return mInstance;}}

三、MainActivity中的使用

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.InputType;
import android.view.View;
import android.widget.EditText;public class MainActivity extends AppCompatActivity {private EditText edit;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);edit = (EditText) this.findViewById(R.id.edit);edit.setInputType(InputType.TYPE_NULL);edit.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {KeyboardUtil.shared(MainActivity.this,edit).showKeyboard();}});}
}

四、实现效果

好了,关于Android的自定义键盘就说到这里,这个只是自定义键盘最简单的使用方式。当然,就算是最简单的方式,想要完整的实现下来也是踩了不少坑的。有时间了在继续踩。这里贴上源码下载

Android自定义键盘的简单实现相关推荐

  1. android自定义数字键盘和字母键盘,Android自定义键盘的实现(数字键盘和字母键盘)...

    Android自定义键盘的实现(数字键盘和字母键盘) 发布时间:2020-09-04 03:18:48 来源:脚本之家 阅读:100 作者:浪淘沙xud 在项目中,产品对于输入方式会有特殊的要求,需要 ...

  2. 关于android自定义键盘

    因为百度里面搜索android自定义键盘内容很少,所以就将我在github上找到的好点的键盘(keyboard)源码分享出来: (因为我在源码上修改了,所以图片是我源码修改之后的图片,大家可以到git ...

  3. Android 自定义键盘 随机键盘

    之前上传的另外一个自定义键盘,并没有实现键盘弹出的时候,布局向上自动调整.(网络上所有的自定义键盘都没有添加自适应的功能,而且布局没这么好看,上一个例子资源链接为:http://download.cs ...

  4. android 键盘开发demo,Android自定义键盘之中文键盘demo

    [实例简介] Android自定义键盘之中文键盘demo,演示了汉字键盘的实现方法.更详细描述见相关博客. [实例截图] [核心代码] keydemo └── keydemo ├── AndroidM ...

  5. android自定义键盘遮挡,Android软键盘遮挡的四种完美解决方案

    一.问题概述 在编辑框输入内容时会弹出软键盘,而手机屏幕区域有限往往会遮住输入界面,我们先看一下问题效果图: 输入用户名和密码时,系统会弹出键盘,造成系统键盘会挡住文本框的问题,如图所示: 输入密码时 ...

  6. Android自定义键盘(KeyboardView)

    目录 1.场景: 2.想法: 3.开始实现: <一> 在res包下创建xml目录,Keyboard标签来定义键盘布局: <二>创建IKeyboardView类并继承Keyboa ...

  7. appium android数字字母切换键,Android自定义键盘:数字键盘和字母键盘

    在项目中,产品对于输入方式会有特殊的要求,需要对输入方式增加特定的限制,这就需要采用自定义键盘.本文主要讲述数字键盘和字母键盘的自定义实现. 自定义键盘的实现步骤如下: 自定义CustomKeyboa ...

  8. android自定义键盘 自定义身份证键盘

    android 系统键盘支持的点已经比较丰富了, 但是有时候某一些需求还不能满足我们的需求.最近公司应用到了实名认证相关的功能,这部分需要一个身份证的EditText, 自然也需要一个身份证的键盘,奈 ...

  9. android自定义键盘开源,Android自定义软键盘的设计与实现代码

    偶然间发现了Android.inputmethodservice.Keyboard类,即android可以自定义键盘类,做了一个简单例子供大家参考. 效果如下: 先看界面布局文件 android:la ...

最新文章

  1. python生成试卷制卷系统_Python 读写文件 小应用:生成随机的测验试卷文件
  2. R语言自定义多分类混淆矩阵可视化函数(mutlti class confusion matrix)、R语言多分类混淆矩阵可视化
  3. Java Code Geeks和Packt提供的Hadoop书籍赠品
  4. WinForm始终置顶并获取焦点
  5. Windows中木马之后桌面被篡改的恢复方法
  6. python学习6 web开发
  7. html5触摸界面设计与开发_原生APP的开发步骤主要分为哪些?
  8. 百度,在模仿和创新中成长
  9. webpack配置报错WARNING in DefinePlugin Conflicting values for ‘process.env.NODE_ENV‘
  10. linux嵌入式面试300问,经典嵌入式Linux面试题3问
  11. 计算机硬件工程师需要学哪些,硬件工程师需要学习哪些知识 上EDA365电子论坛...
  12. Bartender模板三种动态图片设置方法(仅供参考)
  13. 在一维的世界里寻找迭代次数的影子
  14. JS实现星星评分系统
  15. 网页怎么算切屏_十种切屏抓取方法(图形)
  16. [linux] Linux网络之TCP协议详解
  17. 玩转JDBC打造数据库操作万能工具类JDBCUtil,加入了高效的数据库连接池,利用了参数绑定有效防止SQL注入
  18. 国密双证书签发及国密数据信封解析
  19. 11_Flask之Session 设置session有效期 获取session 删除session
  20. python的ppt报告_Python学习报告.ppt

热门文章

  1. 机器学习(周志华) 第九章聚类
  2. 嵌入式开发中,嵌入式硬件和软件有什么区别?
  3. UI自动化测试(一)
  4. 【观察】数字中国的新机遇,神州数码的新角色
  5. 4.18耶稣受难日黄金持续跌势(附黄金原油操作建议)
  6. oracle连接另外一个oracle,Oracle 连接 另一个Oracle数据库 服务器连接
  7. eclipse工具的使用
  8. Auto.js修改QQ语音+破解闪照
  9. 多维联合正态分布代码matlab(以二维为例)
  10. MinIO 文件服务器简单搭建