在一些特别的情况下我们需要去自定义键盘
例如: 银行app的密码输入之类的
笨方法就是直接使用布局写我们的自定义软键盘
但这样写的话我们的代码量就很多
Android官方提供了KeyboardView和Keyboard两个类
我们可以用这两个类去实现自己的软键盘
Demo 已上传 GitHub
https://github.com/pengchengfuGit/DIYKeyboard.git
1.主界面的布局与代码
这是我们主界面的xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@android:color/darker_gray"
android:layout_height="match_parent">
<EditText
android:id="@+id/et"
android:layout_width="match_parent"
android:layout_height="50dp" />
<android.inputmethodservice.KeyboardView
android:id="@+id/kv_keyboard"
android:background="@android:color/white"
android:layout_width="match_parent"
android:keyBackground="@android:color/holo_purple"
android:keyTextColor="#333333"
android:focusable="true"
android:focusableInTouchMode="true"
android:paddingTop="1dp"
android:shadowColor="#FFFFFF"
android:shadowRadius="0.0"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
RelativeLayout>
主界面的Activity 这里写了个KeyBoardUtil来初始的我们自定义软键盘
public class MainActivity extends Activity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_payment);
final KeyboardView keyboard = (KeyboardView) findViewById(R.id.kv_keyboard);
final EditText editText = (EditText) findViewById(R.id.et);
//在我们点EditText的时候弹出我们的软键盘
editText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(editText.hasFocus()){
//用来初始化我们的软键盘
new KeyBoardUtil(keyboard,editText).showKeyboard();
}
return false;
}
});
}
}
2.KeyBoard的键盘按钮配置
这是配置我们自定义软键盘的按钮的
软键盘显示的按钮通过xml来配置
这个xml的文件放个res/xml/… 目录
没有xml文件夹的 手动创建一个
** keyWidth , keyHeight 可以采用百分比的写法
** android:keyWidth=”25%p”
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:keyHeight="50dp"
android:keyWidth="25%p"
android:horizontalGap="1px"
android:verticalGap="1px">
<Row>
<Key
android:keyIcon="@color/white"
android:codes="49"
android:keyLabel="1" />
<Key
android:codes="50"
android:keyLabel="2" />
<Key
android:codes="51"
android:keyLabel="3" />
<Key
android:codes="-5"
android:keyLabel="删除" />
Row>
<Row>
<Key
android:codes="52"
android:keyLabel="4" />
<Key
android:codes="53"
android:keyLabel="5" />
<Key
android:codes="54"
android:keyLabel="6" />
<Key
android:codes="-4"
android:keyHeight="150dp"
android:keyLabel="完成"/>
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="46"
android:keyLabel="." />
<Key
android:keyWidth="50.2%p"
android:codes="48"
android:keyLabel="0" />
Row>
Keyboard>
这里解释下xml里的几个参数
属性 | 说明 |
---|---|
keyLabel | 按键显示的内容 |
keyIcon | 按键显示的图标内容 |
keyWidth | 按键的宽度 |
keyHeight | 按键的高度 |
horizontalGap | 代表按键前的间隙水平方向上的 |
isSticky | 按键是否是sticky的,就像shift 键 具有两种状态 |
isModifier | 按键是不是功能键 |
keyOutputText | 指定按键输出的内容是字符串 |
isRepeatable | 按键是可重复的,如果长按键可以触发重复按键事件则为true,else为false |
keyEdgeFlags | 指定按键的对齐指令,取值为left或者right |
一些特殊的按键的codes建议采用系统已经定义好的值
常见的像删除 确认 取消
public static final int EDGE_LEFT = 1;
public static final int EDGE_RIGHT = 2;
public static final int EDGE_TOP = 4;
public static final int EDGE_BOTTOM = 8;
public static final int KEYCODE_SHIFT = -1;
public static final int KEYCODE_MODE_CHANGE = -2;
public static final int KEYCODE_CANCEL = -3;
public static final int KEYCODE_DONE = -4;
public static final int KEYCODE_DELETE = -5
public static final int KEYCODE_ALT = -6;
3.配置软键盘
配置软键盘中的实现 我把它放在了KeyBoardUtil
import android.content.Context;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.text.Editable;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
public class KeyBoardUtil {
private KeyboardView keyboardView;
private EditText editText;
private Keyboard k1;// 自定义键盘
public KeyBoardUtil(KeyboardView keyboardView, EditText editText) {
//setInputType为InputType.TYPE_NULL 不然会弹出系统键盘
editText.setInputType(InputType.TYPE_NULL);
k1 = new Keyboard(editText.getContext(), R.xml.key);
this.keyboardView = keyboardView;
this.editText = editText;
this.keyboardView.setOnKeyboardActionListener(listener);
this.keyboardView.setKeyboard(k1);
this.keyboardView.setEnabled(true);
this.keyboardView.setPreviewEnabled(false);
}
private KeyboardView.OnKeyboardActionListener listener = new KeyboardView.OnKeyboardActionListener() {
@Override
public void swipeUp() {
}
@Override
public void swipeRight() {
}
@Override
public void swipeLeft() {
}
@Override
public void swipeDown() {
}
@Override
public void onText(CharSequence text) {
}
@Override
public void onRelease(int primaryCode) {
}
@Override
public void onPress(int primaryCode) {
}
@Override
public void onKey(int primaryCode, int[] keyCodes) {
Editable editable = editText.getText();
int start = editText.getSelectionStart();
switch (primaryCode) {
case Keyboard.KEYCODE_DELETE:
if (editable != null && editable.length() > 0) {
if (start > 0) {
editable.delete(start - 1, start);
}
}
break;
case Keyboard.KEYCODE_CANCEL:
keyboardView.setVisibility(View.GONE);
break;
default:
editable.insert(start, Character.toString((char) primaryCode));
break;
}
}
};
// Activity中获取焦点时调用,显示出键盘
public void showKeyboard() {
int visibility = keyboardView.getVisibility();
if (visibility == View.GONE || visibility == View.INVISIBLE) {
keyboardView.setVisibility(View.VISIBLE);
}
}
// 隐藏键盘
public void hideKeyboard() {
int visibility = keyboardView.getVisibility();
if (visibility == View.VISIBLE|| visibility == View.INVISIBLE) {
keyboardView.setVisibility(View.GONE);
}
}
}
这样我们的软键盘就实现了
自定义键盘背景色
有时候我们给不同的按键, 设置不同的背景色
像下图的确定按钮
这时用原生的KeyboardView和Keyboard是实现不了的
原生的只能所有的按钮都是统一的样式
字体颜色 , 按键背景色
那如何实现我们不同按键不同的字体颜色,不同的背景色呢
这时我们可以去重写KeyboardView的OnDraw()方法
public class DIYKeyboardView extends KeyboardView {
public DIYKeyboardView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Keyboard keyboard = getKeyboard();
if (keyboard == null) return;
List.Key> keys = keyboard.getKeys();
if (keys != null && keys.size() > 0) {
Paint paint = new Paint();
paint.setTextAlign(Paint.Align.CENTER);
Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
paint.setTypeface(font);
paint.setAntiAlias(true);
for (Keyboard.Key key : keys) {
if (key.codes[0] == -3) {
Drawable dr = getContext().getResources().getDrawable(R.drawable.keyboard_blue);
dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
dr.draw(canvas);
} else {
Drawable dr = getContext().getResources().getDrawable(R.drawable.keyboard_white);
dr.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
dr.draw(canvas);
}
if (key.label != null) {
if (key.codes[0] == -4 ||
key.codes[0] == -5) {
paint.setTextSize(17 * 2);
} else {
paint.setTextSize(20 * 2);
}
if (key.codes[0] == -4) {
paint.setColor(getContext().getResources().getColor(R.color.white));
} else {
paint.setColor(getContext().getResources().getColor(R.color.blue_03A9F4));
}
Rect rect = new Rect(key.x, key.y, key.x + key.width, key.y + key.height);
Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
int baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2;
// 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(key.label.toString(), rect.centerX(), baseline, paint);
}
}
}
}
}