登录 立即注册
安币:

安卓巴士 - 安卓开发 - Android开发 - 安卓 - 移动互联网门户

楼主: 莫应有道

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

[复制链接]

497

主题

1164

帖子

1049

安币

手工艺人

发表于 2017-10-25 15:39:37 | 显示全部楼层 |阅读模式

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

        项目地址:https://github.com/xudjx/djkeyboard

        键盘效果:

        

        自定义键盘的实现步骤如下:



  

    1. 自定义CustomKeyboard, 继承自系统Keyboard,实现KeyboardView.OnKeyboardActionListener相关接口,以处理用户的点击回调;


  

    2. 自定义CustomKeyboardView, 继承自KeyboardView,实现自定义键盘绘制;


  

    3. 创建KeyboardManager, 用于处理自定义键盘的显示以及和输入UI的交互

        自定义CustomKeyboard

        Android系统Keyboard的构造方法如下:

[Java] 查看源文件 复制代码
 /**
   * Creates a keyboard from the given xml key layout file.
   * @param context the application or service context
   * @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
   */
  public Keyboard(Context context, int xmlLayoutResId) {
    this(context, xmlLayoutResId, 0);
  }

  /**
   * Creates a keyboard from the given xml key layout file. Weeds out rows
   * that have a keyboard mode defined but don't match the specified mode.
   * @param context the application or service context
   * @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
   * @param modeId keyboard mode identifier
   * @param width sets width of keyboard
   * @param height sets height of keyboard
   */
  public Keyboard(Context context, @XmlRes int xmlLayoutResId, int modeId, int width,
      int height) {
      ...
  }

        其中,参数xmlLayoutResId是必须的,另外还可以通过计算系统键盘的高度来设定自定义键盘的高度。

        xmlLayoutRes的格式如下:

[Java] 查看源文件 复制代码
<

        详细的数字键盘和字母键盘xmlLayoutRes资源文件可以从以下链接获取:
数字键盘xmlLayoutRes
字母键盘xmlLayoutRes

        CustomKeyboard主要目的就是赋予xmlLayoutRes并实现特定按键的点击处理,其主要重载的方法是onKey(int primaryCode, int[] keyCodes)。详细代码如下:

[Java] 查看源文件 复制代码
public abstract class BaseKeyboard extends Keyboard implements KeyboardView.OnKeyboardActionListener{

 @Override
 public void onKey(int primaryCode, int[] keyCodes) {
    if(null != mEditText && mEditText.hasFocus() && !handleSpecialKey(primaryCode)) {
      Editable editable = mEditText.getText();
      int start = mEditText.getSelectionStart();
      int end = mEditText.getSelectionEnd();
      if (end > start){
        editable.delete(start,end);
      }
      if(primaryCode == KEYCODE_DELETE) {
        if(!TextUtils.isEmpty(editable)) {
          if(start > 0) {
            editable.delete(start-1,start);
          }
        }
      }else if(primaryCode == getKeyCode(R.integer.hide_keyboard)){
        hideKeyboard();
      }else {
        editable.insert(start,Character.toString((char) primaryCode));
      }
    }
  }

 public abstract boolean handleSpecialKey(int primaryCode);
}

        如上所示是BaseKeyboard,数字键盘和字母键盘需要继承它,并实现public abstract boolean handleSpecialKey(int primaryCode)方法。

        自定义CustomKeyboardView

        KeyboardView 是承载不同的keyboard并绘制keyboard, 是键盘布局的绘制板, 并与系统交互。通过继承KeyboardView自定义CustomKeyboardView,可以对按键样式实现自定义。考察KeyboardView的源码,发现其UI样式都是private类型,这就需要通过反射的方式获取特定的UI属性,并重新进行赋值,同时重载onDraw()方法,在onDraw()中重新绘制。

        详细代码可以参考github源码: BaseKeyBoardView源码

        自定义键盘的UI效果如下:

        


数字键盘

        


字母键盘

        创建KeyboardManager

        主要处理以下功能逻辑:



  

    4. 绑定EditText和Keyboard,监听EditText的OnFocusChangeListener,处理键盘弹出和键盘掩藏;


  

    5. 处理系统键盘和自定义键盘之间的切换关系;


  

    6. 处理键盘区域其他自定义view的显示,比如需要让键盘自动搜索功能时,可在manager中进行相关处理

        以绑定EditText为例:

[Java] 查看源文件 复制代码
public void bindToEditor(EditText editText, BaseKeyboard keyboard) {
  hideSystemSoftKeyboard(editText);
  editText.setTag(R.id.bind_keyboard_2_editor, keyboard);
  if (keyboard.getKeyStyle() == null) {
    keyboard.setKeyStyle(mDefaultKeyStyle);
  }
  editText.setOnFocusChangeListener(editorFocusChangeListener);
}

private final View.OnFocusChangeListener editorFocusChangeListener = new View.OnFocusChangeListener() {
  @Override
  public void onFocusChange(final View v, boolean hasFocus) {
    if (v instanceof EditText) {
      if (hasFocus) {
       v.postDelayed(new Runnable() {
          @Override
          public void run() {
            showSoftKeyboard((EditText) v);
          }
        },300);
      } else {
        hideSoftKeyboard();
      }
    }
  }
};

public void showSoftKeyboard(EditText editText) {
  mRootView.addOnLayoutChangeListener(mOnLayoutChangeListener);
  BaseKeyboard keyboard = getBindKeyboard(editText);
  if (keyboard == null) {
    Log.e(TAG, "edit text not bind to keyboard");
    return;
  }
  keyboard.setEditText(editText);
  keyboard.setNextFocusView(mKeyboardWithSearchView.getEditText());
  initKeyboard(keyboard);
  ...
}

        键盘的使用方式非常简单, 通过KeyboardManager实现调用

        数字键盘:

[Java] 查看源文件 复制代码
KeyboardManager keyboardManagerNumber = new KeyboardManager(this);
keyboardManagerNumber.bindToEditor(editText2, new NumberKeyboard(context,NumberKeyboard.DEFAULT_NUMBER_XML_LAYOUT));

        字母键盘:

[Java] 查看源文件 复制代码
KeyboardManager keyboardManagerAbc = new KeyboardManager(this);
keyboardManagerAbc.bindToEditor(editText1, new ABCKeyboard(context, ABCKeyboard.DEFAULT_ABC_XML_LAYOUT));

        至此,自定义键盘的实现就介绍完了,文中介绍的更多还是实现的思路,具体实现可以参考github,有需要的用户也可以直接修改项目的源码。


20

主题

9216

帖子

2356

安币

Android大神

Rank: 6Rank: 6

发表于 2017-10-26 21:22:07 | 显示全部楼层
感谢大神~

27

主题

9669

帖子

1880

安币

Android大神

Rank: 6Rank: 6

发表于 2017-10-29 00:18:59 | 显示全部楼层
支持楼主,支持安卓巴士!

0

主题

12

帖子

15

安币

初级码农

Rank: 1

发表于 2019-3-13 17:53:14 | 显示全部楼层
很好,有https://github.com/xudjx/djkeyboard

0

主题

12

帖子

15

安币

初级码农

Rank: 1

发表于 2019-3-13 17:54:25 | 显示全部楼层
很好,有https://github.com/xudjx/djkeyboard连接。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站长推荐

通过邮件订阅最新安卓weekly信息
上一条 /4 下一条

下载安卓巴士客户端

全国最大的安卓开发者社区
联系我们
关闭
合作电话:
15618560077
Email:
805941275@qq.com
商务市场合作/投稿
问题反馈及帮助
联系我们

广告投放| 广东互联网违法和不良信息举报中心|中国互联网举报中心|下载客户端|申请友链|手机版|站点统计|安卓巴士 ( 粤ICP备15117877号 )

快速回复 返回顶部 返回列表