输入法编辑器(IME)是一种使用户能够输入文本的用户控件。Android提供了一个可扩展的输入法框架,允许应用程序为用户提供其他输入方法,例如屏幕上的键盘甚至语音输入。安装所需的IME后,用户可以从系统设置中选择使用哪一个,并在整个系统中使用它; 一次只能启用一个IME。

要将IME添加到Android系统,您需要创建一个包含扩展类的Android应用程序InputMethodService。另外,您通常会创建一个“设置”活动,将选项传递给IME服务。您还可以定义显示为系统设置一部分的设置UI。

本指南涵盖以下内容:

  • IME生命周期
  • 在应用程序清单中声明IME组件
  • IME API
  • 设计一个IME UI
  • 从IME发送文本到应用程序
  • 使用IME子类型

如果您之前没有使用过IME,请首先阅读介绍性文章“ 屏幕输入法”。

IME生命周期


下图描述了IME的生命周期:

android 自定义输入法 按钮 基于android自己制作输入法_人工智能


图1. IME的生命周期

以下各节介绍如何实现与此生命周期之后的IME相关的UI和代码。

在清单中声明IME组件


在Android系统中,IME是一个包含特殊IME服务的Android应用程序。应用程序的清单文件必须声明服务,请求必要的权限,提供匹配操作的意图过滤器action.view.InputMethod,并提供定义IME特征的元数据。另外,为了提供允许用户修改IME行为的设置界面,您可以定义可从系统设置启动的“设置”活动。

以下代码片断声明了IME服务。它请求BIND_INPUT_METHOD允许服务将IME连接到系统的权限 ,设置与操作匹配的意图过滤器 android.view.InputMethod,并为IME定义元数据:

<!-- Declares the input method service -->
<service android:name="FastInputIME"
    android:label="@string/fast_input_label"
    android:permission="android.permission.BIND_INPUT_METHOD">
    <intent-filter>
        <action android:name="android.view.InputMethod" />
    </intent-filter>
    <meta-data android:name="android.view.im"
               android:resource="@xml/method" />
</service>

下一个片段声明IME的设置活动。它有一个意图过滤器 ACTION_MAIN,表示此活动是IME应用程序的主要入口点:

<!-- Optional: an activity for controlling the IME settings -->
<activity android:name="FastInputIMESettings"
    android:label="@string/fast_input_settings">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
    </intent-filter>
</activity>

您还可以直接从其UI中访问IME的设置。

输入法API


在android.inputmethodservice和 android.view.inputmethod包中找到特定于IME的类。该KeyEvent班是处理键盘字符重要。

IME的核心部分是一个服务组件,它是一个扩展的类 InputMethodService。除了实现正常的服务生命周期之外,此类还提供了用于提供IME的UI,处理用户输入以及向当前具有焦点的字段传递文本的回调函数。默认情况下, InputMethodService该类提供了用于管理IME的状态和可见性以及与当前输入字段进行通信的大部分实现。

以下课程也很重要:

BaseInputConnection
定义从InputMethod 后面到正在接收其输入的应用程序的通信通道。用它来读取光标周围的文本,将文本提交到文本框,并将原始键事件发送到应用程序。应用程序应该扩展这个类,而不是实现基本接口 InputConnection。

KeyboardView
它的一个扩展View呈现键盘并响应用户输入事件。键盘布局由一个Keyboard可以在XML文件中定义的实例指定 。

设计输入法UI


IME有两个主要的视觉元素:输入视图和 候选视图。您只需实现与您正在设计的输入法相关的元素。

输入视图

输入视图是用户在其中以键击,手写或手势形式输入文本的UI。当IME第一次显示时,系统调用 onCreateInputView()回调。在实现此方法时,可以创建要在IME窗口中显示的布局,并将布局返回到系统。这个片段是实施该onCreateInputView()方法的一个例子 :

@Override
public View onCreateInputView() {
    MyKeyboardView inputView =
        (MyKeyboardView) getLayoutInflater().inflate(R.layout.input, null);

    inputView.setOnKeyboardActionListener(this);
    inputView.setKeyboard(mLatinKeyboard);

    return mInputView;
}

在这个例子中,MyKeyboardView是一个自定义实现的实例 KeyboardView呈现a Keyboard。

候选人视图

候选人视图是IME显示潜在单词更正或建议供用户选择的UI。在IME生命周期中,系统onCreateCandidatesView()在准备好显示候选人视图时调用 。在实现此方法时,返回显示单词建议的布局,如果不想显示任何内容,则返回null。空响应是默认行为,因此如果不提供建议,则不必实现此操作。

UI设计注意事项

本节介绍一些有关IME的特定UI设计注意事项。

处理多种屏幕尺寸
IME的用户界面必须能够针对不同的屏幕尺寸进行缩放,并且还必须处理横向和纵向方向。在非全屏IME模式下,为应用程序留出足够的空间以显示文本字段和任何关联的上下文,以便IME占用不超过一半的屏幕。在全屏IME模式下,这不是问题。

处理不同的输入类型
Android文本字段允许您设置特定的输入类型,例如自由格式文本,数字,网址,电子邮件地址和搜索字符串。当您实施新的IME时,您需要检测每个字段的输入类型并为其提供适当的界面。但是,您不必设置IME来检查用户是否为输入类型输入了有效文本; 这是拥有文本字段的应用程序的责任。

例如,下面是拉丁IME为Android平台提供的文本和电话号码输入提供的界面截图:

android 自定义输入法 按钮 基于android自己制作输入法_android 自定义输入法 按钮_02


图2.拉丁文输入法输入类型。

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

该inputType字段int 包含用于各种输入类型设置的位模式。要对文本字段的输入类型进行测试,请使用常量来掩盖它TYPE_MASK_CLASS,如下所示:

inputType & InputType.TYPE_MASK_CLASS

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

TYPE_CLASS_NUMBER
用于输入数字的文本字段。如前面的屏幕截图所示,拉丁文IME显示此类字段的数字键盘。
TYPE_CLASS_DATETIME
用于输入日期和时间的文本字段。
TYPE_CLASS_PHONE
用于输入电话号码的文本字段。
TYPE_CLASS_TEXT
用于输入所有支持的字符的文本字段。
这些常量在参考文档中有更详细的描述 InputType。

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

TYPE_TEXT_VARIATION_PASSWORD
TYPE_CLASS_TEXT用于输入密码的 变体。输入法将显示dingbats而不是实际的文本。
TYPE_TEXT_VARIATION_URI
的变体TYPE_CLASS_TEXT,用于输入网页的URL和其他的统一资源标识符(URI)。
TYPE_TEXT_FLAG_AUTO_COMPLETE
TYPE_CLASS_TEXT用于输入应用程序从字典,搜索或其他设施“自动完成”的文本的 变体。
请记住inputType在测试这些变体时使用适当的常量进行掩盖。可用的掩码常量在参考文档中列出InputType。

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

发送文本到应用程序


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

编辑光标周围的文本

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

getTextBeforeCursor()
返回一个CharSequence包含当前光标位置之前请求字符数的a 。
getTextAfterCursor()
返回CharSequence包含当前光标位置后面的请求字符数的a 。
deleteSurroundingText()
删除当前光标位置前后的指定字符数。
commitText()
提交一个CharSequence文本字段并设置一个新的光标位置。
例如,下面的代码片段显示了如何用文本“Hello!”替换光标左边的四个字符:

InputConnection ic = getCurrentInputConnection();
ic.deleteSurroundingText(4, 0);
ic.commitText("Hello", 1);
ic.commitText("!", 1);

提交前撰写文本

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

以下片段显示了如何在文本字段中显示进度:

InputConnection ic = getCurrentInputConnection();
ic.setComposingText("Composi", 1);
ic.setComposingText("Composin", 1);
ic.commitText("Composing ", 1);

以下屏幕截图显示了用户对此的看法:

android 自定义输入法 按钮 基于android自己制作输入法_ui_03


图3.提交前撰写文本。

拦截硬件按键事件

即使输入法窗口没有明确的焦点,它也会首先接收硬件按键事件,并可以选择使用它们或将它们转发给应用程序。例如,您可能想要在构图期间使用方向键在UI内导航以供候选人选择。您也可能想要隐藏后退键以关闭源于输入法窗口的任何弹出窗口。

拦截硬件键,覆盖 onKeyDown() 和onKeyUp()。

记得调用super()你不想处理的密钥的方法。

创建一个IME子类型


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

  • 一个区域设置,例如en_US或fr_FR。
  • 输入模式,如语音,键盘或手写。
  • 其他输入样式,表单或特定于IME的属性,例如10键或qwerty键盘布局。

基本上,该模式可以是任何文本,例如“键盘”,“声音”等等。子类型也可以公开这些组合。

子类型信息用于通知栏中提供的IME切换器对话框以及IME设置。该信息还允许框架直接调出IME的特定子类型。当您构建IME时,请使用子类型工具,因为它可以帮助用户识别和切换不同的IME语言和模式。

您可以使用<subtype>元素在其中一个输入方法的XML资源文件中定义子类型 。以下片段定义了一个带有两个子类型的IME:美式英语语言环境的键盘子类型和法语法语语言环境的另一个键盘子类型:

<input-method xmlns:android="http://schemas.android.com/apk/res/android"
        android:settingsActivity="com.example.softkeyboard.Settings"
        android:icon="@drawable/ime_icon">
    <subtype android:name="@string/display_name_english_keyboard_ime"
            android:icon="@drawable/subtype_icon_english_keyboard_ime"
            android:imeSubtypeLanguage="en_US"
            android:imeSubtypeMode="keyboard"
            android:imeSubtypeExtraValue="somePrivateOption=true" />
    <subtype android:name="@string/display_name_french_keyboard_ime"
            android:icon="@drawable/subtype_icon_french_keyboard_ime"
            android:imeSubtypeLanguage="fr_FR"
            android:imeSubtypeMode="keyboard"
            android:imeSubtypeExtraValue="foobar=30,someInternalOption=false" />
    <subtype android:name="@string/display_name_german_keyboard_ime" ... />
</input-method>

为确保您的子类型在UI中正确标记,请使用%s获取与子类型的语言环境标签相同的子类型标签。这在接下来的两个片段中得到证明。第一个片段显示了输入法的XML文件的一部分:

<subtype
    android:label="@string/label_subtype_generic"
    android:imeSubtypeLocale="en_US"
    android:icon="@drawable/icon_en_us"
    android:imeSubtypeMode="keyboard" />

下一个片段是IME strings.xml文件的一部分。label_subtype_generic输入法UI定义用于设置子类型标签的字符串资源定义如下:

<string name="label_subtype_generic">%s</string>

此设置会导致子类型的显示名称与区域设置相匹配。例如,在任何英语语言环境中,显示名称均为“英语(美国)”。

从通知栏中选择IME子类型

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

android 自定义输入法 按钮 基于android自己制作输入法_人工智能_04


图4.从通知栏中选择IME子类型。

android 自定义输入法 按钮 基于android自己制作输入法_移动开发_05


图5.在系统设置中设置子类型首选项。

从系统设置中选择IME子类型

用户可以控制“系统设置”区域中“语言和输入”设置面板中的子类型使用方式。

android 自定义输入法 按钮 基于android自己制作输入法_android_06


图6.为IME选择一种语言。

在IME子类型之间切换


您可以通过在键盘上提供切换键(如globe形状的语言图标),允许用户在多个IME子类型之间轻松切换。这样做极大地提高了键盘的可用性,并且可以帮助避免用户的沮丧。要启用这种切换,请执行以下步骤:
1、声明supportsSwitchingToNextInputMethod = "true"在输入法的XML资源文件。您的声明应该与以下代码片段类似:

<input-method xmlns:android="http://schemas.android.com/apk/res/android"
        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界面设置选项的方法。
  • 由于可以在设备上安装多个IME,因此可以让用户直接从输入法UI切换到其他IME。
  • 快速调出IME的用户界面。根据需要预加载或加载任何大型资源,以便用户在点击文本字段后立即看到输入法。为后续调用输入方法缓存资源和视图。
  • 相反,在隐藏输入法窗口后,应该立即释放大量内存分配,以便应用程序可以有足够的内存运行。如果IME处于隐藏状态几秒钟,请考虑使用延迟消息释放资源。
  • 确保用户可以为与IME关联的语言或区域输入尽可能多的字符。请记住,用户可能会在密码或用户名中使用标点符号,因此您的IME必须提供许多不同的字符以允许用户输入密码并访问设备。


转载于:https://blog.51cto.com/4789781/2125396