概述

  在项目开发中遇到一个需求,”只要数字键盘的输入,仅仅有大写字母的输入,某些输入法总是会提示更新,弹出广告等“,使得我们需要自定义输入。

关联到的知识 

  • KeyboardView      一个视图对象,展示了键盘。它需要关联到一个 Keyboard对象才能展示。
  • Keyboard              键盘对象,通过加载xml的配置获得键盘的排列。
  • xml 文件键盘描述     一个xml文件,放置在 xml 资源文件夹下,描述了 显示的键盘按钮,和排列,键盘宽度和高度等。

具体实现

  准备xml键盘描述文件

    在xml文件夹下创建文件,下面的代码中使用 “ 33%p” 这样的单位指定一定的 百分比,以适配屏幕,详细内容如下:

<?xml version="1.0" encoding="UTF-8"?><!-- 数字键盘 -->
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
android:horizontalGap="0dp"
android:keyHeight="61dp"
android:keyWidth="33%p"
android:verticalGap="0dp">
<Row>
<Key
android:codes="49"
android:keyEdgeFlags="left"
android:keyLabel="1" />
<Key
android:codes="50"
android:keyLabel="2" />
<Key
android:codes="51"
android:keyLabel="3" />
</Row>
<Row>
<Key
android:codes="52"
android:keyEdgeFlags="left"
android:keyLabel="4" />
<Key
android:codes="53"
android:keyLabel="5" />
<Key
android:codes="54"
android:keyLabel="6" />
</Row>
<Row>
<Key
android:codes="55"
android:keyEdgeFlags="left"
android:keyLabel="7" />
<Key
android:codes="56"
android:keyLabel="8" />
<Key
android:codes="57"
android:keyLabel="9" />
</Row>
<Row>
<Key
android:codes="48"
android:keyEdgeFlags="left"
android:keyLabel="0" />
<Key
android:codes="-5"
android:isRepeatable="true"
android:keyIcon="@drawable/keyboard_delete"
android:keyWidth="66%p" />
</Row>
</Keyboard>

  创建Keyboard对象

    要先配置好xml文件,在构造方法里传入上面的xml文件

 this.keyboard = new Keyboard(mActivity, R.xml.small_keyboard);

  构造KeyboardView

    keyboardView 对象可以在 xml 中描述,类似下面这样

  

<android.inputmethodservice.KeyboardView
android:id="@+id/keyboard_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@android:color/transparent"
android:focusable="true"
android:focusableInTouchMode="true"
android:keyBackground="@drawable/keyboard_key"
android:keyTextColor="@color/white"
android:keyTextSize="@dimen/sp_32"
android:visibility="visible" />

    获得 KeyboardView并进行配置,需要关联到具体的 keyboard 对象

        KeyboardView keyboardView = (KeyboardView) viewContainer.findViewById(R.id.keyboard_view);
this.keyboardView = keyboardView;
this.keyboardView.setKeyboard(keyboard);
this.keyboardView.setEnabled(true);
this.keyboardView.setPreviewEnabled(false);
this.keyboardView.setOnKeyboardActionListener(listener2);

  

   隐藏系统自带的键盘

      根据android系统的版本的不同,有不同的方法,需要利用反射,见代码:

 /**
* 隐藏系统键盘
*
* @param editText
*/
public static void hideSystemSofeKeyboard(EditText editText) {
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);
}
}

  从底部弹出键盘

  输入法需要从页面底部向上弹出,需要一个过渡动画,android每个页面都有一个window,window包含了一个getDecorView 根视图,我们要把键盘的视图添加到这个根视图下,配合动画出现键盘。

    

    public void showSoftKeyboard() {

        if (viewContainer == null) {
viewContainer = mActivity.getLayoutInflater().inflate(R.layout.keyboardview_layout, null);
} else {
if (viewContainer.getParent() != null)
return;
} FrameLayout frameLayout = (FrameLayout) mActivity.getWindow().getDecorView();
KeyboardView keyboardView = (KeyboardView) viewContainer.findViewById(R.id.keyboard_view);
this.keyboardView = keyboardView;
this.keyboardView.setKeyboard(keyboard);
this.keyboardView.setEnabled(true);
this.keyboardView.setPreviewEnabled(false);
this.keyboardView.setOnKeyboardActionListener(listener2); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.BOTTOM;
frameLayout.addView(viewContainer, lp);
//viewContainer.setVisibility(View.GONE);
viewContainer.setAnimation(AnimationUtils.loadAnimation(mActivity, R.anim.down_to_up));
}

完整的代码如下:

package vir56k.democustomkeyboard;

import android.app.Activity;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
import android.os.Build;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.EditText;
import android.widget.FrameLayout; import java.lang.reflect.Method; public class PopupKeyboardUtil {
private Activity mActivity; private KeyboardView keyboardView;
private Keyboard keyboard;// 全键盘包括数字和字母 private EditText editText1; public PopupKeyboardUtil(Activity mActivity) {
this.mActivity = mActivity;
this.keyboard = new Keyboard(mActivity, R.xml.small_keyboard);
} public void attachTo(EditText editText, boolean isAuto) {
this.editText1 = editText;
hideSystemSofeKeyboard(this.editText1);
setAutoShowOnFocs(isAuto);
} public void setAutoShowOnFocs(boolean enable) {
if (editText1 == null)
return;
if (enable)
editText1.setOnFocusChangeListener(onFocusChangeListener1);
else
editText1.setOnFocusChangeListener(null);
} View.OnFocusChangeListener onFocusChangeListener1 = new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus)
showSoftKeyboard();
else
hideSoftKeyboard();
}
}; View viewContainer; public void showSoftKeyboard() { if (viewContainer == null) {
viewContainer = mActivity.getLayoutInflater().inflate(R.layout.keyboardview_layout, null);
} else {
if (viewContainer.getParent() != null)
return;
} FrameLayout frameLayout = (FrameLayout) mActivity.getWindow().getDecorView();
KeyboardView keyboardView = (KeyboardView) viewContainer.findViewById(R.id.keyboard_view);
this.keyboardView = keyboardView;
this.keyboardView.setKeyboard(keyboard);
this.keyboardView.setEnabled(true);
this.keyboardView.setPreviewEnabled(false);
this.keyboardView.setOnKeyboardActionListener(listener2); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.BOTTOM;
frameLayout.addView(viewContainer, lp);
//viewContainer.setVisibility(View.GONE);
viewContainer.setAnimation(AnimationUtils.loadAnimation(mActivity, R.anim.down_to_up));
} public void hideSoftKeyboard() {
if (viewContainer != null && viewContainer.getParent() != null) {
((ViewGroup) viewContainer.getParent()).removeView(viewContainer);
}
} public boolean isShowing() {
if (viewContainer == null)
return false;
return viewContainer.getVisibility() == View.VISIBLE;
} /**
* 隐藏系统键盘
*
* @param editText
*/
public static void hideSystemSofeKeyboard(EditText editText) {
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);
}
} private OnKeyboardActionListener listener2 = new 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) {
if (editText1 != null) {
keyCode_delect(primaryCode, editText1);
}
keyboardView.postInvalidate();
}
}; /**
* 判断回退键 和大小写切换
*
* @param primaryCode
* @param edText
*/
private void keyCode_delect(int primaryCode, EditText edText) { Editable editable = edText.getText();
int start = edText.getSelectionStart();
if (primaryCode == Keyboard.KEYCODE_DELETE) {// 回退
if (edText.hasFocus()) {
if (!TextUtils.isEmpty(editable)) {
if (start > 0) {
editable.delete(start - 1, start);
}
}
} } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {// 大小写切换
keyboardView.setKeyboard(keyboard);
} else {
if (edText.hasFocus()) {
editable.insert(start, Character.toString((char) primaryCode));
}
}
} }

功能完成后,具体调用的演示:

package vir56k.democustomkeyboard;

import android.app.Activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText; public class MainActivity extends AppCompatActivity {
EditText edittext1;
PopupKeyboardUtil smallKeyboardUtil;
private View viewContainer; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); edittext1 = (EditText) findViewById(R.id.edittext1); smallKeyboardUtil = new PopupKeyboardUtil(self());
smallKeyboardUtil.attachTo(edittext1, false);
//smallKeyboardUtil.setAutoShowOnFocs(false);
} public void onClickView(View view) {
if (view.getId() == R.id.btn1)
smallKeyboardUtil.showSoftKeyboard();
if (view.getId() == R.id.btn2)
smallKeyboardUtil.hideSoftKeyboard(); } private Activity self() {
return this;
}
}

完整的代码下载:

https://github.com/vir56k/demo/tree/master/demo.customkeyboard

  

android开发(45) 自定义软键盘(输入法)的更多相关文章

  1. Android开发案例 - 自定义虚拟键盘

    所有包含IM功能的App(如微信, 微博, QQ, 支付宝等)都提供了Emoji表情之类的虚拟键盘,  如下图:    本文只着重介绍如何实现输入法键盘和自定义虚拟键盘的流畅切换, 而不介绍如何实现虚 ...

  2. Android App监听软键盘按键的三种方式

    前言:   我们在android手机上面有时候会遇到监听手机软键盘按键的时候,例如:我们在浏览器输入url完毕后可以点击软键盘右下角的“GO”按键加载url页面:在点击搜索框的时候,点击右下角的sea ...

  3. Android App监听软键盘按键的三种方式(转)

    最近有类似需求,在csdn上刚好发现,粘贴过来,以防止忘记喽 前言:   我们在android手机上面有时候会遇到监听手机软键盘按键的时候,例如:我们在浏览器输入url完毕后可以点击软键盘右下角的“G ...

  4. Android中点击隐藏软键盘最佳方法——Android开发之路4

    Android中点击隐藏软键盘最佳方法 实现功能:点击EditText,软键盘出现并且不会隐藏,点击或者触摸EditText以外的其他任何区域,软键盘被隐藏: 1.重写dispatchTouchEve ...

  5. android开发之自定义组件

    android开发之自定义组件 一:自定义组件: 我认为,自定义组件就是android给我们提供的的一个空白的可以编辑的图片,它帮助我们实现的我们想要的界面,也就是通过自定义组件我们可以把我们要登入的 ...

  6. android 弹出的软键盘遮挡住EditText文本框的解决方案

    1.android 弹出的软键盘遮挡住EditText文本框的解决方案: 把Activit对应的布局文件filename.xml文件里的控件用比重设置布局.(例如:android:layout_wei ...

  7. 钉钉开发笔记(5)android系统中html软键盘的适配

    最近项目中发现个别Android手机中存在弹出的软键盘会遮挡输入框的现象,最后自己写了一个方法(如下),问题基本解决. 记录下来,防止忘记.有什么不对的地方欢迎指正.O(∩_∩)O 1 //键盘适配 ...

  8. 软键盘 输入法管理器 InputMethodManager

     基本介绍 软键盘的显示原理 软键盘其实是一个Dialog.InputMethodService为我们的输入法创建了一个Dialog,并且对某些参数进行了设置,使之能够在底部或者全屏显示.当我们点击输 ...

  9. android显示和隐藏软键盘(转)

    显示键盘: EditText editText.setFocusable(true); editText.setFocusableInTouchMode(true); editText.request ...

随机推荐

  1. [转]Servlet 单例多线程

    Servlet如何处理多个请求访问? Servlet容器默认是采用单实例多线程的方式处理多个请求的: 1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在 ...

  2. golang包time用法详解

    在我们编程过程中,经常会用到与时间相关的各种务需求,下面来介绍 golang 中有关时间的一些基本用法,我们从 time 的几种 type 来开始介绍. 时间可分为时间点与时间段,golang 也不例 ...

  3. Django基于正则表达式的URL(2)

    Django基于正则表达式的URL(2) 1. 关于正则的说明 url(r'^detail-(\d+)-(\d+).html',views.detail), 当客户端输入 127.0.0.1:8000 ...

  4. 史上最简单的 GitHub 教程

    史上最简单的 GitHub 教程 温馨提示:本系列博文已经同步到 GitHub,如有需要的话,欢迎大家到「github-tutorial」进行Star和Fork操作! 1 简介 GitHub 是一个面 ...

  5. Python常见问题系列

    Python基础题1.冒泡排序 def mao_pao(li): for i in range(len(li)): for j in range(len(li)): if li[i] < li[ ...

  6. 将redis作为windows服务安装

    1,下载redis并解压到一个目录下,然后切换到该目录下,也就是redis-server.exe文件所在的目录 2,在cmd下执行 redis-server --service-install red ...

  7. 群主微信sdk说明地址

    群主微信sdk说明地址官网地址:http://weixin.senparc.com/ 源代码及最新更新:https://github.com/JeffreySu/WeiXinMPSDK 最新DLL发布 ...

  8. C++中虚函数的作用是什么?它应该怎么用呢?

    虚函数联系到多态,多态联系到继承.所以本文中都是在继承层次上做文章.没了继承,什么都没得谈. 下面是对C++的虚函数这玩意儿的理解. 一, 什么是虚函数(如果不知道虚函数为何物,但有急切的想知道,那你 ...

  9. fzu2158

    http://acm.fzu.edu.cn/problem.php?pid=2158 在密室逃脱游戏中,大家被困在一个密室中,为了逃出密室,需要找到正确的数字密码,于是大家分头行动,分别找到了密码的子 ...

  10. ios 6.1中 Release问题

    程序中有如下代码: UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Something was done." m ...