大多数浏览器和
Developer App 均支持流媒体播放。
-
了解 iPad 的随手写功能
“随手写”功能借助 Apple Pencil 为 iPad 文字输入提供了一种轻巧、有趣且符合人体工程学的途径。探索用户可以怎样在app中运用“随手写”功能以及手写文本,手写文本既可使用标准文字输入控制,也可创造个性化文字输入体验。你将了解该功能与TextKit相融合的方式,以及何时应用新的 UIScribbleInteraction 和 UIIndirectScribbleInteraction 两大 API 为你的 app 创造令人愉悦且持续流畅的随手写体验。 若想充分掌握本章节,需先熟悉 UIKit 文本输入控制,以及键盘输入技术。初次接触者,请先观看“iOS 的键盘输入”部分。若准备搭建个性化文本编辑器,须先熟悉 UITextInput 协议、TextKit,以及相关文本输入API。若想获取更多信息,建议查看“TextKit 最佳实践”以及“带来更好文本输入体验的关键”若要设计基于触控笔的互动指导,请查看“Apple Pencil 设计须知”。
资源
相关视频
WWDC20
-
下载
你好 欢迎来到全球开发者大会 (认识一下 iPad 的涂文字) 欢迎来到《认识一下 iPad 的涂文字》 我叫 Daniel Gobera 我是 Pencil and Paper 团队的工程师 稍后我的同事 Evan Long 会在我后面发言 涂文字是在 iPad上 通过手写识别用 Apple Pencil 输入文本的奇妙新方式 在本视频中 我们会看到 涂文字工作原理的概述 我们来看看哪些方面 能使你有美好的书写体验 我们会查看支持涂文字的 API 最后 我们会看到一些 关于如何自定义涂文字行为的例子 以便你在 app 中获得最佳体验 在将涂文字引入 iPad 时 我们希望大干一场 以 Apple Pencil 为中心 涂文字被深入整合到系统中 也就是说你可以 直接在任何文本框内书写 而不是在单独的书写区域 (在任何文本框书写) 转录在你书写过程中动态地发生 没有模式 没有点击 就只是书写 iPadOS 上的涂文字是系统体验的一部分 也就是说在默认情况下 所有 app 都可以使用它 就像键盘一样 它可以用于任何可以输入文本的地方 它构建在一流的快速手写识别引擎之上 它非常准确 并且完全在设备上运行 因此它随时可用 而且完全私密
它能识别手写的英文 简体、繁体中文和粤语 让我们来看看 构成美好书写体验的各个方面的概述 这会给你一套指南 以确保你的 app 获得最佳涂文字体验
第一个重要方面是 涂文字使键入文本更流畅、更轻松 这里我们看到一个在地图中搜索的例子 注意你可以直接开始书写 而无需先点击字段 如果你注意到 app 中有任何文本框 不支持直接用涂文字书写 必须先点击文本框 则你应该采用我们稍后将展示的 API 涂文字很直接 意思是 Pencil 的位置 告诉系统文本应插入的位置 我们现在看到的是在 Safari 浏览器中 填写有多个字段的表单的例子 注意你如何能轻松地 从一个字段跳到另一个字段 笔划转瞬即逝 因为转录在你书写过程中动态地发生 感觉就像是在用动作口述
第二个设计原则是一致性 涂文字需要在任何 你希望能输入文本的地方运作 这里我们看到一个提醒事项中的例子 列表中的每一项 都包含通常可以编辑的文本 因此很自然你可以 开始在任何一项上书写 我们注意到一些人觉得 在列表下方的空白区域书写 以创建新条目很自然 这通常不是文本键入视图 因此提醒事项采用了 我们稍后将说明的 API 以允许在该区域书写 这创造了一种 轻松添加新提醒事项的好方法 还有一小组 人们只需要学一次的编辑手势 它们在任何能用涂文字编辑文本的地方的 工作方式都完全相同 我们可以看到一个编写电子邮件的例子 你可以画一条水平线来选取文本 进行常规文本编辑操作 你还可以划掉一些想删除的文本 所有这些加起来 创建了一个可靠且熟悉的交互模型 我们最终的设计原则是适合 Pencil iOS 用户界面主要是为 Touch 而设计 它真的很适合 Pencil 输入 但你会注意到 我们在几个地方进行了一些调整 我想强调其中的一些调整 让我们从减少干扰开始 我们在这里看到的一个很好的例子 是文本框中的占位符 当你开始在有占位符的字段书写时 它会消失以避免与笔划重叠 这使字迹清晰可辨 通过标准文本控件可自动获得该行为
稳定的布局意味着文本框和里面的文本 在你书写时不应该移动或滚动 举例来说 你可能知道一些搜索框 在聚焦时往往会改变位置 这对键盘而言很好 但在你试图用 Pencil 在里面书写时 这可能是个问题
你在移动的搜索字段上书写时 涂文字会检测到 它会等你停下来 才做出第一个响应 并插入文本 如果使用标准搜索控制器 则可以自动获得该行为 但如果你的自定义字段有类似的移动动画 你需要告诉涂文字这一点 而且你可以要求延迟对该字段聚焦 以采用相同的行为
始终有足够的空间来书写也很重要 一个好例子是消息 app 你会注意到屏幕角落附近的消息框 空间真的不多 只能写几个字
消息检测到你在用涂文字 于是它调整了输入框的大小 写更长的句子就轻松多了
我们知道很多 app 有类似的布局 尤其是即时通讯 app 我们建议你通过我们稍后会展示的 API 应用相同的行为 (提供支持的 API) 让我们看看支持涂文字的 API 的概况 一些现有的 以及一些新的
涂文字依赖于 iOS 现有的文本键入 API 标准文本控件 以及 UIKit 文本键入基础架构 我们还将在 iOS 14 中引入两个新的 API 允许自定义涂文字的行为
我们先来谈谈现有的文本键入 API 标准文本控件诸如文本框、文本视图 以及可从 UIKit 获得的搜索框 它还包括标准可编辑 web 内容 通过 WebKit 访问的网页中的表单 好消息是所有这些都是现成的 而且它们与涂文字很兼容 我们建议你尽量用这些 而且它们高度可定制 可适应你的 app 的外观和感觉 值得注意的是 涂文字不支持密码框 因为建议通过自动填充输入密码 接下来是 UIKit 文本键入基础架构 如果你有自定义文本编辑经验 则有一套必须实现的协议 使你的视图可以使用 键盘和 iOS 文本键入系统
涂文字依赖相同的 API 与文本视图进行对话
良好彻底地 实现 UITextInput 尤为重要
这是涂文字获取有关文本内容 选项的信息的方式 以及它将如何更改视图中的文本
我们还建议你用 UITextInteraction 从系统获取标准光标和选择用户界面 这样你就不必实现你自己的 如果你对这些话题的更多详情感兴趣 请查看 2012 年和 2017 年 全球开发者大会的精彩演讲 现在 Evan 将向我们概述如何用新的 API 在你的 app 中自定义涂文字的行为 谢谢 Daniel 正如 Daniel 提到的 在使用标准 UIKit 文本控件时 涂文字会正常运作 但在有些情况下 可能需要自定义涂文字体验 要支持这些自定义 我们在 iOS 14 中 引入了 UIScribbleInteraction 和 UIIndirectScribbleInteraction
首先是 UIScribbleInteraction
交互被添加到视图 在这里 我们向文本框添加了 UIScribbleInteraction
交互有一个代理 这个代理是 app 可以 自定义涂文字体验的地方
例如 在视图上禁用涂文字 推迟该视图成为第一响应者 直到手写暂时停止 或只是在涂文字手写开始 或结束时接到通知 现在让我们来看看如何使用 UIScribbleInteraction 的一些实际案例 一些 app 添加了在线完成字段 例如 聚焦的搜索字段 这对键盘输入很有用 但会在视觉上干扰手写
通过使用先前添加到该字段的 UIScribbleInteraction 可以检查视图当前是否在处理手写 并相应地更新完成文本 在这种情况下 通过隐藏它 要优化涂文字的用户界面布局 我们需要知道手写是否可能 或者是否已经完成
其中一个地方是在用户界面的 初始外观或设置中 在这里 app 使用 UIScribbleInteraction 的类属性 isPencilInputExpected 当属性为“真”时 app 使文本区域变大一些
而不是作为视图设置的一部分 更改用户界面 在用户通过代理方式 scribbleInteractionDidFinishWriting 完成书写后 它还可以对其进行更新 得注意的是 在我们刚刚看到的两种方式中 当用户不在书写时 用户界面更改了 一些 app 混合绘图和可编辑文本 在这种情况下 可以禁用涂文字以允许绘图 这可以通过 ScribbleInteraction 的 shouldBeginAt 代理方式实现 通过在 app 处于绘图模式时返回“假”
现在我们来看看 UIIndirectScribbleInteraction
正如 UIScribbleInteraction UIIndirectScribbleInteraction 也添加到视图 该交互用于提醒事项 允许在当前提醒事项列表下书写 以创建新的提醒事项
这也是用于用户界面的交互 会回应点击手势 变为可编辑
而且该交互有一个代理 该代理提供有关元素的系统信息 元素是视图中可以写入的区域 可以有多个元素 而且元素的大小可能会有所不同 让我们更深入地了解一下在示例 app 中 如何使用 UIIndirectScribbleInteraction
我们的示例 app 允许在笔记本电脑背面添加雕刻 该雕刻元素只有在点击后才可编辑 我可以用手指点击 建立了一个成为第一响应者的文本框 我可以输入我的名字 但如果我删除文本 试着用 Apple Pencil 书写却不起作用 这是因为雕刻字段本身 不是可编辑的文本键入 让我们添加 UIIndirectScribbleInteraction 以便在涂文字中实现这一点
要将雕刻区域字段显示为可写区域 我们安装 UIIndirectScribbleInteraction
接下来我们需要实现 说明可写区域的代理方式
首先要实现 为所有可写元素 提供标识符列表的代理方式
在这种情况下 雕刻字段只有一个可写区域 我们可以用标识符立即调用完成处理程序 接下来 我们需要提供 关于元素位置的系统信息
这通过 frameForElement 代理方式实现 可返回可以写入的较小区域 但我们希望允许写入整个视图 因此在这种情况下 我们只返回边界
接下来 我们需要处理 系统要求我们聚焦 支持文本键入的响应者的情况 这通过 focusElementIfNeeded 方式实现
如果未建立文本框 我们会创建它 并将其添加至视图层次结构 然后我们会确保建立的文本框 成为第一响应者
最后 用完成处理程序返回该文本框
系统所需的最后一条信息是 标示某个特定元素是否被聚焦
在这种情况下 我们只有一个字段 如果我们有一个字段 而且它是第一响应者 我们将返回“真” 否则 我们将始终返回“假”
如果我试着在雕刻区域写我的名字 我可以做到
再回顾一下支持涂文字的 API 来自 UIKit 和 WebKit 的系统中的 标准文本控件就可以 涂文字也适用于实现文本键入协议的 自定义文本编辑器 要自定义涂文字 这通过在 iOS 14 中添加的两个交互完成 拿起 Pencil 用涂文字测试你的 app 看看你如何符合我们前面介绍的设计原则 并用标准文本控件 自动获得大多数这些行为 将这些涂文字交互应用于最后的润色 比如创造书写空间 和允许在预期的地方使用涂文字 感谢观看 我们期待你的 app 在 iOS 14 中取得成功 (2020 全球开发者大会)
-
-
9:15 - isHandlingWriting Example
func updateSearchCompletion() { customSearchField.hideCompletionText = interaction.isHandlingWriting }
-
9:35 - UIScribbleInteraction.isPencilInputExpected
override func viewDidAppear(_ animated: Bool) { if UIScribbleInteraction.isPencilInputExpected { let lineHeight = textField.font?.lineHeight ?? 17.0 let heightForScribble = lineHeight * 4.0 heightConstraint.constant = heightForScribble } }
-
9:51 - scribbleInteractionDidFinishWriting
func scribbleInteractionDidFinishWriting(_ interaction: UIScribbleInteraction) { let lineHeight = textField.font?.lineHeight ?? 17.0 let heightForScribble = lineHeight * 4.0 heightConstraint.constant = heightForScribble }
-
10:08 - Should Begin
func scribbleInteraction(_ interaction: UIScribbleInteraction, shouldBeginAt location: CGPoint) -> Bool { return !appIsInDrawingMode() }
-
11:41 - Install UIIndirectScribbleInteraction in Engraving Field
override init(frame: CGRect) { super.init(frame: frame) indirectScribbleInteraction = UIIndirectScribbleInteraction(delegate: self) addInteraction(indirectScribbleInteraction) ... }
-
11:48 - Request Elements
func indirectScribbleInteraction(_ interaction: UIInteraction, requestElementsIn rect: CGRect, completion: @escaping ([ElementIdentifier]) -> Void) { completion(["EngravingIdentifier"]) }
-
12:14 - Frame for element
func indirectScribbleInteraction(_ interaction: UIInteraction, frameForElement elementIdentifier: String) -> CGRect { return bounds }
-
12:28 - Focus Element if Needed
func indirectScribbleInteraction(_ interaction: UIInteraction, focusElementIfNeeded elementIdentifier: String, referencePoint focusReferencePoint: CGPoint, completion: @escaping ((UIResponder & UITextInput)?) -> Void) { if editingTextField == nil { createTextField() } editingTextField?.becomeFirstResponder() completion(editingTextField) }
-
12:57 - Is Element Focused
func indirectScribbleInteraction(_ interaction: UIInteraction, isElementFocused elementIdentifier: String) -> Bool { // Indicate if our only element is currently installed and focused return editingTextField?.isFirstResponder ?? false }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。