输入法编辑器(IME)是一个便于用户输入文本的控件。Android提供了一个可扩展的输入法框架,允许应用程序提供可替代的输入法,比如屏幕上的键盘或者语音输入。在安装输入法后,用户可以通过系统选项选择想要使用的输入法。

想要添加一个输入法,你需要创建一个Android应用并包含一个继承自InputMethodService的类。此外,同城创建一个设置页面来承载输入发的各个选项。你可以自行定义一个设置的UI。

下面讲述以下几个内容:

输入法的生命周期

在应用的清单文件中定义输入法组件

输入法相关接口

设计一个款输入法的UI

发送文本到应用

输入法子类型的使用

一、输入法的生命周期

输入法的生命周期如下图所示:

20170206170754535.png

二、在清单文件中定义输入法组件

在Android系统中,IME是一个包含特殊IME服务的应用程序。应用的清单文件必须声明输入法服务,请求必须的权限,提供一个intent filter来匹配 action.view.InputMethod,并提供定义了IME特征的元数据(metadata)。此外,可以定义一个设置页面来提供用户修改IME配置的接口,它可以被系统设置所启动。

下面的代码片段声明了一个IME服务。请求了 BIND_INPUT_METHOD 权限来允许服务连接到系统的IME,建立intent filter和metadata:

android:label="@string/fast_input_label"

android:permission="android.permission.BIND_INPUT_METHOD">

android:resource="@xml/method" />

下面的代码片段声明了IME的设置页面,它拥有 ACTION_MAIN 的intent filter来表示它是IME程序的主入口

android:label="@string/fast_input_settings">

也可以从IME的UI提供直接进入设置的入口。

三、输入法API

与IME相关的类在 android.inputmethodservice 和 android.view.inputmethod 包中。KeyEvent 类对于处理键盘特征至关重要。

IME的核心部分是一个服务组件,即一个继承自InputMethodService的类。此外为了实现一般服务的生命周期,这个类提供了IME的UI,处理用户输入和传输文本到指定区域以及当前焦点的回调。InputMethodService类提供了绝大多数管理IME状态和与当前输入区域交互的实现。

下面几个类也很重要。

BaseInputConnection

定义了输入法和应用之间接收输入的交互通道。使用它来读取光标周围的文本,提交文本到输入框以及发送键盘事件给应用。应用应该集成此类。

KeyboardView

一个View的扩展,描绘了一个键盘和用户输入事件的响应。键盘的布局是被Keyboard的实例指定,可以定义一个XML文件。

四、设计输入法UI

IME有两个主要的视觉元素:即输入视图和备选视图。你只需要实现和你设计的输入法有关的元素。

4.1 输入视图

输入视图是用户使用按键,手写或者手势在表单中输入文本的UI。

当IME第一次显示,系统会调用 onCreateInputView() 回调。在你实现的这个方法中,你创建你想要的IME窗口的布局并返回给系统。下面片段是一个例子:

@Override

public View onCreateInputView() {

MyKeyboardView inputView =

(MyKeyboardView) getLayoutInflater().inflate( R.layout.input, null);

inputView.setOnKeyboardActionListener(this);

inputView.setKeyboard(mLatinKeyboard);

return mInputView;

}

这里的MyKeyboardView是一个自定义的实现了 KeyboardView 的实例,如果你构建的是一个传统的QWERTY键盘,请查看 KeyboardView 类。

4.2.候选视图

候选视图是供用户选择可选词和推荐词的视图。在IME的生命周期中,系统在准备好显示备选视图的时候会调用onCreateCandidatesView()。在你实现的这个方法中,返回显示词汇建议的布局,当什么都不显示时,返回null。

若要查看实现用户建议词汇的例子,请查看SoftKeyboard示例应用。

4.3.UI设计依据

此部分介绍了一些IME的UI设计思想。

· 应对多元化的屏幕尺寸

你的IME的UI必须可以适配不同屏幕的尺寸,且必须处理竖屏和横屏两种方向。在非全屏模式下,为应用程序留出足够的空间以显示文本字段和任何相关联的上下文,使得IME不会占用屏幕一半以上的空间。在全屏模式下没有这个问题。

· 处理不同的输入类型

Android的输入框允许你选择一个特殊的输入类型,比如自由文本,数字,网址,邮箱地址,收索内容等。当你实现一个新的IME,您需要检测每个字段的输入类型,并为其提供适当的接口。但是,你不必设置IME以检查用户输入的文本对输入类型有效; 这是拥有文本字段的应用程序的责任。

当输入字段接收焦点并且您的IME启动时,系统调用 onStartInputView(),传递一个 EditorInfo 对象,该对象包含有关文本字段的输入类型和其他属性的详细信息。 在此对象中,inputType 字段包含文本字段的输入类型。

输入类型字段是一个包含用于各种输入类型设置的位模式的int参数。 要测试它的文本字段的输入类型,用常量TYPE_MASK_CLASS屏蔽它,像这样:

inputType & InputType.TYPE_MASK_CLASS

输入类型位模式可以具有几个值中的一个,包括:

TYPE_CLASS_NUMBER

用于输入数字的文本字段。

TYPE_CLASS_DATETIME

用于输入日期和时间的文本字段。

TYPE_CLASS_PHONE

用于输入电话号码的文本字段。

TYPE_CLASS_TEXT

用于输入所有支持的字符的文本字段。

这些常量在 InputType 的参考文档中有更详细的描述。

inputType字段可以包含指示文本字段类型的其他位,例如:

TYPE_TEXT_VARIATION_PASSWORD

用于输入密码的TYPE_CLASS_TEXT 的变体。 输入法将显示标记,而不是实际文本。

TYPE_TEXT_VARIATION_URI

用于输入网址和其他统一资源标识符(URI)的TYPE_CLASS_TEXT 的变体。

TYPE_TEXT_FLAG_AUTO_COMPLETE

TYPE_CLASS_TEXT 的变体,用于输入应用程序从字典,搜索或其他工具中“自动完成”的文本。

记住在测试这些变量时,用适当的常数掩蔽输入类型。 可用的掩码常数在输入类型的参考文档中列出。

注意:在您自己的IME中,确保在将其发送到密码字段时正确处理文本。 在输入视图和候选视图中的用户界面中隐藏密码。 还要记住,您不应该在设备上存储密码。 要了解更多信息,请参阅“为安全性设计”指南。

五、向应用程序发送文本

当用户使用IME输入文本时,您可以通过发送单个键事件或在应用程序的文本字段中编辑光标周围的文本来向应用程序发送文本。 在任一情况下,您都使用 InputConnection的实例来传递文本。 要获取此实例,请调用 InputMethodService.getCurrentInputConnection() 。

5.1.编辑光标周围的文本

当处理文本字段中现有文本的编辑时,BaseInputConnection 中一些更有用的方法是:

getTextBeforeCursor()

返回包含当前光标位置之前的请求字符数的 CharSequence 。

getTextAfterCursor()

返回包含当前光标位置后的请求字符数的 CharSequence 。

deleteSurroundingText()

删除当前光标位置前后的指定数量的字符。

commitText()

向文本字段提交 CharSequence 并设置新的光标位置。

例如,以下代码段显示如何使用文本“Hello!”替换光标左侧的四个字符:

InputConnection ic = getCurrentInputConnection();

ic.deleteSurroundingText(4, 0);

ic.commitText("Hello", 1);

ic.commitText("!", 1);

5.2.在提交之前撰写文本

如果您的IME执行文本预测或需要多个步骤来组成字形或单词,则可以在文本字段中显示进度,直到用户提交单词,然后您可以用完成的文本替换部分组合。 当你传递给 setComposingText()时,你可以通过添加一个“span”来对文本进行特殊处理。

以下代码段显示了如何在文本字段中显示进度

2.在提交之前撰写文本

如果您的IME执行文本预测或需要多个步骤来组成字形或单词,则可以在文本字段中显示进度,直到用户提交单词,然后您可以用完成的文本替换部分组合。 当你传递给 setComposingText()时,你可以通过添加一个“span”来对文本进行特殊处理。

以下代码段显示了如何在文本字段中显示进度

以下屏幕截图显示了用户看到的页面:

WX20181023-195324@2x.png

5.3.拦截硬件按键事件

即使输入法窗口没有明确的焦点,它首先接收硬件键事件,并且可以选择使用它们或将它们转发到应用程序。 例如,您可能想要使用方向键在UI中导航以在组合期间选择候选项。 您可能还想捕获返回键以关闭源自输入法窗口的任何弹出窗口。

要拦截硬件键,重写onKeyDown()和 onKeyUp()。 请参阅 SoftKeyboard 示例应用程序的示例。

记住要为你不想处理的键调用super()方法。

六、创建IME子类型

子类型允许IME公开IME支持的多种输入模式和语言。 子类型可以表示:

· 区域设置,如en_US或fr_FR

· 输入模式,如语音,键盘或手写

· IME特有的其他输入样式,表单或属性,例如10键或qwerty键盘布局。

基本上,模式可以是诸如“键盘”,“语音”等的任何文本。 子类型还可以暴露这些的组合。

子类型信息用于IME切换器对话框,该对话框可从通知栏和IME设置中使用。 该信息还允许框架直接引出IME的特定子类型。 当构建IME时,使用子类型工具,因为它有助于用户识别和在不同的IME语言和模式之间切换。

您可以使用元素在输入法的XML资源文件之一中定义子类型。 以下代码段定义了一个具有两个子类型的IME:美国英语语言环境的键盘子类型,法国的法语语言环境的另一个键盘子类型

android:settingsActivity="com.example.softkeyboard.Settings"

android:icon="@drawable/ime_icon"

android:icon="@drawable/subtype_icon_english_keyboard_ime"

android:imeSubtypeLanguage="en_US"

android:imeSubtypeMode="keyboard"

android:imeSubtypeExtraValue="somePrivateOption=true"

/>

android:icon="@drawable/subtype_icon_french_keyboard_ime"

android:imeSubtypeLanguage="fr_FR"

android:imeSubtypeMode="keyboard"

android:imeSubtypeExtraValue="foobar=30,someInternalOption=false"

/>

...

/>

/>

6.1.从通知栏中选择TIME子类型

Android系统管理所有IME公开的所有子类型。 IME子类型被视为它们所属的IME的模式。 在通知栏中,用户可以为当前设置的IME选择可用的子类型,如以下屏幕截图所示:

20170206171319355.png

20170206171330099.png

6.2.从系统设置选择IME子类型

用户可以在“系统设置”区域的“语言和输入”设置面板中控制子类型的使用方式。 在 SoftKeyboard 示例应用程序中,文件InputMethodSettingsFragment.java包含一个在IME设置中实现子类型启用程序的实现。 有关如何在IME中支持输入法子类型的更多信息,请参阅Android SDK中的 SoftKeyboard 示例应用程序。

20170206171422115.png

6.3.在IME子类型之间切换

您可以允许用户通过提供切换键(如球形语言图标)作为键盘的一部分,在多个IME子类型之间轻松切换。 这样做大大提高了键盘的可用性,并可以帮助避免用户的失望。 要启用此类切换,请执行以下步骤:

(1). 在输入法的XML资源文件中声明 supportsSwitchingToNextInputMethod = “true” 。 您的声明应类似于以下代码段:

android:settingsActivity="com.example.softkeyboard.Settings"

android:icon="@drawable/ime_icon"

android:supportsSwitchingToNextInputMethod="true">

(2). 调用 shouldOfferSwitchingToNextInputMethod() 方法。

(3). 如果方法返回true,则显示切换键。

(4). 当用户点击切换键时,调用 switchToNextInputMethod(),将false传递给第二个参数。 值false表示系统平等对待所有子类型,而不管它们属于什么IME。 指定true要求系统在当前IME中循环遍历子类型。

注意:在Android 5.0(API级别21)之前,switchToNextInputMethod()不知道 supportsSwitchingToNextInputMethod 属性。 如果用户切换到IME而没有切换键,他可能会卡在该IME中,无法轻松地切换出来。

七、一般IME注意事项

以下是您实现IME时需要考虑的其他事项:

· 为用户提供一种直接从IME的UI设置选项的方法。

· 因为设备上可以安装多个IME,所以提供了用于用户从输入法UI直接切换到不同的IME的方式。

· 快速启动IME的UI。根据需要预加载或加载任何大型资源,以便用户在点击文本字段时看到IME。缓存资源和视图,用于后续调用输入法。

· 相反,您应该在隐藏输入法窗口后立即释放大量内存分配,以便应用程序可以有足够的内存来运行。如果IME处于隐藏状态几秒钟,请考虑使用延迟消息来释放资源。

· 请确保用户可以为与IME关联的语言或区域设置输入尽可能多的字符。请记住,用户可以在密码或用户名中使用标点符号,因此您的IME必须提供许多不同的字符,以允许用户输入密码并访问设备。

参考

android 输入法字典_Android输入法开发相关推荐

  1. android cmake 打印_Android NDK 开发:CMake 使用

    1. 前言 当在做 Android NDK 开发时,如果不熟悉用 CMake 来构建,读不懂 CMakeLists.txt 的配置脚本,很容易就会踩坑,遇到编译失败,一个很小的配置问题都会浪费很多时间 ...

  2. android pcm频谱_Android音频开发(7):音乐可视化-FFT频谱图

    Android 音频开发 目录 一.演示 image 二.实现 实现流程: 使用MediaPlayer播放传入的音乐,并拿到mediaPlayerId 使用Visualizer类拿到拿到MediaPl ...

  3. android策略模式_Android游戏开发–设计游戏实体–策略模式

    android策略模式 在这一部分中,我将尝试解释我对好的游戏设计元素的理解. 我将在示例中使用droid,并编写基本的战斗模拟器脚本以查看其行为. 问题: 我指挥一个机器人,我想消灭敌人. 再次面对 ...

  4. android camera移动方向_Android Camera开发系列:调整Camera预览方向

    有时候我们想根据自己的需要调整下Camera的预览方向,那么是调用哪个API可以达到我们的目的呢? 我们看下下图拍的几张小可爱的照片,分别是正常方向.旋转180度.90度拍的照片. ​ 正常方向 旋转 ...

  5. android爆炸粒子_Android游戏开发–粒子爆炸

    android爆炸粒子 有没有想过爆炸是如何产生的? 让我们绕个弯路,尝试实现基本的粒子爆炸. 爆炸不过是一堆散布在屏幕上的,源自单个点的粒子(无论是像素,小形状还是图像). 为了方便起见,并非总是如 ...

  6. android 人物走动_Android游戏开发学习(2)--SurfaceView实例控制角色移动

    先看效果 我用到的图片- 在看代码 package dk.game; import android.app.Activity; import android.os.Bundle; import and ...

  7. android 输入法如何启动流程_android输入法02:openwnn源码解析01—输入流程

    android 输入法 02:openwnn 源码解析 01-输入流程 之后要开始 android 日文输入法的测试,因此现在开始研究 android 输入法.之前两 篇文章已经对 android 自 ...

  8. android 输入法如何启动流程_android输入法状态控制

    在应用程序中,我们经常需要控制EditText的输入法打开与关闭,手指touch之后,自动打开了输入法,可是怎么控制关闭输入法,除了输入法自己的关闭按钮之外,还有以下的方法. 一.打开输入法窗口: I ...

  9. Android下创建一个输入法

    输入法是一种可以让用户输入文字的控件.Android提供了一套可扩展的输入法框架,使得应用程序可以让用户选择各种类型的输入法,比如基于触屏的键盘输入或者基于语音.当安装了特定输入法之后,用户即可在系统 ...

  10. android 输入法 悬浮窗口,Android EditText悬浮在输入法之上

    Android EditText悬浮在输入法之上 使用 android:windowSoftInputMode="adjustResize" 会让界面整体被顶上去,很多时候我们不需 ...

最新文章

  1. 微服务架构下,解决数据一致性问题的实践
  2. tjoi2018D2T2(luogu4590) 游园会 (状压dp)
  3. 国内三款主流海淘产品APP竞品分析
  4. 为什么VS(visual studio)中会建议宏 #define 转换为constexpr?
  5. Android如何实现TCP和UDP传输
  6. 数据结构与算法入门---数据结构类型
  7. 编写一个程序,对一个整型数组的元素求和,结果使用全局变量sum存储,另外对数组元素中的奇数求和,结果使用局部变量sum存储,在主程序将两个结果输出。
  8. 数据可视化怎么完成的_完成期望后会发生什么:可视化育儿数据
  9. Matlab之三维曲面的绘制
  10. 如意淘商品推荐技术介绍之一:基础推荐
  11. 拆解一探电路设计:小米路由器3C拆解
  12. python识别手写文字_深度学习---手写字体识别程序分析(python)
  13. 计算机无线网络计算机文件共享,两台电脑怎么用无线网络共享文件?
  14. Linux命令行下,颜色表示什么意思
  15. 短期工作经历到底要不要写到简历上?
  16. 改变指标改变图(FusionChart)
  17. 鲁大师升级“Pro”,2B领域谋篇布局
  18. luhn算法 java_java – 使用luhn算法验证信用卡号
  19. Java多线程运用——赛马小游戏
  20. Newcoder 110 E.Pocky游戏(状压DP)

热门文章

  1. 用Google地图获取地图上某点的经纬度坐标
  2. Windows 10 系统关闭自动更新
  3. CSS3:3D环绕实现
  4. c语言之sizeof与strlen全
  5. 直方图均衡(HE)与局部色调映射(LTM)
  6. Promise then的嵌套
  7. offer和面经分享(内含offer截图)
  8. 原生对象、内置对象、宿主对象的区别
  9. 重装后显示计算机无法联网,重装系统后电脑无法连接网络怎么办
  10. 【Git】Git的“隐身术”:git status/git diff……文件被忽略的秘密