App Extension Programming Guide: Custom Keyboard
自定义键盘取代了系统键盘,用户需要能力,如一种新的文本输入方法,或者在IOS中不支持的语言中输入文本的能力。自定义键盘的基本功能很简单:响应轻敲、手势或其他输入事件,并在当前文本输入对象的文本插入点以非属性NSCOPE对象的形式提供文本。
用户选择自定义键盘后,它就成为用户打开的每个应用程序的键盘。为此,您创建的键盘至少必须提供某些基本特征。最重要的是,您的键盘必须允许用户切换到另一个键盘。#了解用户对键盘的期望为了了解用户对自定义键盘的期望,研究系统键盘的快速、响应和能力。而且它从不中断用户的信息或请求。如果您提供需要用户交互的功能,则不将它们添加到键盘,而是添加到包含键盘的应用程序中。
iOS用户期待的键盘功能
这是iOS用户期望的一个特性,每个自定义键盘必须提供:切换到另一个键盘的方法。在系统键盘上,这个按钮显示为一个称为“环球钥匙”的按钮。在iOS 8和以后,系统为您的“下一个键盘”键提供了一个特定的API,描述了提供切换到另一个键盘的方法。系统键盘根据当前文本输入对象的UIKeyboradType特性提供适当的密钥集或布局。例如,在邮件中的“to”字段中插入点时,系统键盘周期密钥更改:当按下并保持该键时,可以从一组顶级域后缀中挑选。像这样设计你的键盘。IOS用户也希望自动大写:在标准文本字段中,区分大小写语言的句子的第一个字母是自动大写的。
下面列出这些特性和其他特性
- 基于键盘类型特征的适当布局和特征
- 自动校正与建议
- 首字母自动大写
- 双击空格插入句号
- 大写锁定
您可以决定是否实现这些特性;没有列出任何列出的功能的专用API,因此提供它们是一个竞争优势。
自定义键盘不可用的系统键盘功能
您的自定义键盘无法访问设置应用程序(设置>通用键盘)中的大多数通用键盘设置,例如自动大写和启用大写锁定。您的键盘也不能访问字典重置功能(设置>通用>重置>重置键盘字典)。为了给用户提供灵活性,创建一个标准设置包,如在IOS设置包中的首选项和设置编程指南中所描述的。然后,您的自定义设置出现在与键盘相关的设置中的键盘区域中。有某些文本输入对象,您的自定义键盘没有资格输入。首先是任何安全的文本输入对象。这样的对象是通过其secureTextEntry属性设置为yes定义的,并通过将类型化的字符表示为点来区分。当用户在安全文本输入时,系统会临时用系统键盘替换您的自定义键盘。当用户在非安全文本输入时,您的键盘会自动恢复。您的自定义键盘也不适合键入所谓的电话簿对象,例如联系人中的电话号码字段。
这些输入对象专门用于由电信运营商指定的一组字母数字字符构成的字符串,并通过具有以下两种键盘类型特征的一种或另一种来标识:
- UIKeyboradTypePhonePad
- UIKeyboradTypeNamePhonePad
当用户在电话盘点击时,系统会临时用适当的标准键盘替换您的键盘。当用户在一个不同的输入对象中点击,通过其类型特征请求一个标准键盘时,你的自定义键盘自动恢复。应用程序开发人员可以选择拒绝在他们的应用程序中使用所有自定义键盘。例如,一个银行应用程序的开发者,或者一个必须符合美国HIPAA隐私规则的开发者,可能会这样做。这样的应用程序遵守UIApplicationDelegate委托协议中的application:shouldAllowExtensionPointIdentifier:方法(返回no),因此总是使用系统键盘。
因为自定义键盘只能在其UIInputViewControoler对象的主视图内绘制,所以无法选择文本。文本选择是在使用键盘的应用程序的控制之下。如果该应用程序提供了编辑菜单界面(如剪切、复制和粘贴),则键盘无法访问它。自定义键盘不能在插入点附近提供内联自动更正控件。自定义键盘,像所有的应用程序扩展在IOS 8,没有访问设备麦克风权限,因此听写输入是不可能的。
最后,不可能在自定义键盘的主视图的顶部边缘显示关键图形,因为系统键盘在iPhone上点击并保持顶部行中的键。
自定义键盘的快速启动
这一节让你快速浏览API来构建键盘。图8-1显示了运行键盘中的一些重要对象,它们来自一个典型的开发流程。
自定义键盘模板(在IOS应用程序扩展“目标模板组”)包含UIInputViewController的子类,该类用作键盘的主视图控制器。该模板还包括“下一个键盘”键的基本实现,它调用类的UIInputViewController的advanceToNextInputMode方法。将对象(如视图、控件和手势识别器)添加到输入视图控制器的主视图(在其输入视图属性中),如图8-1所示。与其他应用程序扩展一样,目标中没有窗口,因此本身也没有根视图控制器。
模板的info.plist预先配置键盘所需的最小值。在键盘目标的info.plist中查看NSExtensionAttributes字典键。在配置自定义键盘的info.plist时,描述了配置键盘的键。
默认情况下,键盘没有网络访问,不能与包含它的应用程序共享内容。若要启用这些操作,请将info.plist中的RequestOpenAccess密钥的值设置为“是”。这样扩展键盘沙盒,是为用户信任而做。
输入视图控制器符合与文本输入对象的内容交互的各种协议:
- 要插入或删除文本响应触摸事件,请使用UIKeyInput协议中的insertText方法和deleteBackward方法。在输入视图控制器的textDocumentProxy属性上调用这些方法,该属性表示当前文本输入对象,并且符合UITextDocumentProxy协议。
- 在使用deleteBackward方法时,若要获取您需要删除多少文本的数据,请从TextDocumentProxy属性的documentContextBeforeInput属性获取插入点附近的文本上下文。你可以删除适当的文本,例如,单个字符,或返回到空白字符的所有内容。要用语义单位删除,如单词、句子或段落,请使用CFStringTokenizer Reference中描述的函数,并参考相关文档。注意,每种语言都有自己的符号化规则。
- 为了控制插入点位置,例如支持在向前方向上的文本删除,请调用UITextDocumentProxy协议的adjustTextPositionByCharacterOffset方法。
- 为了响应活动文本对象内容的变化,或者响应用户发起的插入点位置的变化,使用UITextInputDelegate协议中的方法。若要呈现适用于当前文本输入对象的键盘布局,请响应对象的UIKeyboardType属性。
对于支持的每个特性,相应地更改自己的主视图的内容。为了在自定义键盘中支持多个语言,您有两个选项:
- 每个语言创建一个键盘,每个都作为一个单独的目标添加到一个公共的包含应用程序中。
- 创建一个单一的多语言键盘,动态地切换它的主要语言若要动态切换主语言,请使用UIInputViewController类的primaryLanguage属性。根据你想要支持的语言数量和你想要提供的用户体验,选择最有意义的选项。每个自定义键盘(独立于其RequestOpenAccess键的值)都可以通过UILexicon类访问基本的自动更正词典。利用这个类,连同你自己设计的词典,在用户输入文本时提供建议和自动更正。UILexicon对象包含来自不同来源的单词,包括:
- 用户地址簿数据库中未配对的名字和姓氏
- 在设置> 通用 >键盘>快捷方式列表中定义的文本替换
- 常用词词典
您可以使用自动布局调整自定义键盘的主视图的高度。默认情况下,根据屏幕大小和设备方向,定制键盘的大小与系统键盘匹配。自定义键盘的宽度总是由系统设置为等于当前屏幕宽度。若要调整自定义键盘的高度,请更改其主视图的高度限制。
定制键盘的开发要点
有两点非常重要:
- **信任**。您的自定义键盘使您能够访问用户的类型,因此您和用户之间的信任是必不可少的。
- **切换到下一个键盘**。让用户切换到另一个键盘的功能是键盘用户界面的一部分;您必须在键盘中提供一个。
用户信任的设计
创建自定义键盘时首先考虑的是如何建立和维护用户信任。这种信任取决于您对隐私最佳实践的理解和了解如何实现它们。对于键盘来说,以下三个方面对于建立和维护用户信任尤为重要:
- 输入数据的安全性 用户希望他们的按键转到他们正在键入的文档或文本字段,而不是在服务器上存档或用于不明显的目的。
- 适当和最小化使用其他用户数据 如果您的键盘使用其他用户数据,例如从位置服务或地址簿数据库,您就有责任向用户解释和演示这些好处。
- 准确性 将输入事件转换为文本的准确性本身不是一个隐私问题,但它影响信任:每一个字输入,用户都会看到代码的准确性。
为了设计信任,首先考虑是否请求开放访问。尽管开放式访问使自定义键盘有很多可能,但它也增加了您的职责(见表8-1)。
如果你建立一个键盘,没有打开的访问权限,系统确保击键不能发送回你或任何其他地方。如果你的目标是提供正常的键盘功能,请使用非网络键盘。由于其受限的沙盒,非网络键盘使您在满足苹果的数据隐私指南和获得用户信任。如果启用打开访问(如为自定义键盘配置info.plist所描述的),各种可能性打开,但您的职责也会增加。与开放存取相关联的每个键盘功能都作为开发人员承担责任,如表8-2所示。一般来说,以最大可能的尊重对待用户数据,并且不使用对用户不明显的任何目的。开放存取键盘及其包含的应用程序可以向您的服务器发送击键数据,这使得您可以将计算资源应用于触摸事件处理和输入预测等功能。如果您使用此功能,不要将接收到的击键或语音数据存储在提供给用户的文本所需的时间之外,或提供您向用户解释的功能。在使用开放存取键盘功能时,请参阅表8-2以了解您的额外职责。
提供切换到另一个键盘的方法
当一个以上的键盘被启用时,系统键盘包括一个允许用户切换键盘的地球键(见图8-2)。您的自定义键盘可能需要类似的“下一个键盘”键。要确定您的自定义键盘是否需要显示“下一个键盘”键,请检查输入视图控制器上的needsInputModeSwitchKey属性。如果是真的,你的键盘应该包括这个键。要让系统切换到另一个键盘,请调用UIInputViewController类的advanceToNextInputMode方法。
系统从用户启用的键盘列表中选择合适的“下一个”键盘;没有API来获得启用的键盘列表或选择切换到特定键盘。XCODE自定义键盘模板包括advanceToNextInputMode方法作为下一个键盘键的动作。为了获得最佳用户体验,将你的“下一个键盘”键放在靠近系统键盘位置的同一屏幕位置。
开始编写自定义键盘
在本节中,您将学习如何创建自定义键盘,根据您的目标配置它,并在iOS模拟器或设备上运行它。在替换系统键盘时,您还可以了解一些UI因素。###使用XCODE自定义键盘模板创建键盘及其包含的应用程序的步骤与其他应用程序扩展略有不同。本节介绍如何获得和运行基本键盘。
在包含应用程序中创建自定义键盘
1. 在Xcode中,choose File > New > Project,选择ios application模板中的单例模式
2. 点击next
3. 命名工程,点击next
4. 选定创建位置,点击next
5. 选择 File> New > Target,然后选择Application Extension中的Custom Keyboard 模板,点击next
6. 命名
7. 点击结束
现在可以选择自定义键盘组名称,如在设置中购买的键盘列表中所示,如下所述。
设定键盘组名称
1. 在XCODE项目导航器中,选择包含在App的支持文件文件夹中的应用程序的info.plist。属性列表编辑器打开,显示文件的内容。
2. 将光标悬停在“束名”行上,然后单击出现的“+”按钮。这将创建一个新的空属性列表行并选择它的键字段。
3. 开始键入绑定显示名称,当名称自动完成时,按返回。
4. 在同一行中的值字段中双击以获得一个游标,然后输入所需的键盘组名称。
5. 选择文件>保存以保存对属性列表文件的更改。表8- 3总结了自定义键盘的UI字符串,可以在键盘的info.plist中配置UI及其包含的应用程序。现在,您可以在iOS模拟器或设备上运行基于模板的键盘,以探索其行为和能力。
为自定义键盘配置info.plist文件
特定于自定义键盘的信息属性列表(info.plist文件)键使您静态声明键盘的显著特征,包括其主语言,以及它是否需要打开访问。要检查这些键,请打开一个XCODE项目,其中添加了自定义键盘目标模板。现在在项目导航器中选择info.plist文件(iinfo.plist文件在键盘目标的支持文件文件夹中)。
这些密钥中的每一个都在应用程序扩展键中解释。使用NSExtensionAttributes字典中的键来表示自定义键盘的特性和需求,如下所示:
IsASCIICapable-默认情况为NO,此布尔值表示自定义键盘是否可以将ASCII字符串插入到文档中。如果您提供一个键盘类型专门用于UIKeyboardTypeASCIICapable键盘类型的特性,则将该值设置为YES。
PrefersRightToleft-默认情况为NO,该布尔值也表示自定义键盘是否为右到左语言。如果键盘的主语言从右到左,将此值设置为YES。
primaryLanguage -这个字符串值,en-us(默认为美国英语)使用模式-表示键盘的主要语言。
RequestOpenAccess-默认情况为NO,此布尔值表示自定义键盘是否希望将沙盒扩大到基本键盘所需的范围之外。如果您通过将该键的值设置为YES,请求打开访问,则您的键盘将获得以下功能,每个功能在用户信任方面具有伴随的责任:
- 访问位置服务、地址簿数据库和相机滚动,每个用户需要在第一次访问时允许
- 选择使用包含键盘的应用程序的共享容器,它可以在包含应用程序的应用程序中提供自定义的词典管理UI
- 能够通过网络发送击键、其他输入事件和数据来进行服务器端处理
- 使用UIPastedboard
- 播放音频的能力,包括使用playInputClick方法点击键盘
- 访问iCloud,您可以使用它,例如,确保键盘设置和自定义自动更正词典在用户拥有的所有设备上都是最新的
- 通过包含应用程序访问游戏中心和应用程序购买
- 如果设计了支持移动设备管理的键盘(MDM),则可以使用托管应用程序
在考虑是否将RequestOpenAccess密钥的值设置为YES时,请务必阅读用户信任的设计,它描述了您尊重和保护用户数据的职责。