前言
也是最近想写个demo玩玩,不知道写哪个方面的好,就随便写了一个自定义的键盘,比较简单,但是做了封装,支持jitpack库依赖(这也是我第一次开源自己的库,比较水的一个开源项目,仅供学习使用)。
概述
主要完成了以下功能:
1.自定义数字键盘
2.切换到随机数字键盘
3.自定义确定和删除等键(向外抛出接口,感觉设计的挺好)
下面先看下运行效果吧
效果图片使用方法
1.在项目build.gradle文件中添加jitpack,添加jitpcak就够了。
allprojects {
repositories {
jcenter()
maven { url 'https://jitpack.io' }
}
}
2.在module 的build.gradle文件添加依赖
compile 'com.github.Simon986793021:NumberKeyboard:v1.0'
3.在布局文件中添加布局
<com.wind.keyboard.OfoKeyboardView
android:id="@+id/keyboard_view"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:paddingTop="0dp"
android:focusableInTouchMode="true"
android:keyBackground="@drawable/bg_keyboardview"
android:keyPreviewOffset="0dp"
android:keyTextColor="#000"
android:shadowColor="#fff"
android:shadowRadius="0.0"
android:layout_alignParentBottom="true"
/>
4.在MainActivity调用。
editText= (EditText) findViewById(R.id.et_numberplate);
changebutton= (Button) findViewById(R.id.bt_change_keyboard);
final OfoKeyboard keyboard = new OfoKeyboard(MainActivity.this);//获取到keyboard对象
changebutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
keyboard.attachTo(editText,true);//eiditext绑定keyboard,true表示随机数字
}
});
editText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
keyboard.attachTo(editText,false);//eiditext绑定keyboard,false表示普通数字键盘
}
});
/*
确定按钮
*/
keyboard.setOnOkClick(new OfoKeyboard.OnOkClick() {
@Override
public void onOkClick() {
Log.i(">>>>>>","点击了确定");
Toast.makeText(MainActivity.this,editText.getText().toString(),Toast.LENGTH_SHORT).show();
}
});
//隐藏键盘按钮
keyboard.setOnCancelClick(new OfoKeyboard.OnCancelClcik() {
@Override
public void onCancelClick() {
Toast.makeText(MainActivity.this,"隐藏键盘",Toast.LENGTH_SHORT).show();
}
});
只需要这些简单的代码就能够实现一个自己定义的键盘了。
实现过程
1.新建一个keyboard布局
在看这个代码之前需要了解keyboard的属性:
不清楚属性,怎么画页面,不懂的请移步这篇博客
在 res 新建一个xml文件,然后在xml新建一个keyboard.xml
里面代码如下
<?xml version="1.0" encoding="utf-8"?>
<Keyboard
xmlns:android="http://schemas.android.com/apk/res/android"
android:keyHeight="9%p"
android:keyWidth="25%p"
android:horizontalGap="0dp">
<Row>
<Key
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:keyHeight="18%p"
android:keyEdgeFlags="right"
android:isRepeatable="true"
android:keyIcon="@drawable/icon_delete_32dp"/>
</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"/>
<Key
android:codes="-4"
android:keyLabel="确定"
android:keyEdgeFlags="right"
android:keyHeight="18%p"/>
</Row>
<Row>
<Key
android:codes="46"
android:keyLabel="."/>
<Key
android:codes="48"
android:keyLabel="0"/>
<Key
android:codes="-3"
android:keyIcon="@drawable/icon_hide_keyboard"/>
</Row>
</Keyboard>
这个布局就是自己自定义键盘的布局实现,有了布局,显然是不够的。
2.自定义KeyboardView
package com.wind.keyboard;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.util.AttributeSet;
import android.util.Log;
import java.lang.reflect.Field;
import java.util.List;
/**
* Created by zhangcong on 2017/8/24.
*/
public class OfoKeyboardView extends KeyboardView {
private Context context;
private Keyboard keyboard;
public OfoKeyboardView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context=context;
Log.i(">>>>>","构造函数被调用了");
}
/**
* 重新画一些按键
*/
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
keyboard = this.getKeyboard();
List<Keyboard.Key> keys = null;
if (keyboard != null) {
keys = keyboard.getKeys();
}
if (keys != null) {
for (Keyboard.Key key : keys) {
// 数字键盘的处理
if (key.codes[0] == -4) {
drawKeyBackground(R.drawable.bg_keyboardview_yes, canvas, key);
drawText(canvas, key);
}
}
}
}
private void drawKeyBackground(int drawableId, Canvas canvas, Keyboard.Key key) {
Drawable npd = context.getResources().getDrawable(
drawableId);
int[] drawableState = key.getCurrentDrawableState();
if (key.codes[0] != 0) {
npd.setState(drawableState);
}
npd.setBounds(key.x, key.y, key.x + key.width, key.y
+ key.height);
npd.draw(canvas);
}
private void drawText(Canvas canvas, Keyboard.Key key) {
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);
}
}
}
3.KeyBoard的对象的创建:
package com.wind.keyboard;
import android.app.Activity;
import android.content.Context;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.os.Build;
import android.text.Editable;
import android.text.InputType;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
/**
* Created by zhangcong on 2017/8/28.
*/
public class OfoKeyboard {
private Activity activity;
private Keyboard keyboard;
private OfoKeyboardView keyboardView;
private EditText editText;
private boolean isRandom=false;
public OfoKeyboard (Activity activity )
{
this.activity=activity;
keyboardView= (OfoKeyboardView) activity.findViewById(R.id.keyboard_view);
}
//点击事件触发
public void attachTo(EditText editText,boolean isRandom){
/*
切换键盘需要重新new Keyboard对象,否则键盘不会改变,keyboardView放到构造函数里面,避免每次点击重新new 对象,提高性能
*/
keyboard=new Keyboard(activity,R.xml.keyboard);
this.isRandom=isRandom;
Log.i(">>>>>","attachTo");
this.editText=editText;
hideSystemSofeKeyboard(activity,editText);
showSoftKeyboard();
}
private void showSoftKeyboard() {
if (keyboard == null) {
keyboard = new Keyboard(activity, R.xml.keyboard);
}
if(keyboardView==null)
{
keyboardView= (OfoKeyboardView) activity.findViewById(R.id.keyboard_view);
}
if (isRandom)
{
randomKeyboardNumber();
}
else {
keyboardView.setKeyboard(keyboard);
}
keyboardView.setEnabled(true);
keyboardView.setPreviewEnabled(false);
keyboardView.setVisibility(View.VISIBLE);
keyboardView.setOnKeyboardActionListener(listener);
}
private KeyboardView.OnKeyboardActionListener listener=new KeyboardView.OnKeyboardActionListener() {
@Override
public void onPress(int primaryCode) {
}
@Override
public void onRelease(int primaryCode) {
}
@Override
public void onKey(int primaryCode, int[] keyCodes) {
Editable editable=editText.getText();
int start =editText.getSelectionStart();
if (primaryCode==Keyboard.KEYCODE_DELETE)//key codes 为-5
{
if (editable!=null&&editable.length()>0)
{
if (start>0)
{
editable.delete(start-1,start);
}
}
}
else if (primaryCode==Keyboard.KEYCODE_CANCEL)
{
hideKeyBoard();
if (mCancelClick!=null)
{
mCancelClick.onCancelClick();
}
}
else if (primaryCode==Keyboard.KEYCODE_DONE)
{
hideKeyBoard();
if (mOkClick!=null)
{
mOkClick.onOkClick();
}
}
else {
Log.i(">>>>>>",primaryCode+"1");
Log.i(">>>>>>",(char) primaryCode+"2");
editable.insert(start,Character.toString((char) primaryCode));
}
}
@Override
public void onText(CharSequence text) {
}
@Override
public void swipeLeft() {
}
@Override
public void swipeRight() {
}
@Override
public void swipeDown() {
}
@Override
public void swipeUp() {
}
};
public interface OnOkClick {
void onOkClick();
}
public interface OnCancelClcik{
void onCancelClick();
}
public OnOkClick mOkClick;
public OnCancelClcik mCancelClick;
public void setOnOkClick(OnOkClick onOkClick)
{
this.mOkClick=onOkClick;
}
public void setOnCancelClick (OnCancelClcik onCancelClick)
{
this.mCancelClick=onCancelClick;
}
private void hideKeyBoard() {
int visibility=keyboardView.getVisibility();
if (visibility==KeyboardView.VISIBLE)
{
keyboardView.setVisibility(KeyboardView.GONE);
}
}
private boolean isNumber(String str) {
String wordstr = "0123456789";
return wordstr.contains(str);
}
private void randomKeyboardNumber() {
List<Keyboard.Key> keyList = keyboard.getKeys();
// 查找出0-9的数字键
List<Keyboard.Key> newkeyList = new ArrayList<Keyboard.Key>();
for (int i = 0; i < keyList.size(); i++) {
if (keyList.get(i).label != null
&& isNumber(keyList.get(i).label.toString())) {
newkeyList.add(keyList.get(i));
}
}
// 数组长度
int count = newkeyList.size();
// 结果集
List<KeyModel> resultList = new ArrayList<KeyModel>();
// 用一个LinkedList作为中介
LinkedList<KeyModel> temp = new LinkedList<KeyModel>();
// 初始化temp
for (int i = 0; i < count; i++) {
temp.add(new KeyModel(48 + i, i + ""));
}
// 取数
Random rand = new Random();
for (int i = 0; i < count; i++) {
int num = rand.nextInt(count - i);
resultList.add(new KeyModel(temp.get(num).getCode(),
temp.get(num).getLable()));
temp.remove(num);
}
for (int i = 0; i < newkeyList.size(); i++) {
newkeyList.get(i).label = resultList.get(i).getLable();
newkeyList.get(i).codes[0] = resultList.get(i)
.getCode();
}
// hideKeyBoard();
keyboardView.setKeyboard(keyboard);
}
/**
* 隐藏系统键盘
*
* @param editText
*/
public static void hideSystemSofeKeyboard(Context context, EditText editText) {
Log.i(">>>>>","hide");
int sdkInt = Build.VERSION.SDK_INT;
if (sdkInt >= 11) {
try {
Class<EditText> cls = EditText.class;
Method setShowSoftInputOnFocus;
setShowSoftInputOnFocus = cls.getMethod("setShowSoftInputOnFocus", boolean.class);
setShowSoftInputOnFocus.setAccessible(true);
setShowSoftInputOnFocus.invoke(editText, false);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
} else {
editText.setInputType(InputType.TYPE_NULL);
}
// 如果软键盘已经显示,则隐藏
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
}
}
到这里,自定义键盘就全部完成了。
总结
自定义键盘就是通过自定义一个键盘布局,然后通过keyboardView来展示出来。个人感觉没什么需要掌握的,不过可以学习一下代码的封装技巧。
自定义键盘是比较简单的,但是个人感觉可以看看里面的一些代码封装的技巧,如果你觉得对你有帮助,麻烦来个star吧。
网友评论