大多数浏览器和
Developer App 均支持流媒体播放。
-
使用 iOS 的选择器 菜单和操作进行构建
使用流畅的界面和易于访问的上下文信息构建 iPhone 和 iPad app。 我们将向你展示如何将最新的 UIKit 控件集成到你的 app 中,从而最好地利用菜单、日期选择器,页面控件和分段控制器。 了解如何在整个用户界面中采用菜单,并了解 UIAction 如何协助统一你的事件处理。 了解这些新控件后,请观看“ UIKit设计的新功能”,从而了解如何使用这些工具和 API 设计出色的界面。
资源
相关视频
WWDC20
-
下载
(你好 WWDC 2020)
你好 欢迎来到 WWDC (使用 IOS 的选择器 菜单和操作进行构建) 你好 欢迎来到本期节目 我是 UIKit 团队的工程师 Eric Dudiak David Duncan 将和我一起参与本期节目 我们将讨论 UIKit 一些出色的新功能 重点是讨论标准控件和菜单 那我们开始吧 下面是我们本节内容的 简短概述 我们将简要介绍一下控件外观的最新变化 之后 我们将介绍 新型颜色选取器及其使用方法 然后我们会介绍更新后的日期选择器 我们也会介绍菜单变化以及它新增的选项 最后 我们会介绍 UIActions 上的改进之处 这些改进可以大大简化你的代码
那么 我们从一些常见控件的外观更新开始介绍 这些更新适用于 iOS 和 iPadOS 包括 UIKit 和他们的 SwiftUI 对应控件
我们对 UISlider 和 UIProgressView 都进行了小的更新 以使其在所有平台上更加一致
首先 你会看到轨道厚度有所增加 这使得其外观更符合 macOS 的要求 除了外观上的变化 UISlider 现在还采用了macOS 的行为 即可以点击或轻点轨道以调整数值
在这里我们可以看到 UIProgressView 上与之匹配的视觉变化
当在优化的 Catalyst app 中 使用这些和其他 UIKit 控件时 他们会进一步采用 macOS 的外观 这种进一步采用行为 将使这些控件的部分自定义 API 受限 并且这些 API 不会发挥任何作用 有关开发优化 Catalyst app 时 注意事项的更多信息 请查看 “优化你的 Mac Catalyst App 界面”一节
另一个在外观上有所更新的控件是 UIActivityIndicatorView 新设计的特点是减少了踏板 而且在所有尺寸上都是一致的 同时在动画上也做了一些时间上的调整 现在 重要的是 当显示不确定的进度时 请始终使用内置的 UIActivityIndicatorView 这可保证一致性 现在 要确保 它在所有可能的情况下都能正常工作 请使用适合深色模式的现代样式 并允许选择通过 API 设置自定义颜色
我们在 pulltorefresh 控件中 也进行了类似的外观更改
而在这里 我们看到了 这些控件和其他一些标准控件的 优化 Mac Catalyst 版本 请注意 它们与标准 Mac 控件的外观一致
我们对 UIPickerView 也进行了外观更改 然而 应该指出的是 在很多情况下 菜单可能是一个合适的替代品 我们会在本节稍后部分讨论这些问题 在 macOS 上的 Catalyst app 上 当你要从多个选择中呈现一个选择时 菜单几乎总是最好的选择
最后我们要介绍的控件是 UIPageControl 现在 它的外观和功能 都发生了变化 新的外观允许页面控件在固定的尺寸内 支持无限量的 pages 文稿
现在 当 pages 文稿数量超过可用空间时 控件允许对这些界面进行清理和滚动 这使得该控件更适用于 用户自定义时可能指定了 pages 文稿数量的情况 比如在主屏幕上 此外 该页面控件具有新的 API 以自定义其外观
现在 无论是单个页面还是所有页面 指示器都可以设置为自定义图像 如果某个页面具有特殊的功能 这个功能就非常有用 比如这里显示的 Weather app 中的首页 它会显示天气的当前定位图标
我们也可以自定义 控件的显示方式和交互方式 比如 当控件是界面的主要控件时 可以将其设置为以更突出的模式显示 让我们一起看看如何使用这些自定义功能 我们在这里继续创建 pageControl
我们可以 将 backgroundStyle 设置为突出 这样它在我们的 app 中就显得更加突出 这将使背景区域可以一直显示 而不是只在我们与它交互时显示
如果我们不希望指示器是常规的圆圈 我们也可以为所有指示器设置默认图像 在本例中 可以为我们正在浏览的书签页面 设置书签图像
我们还可以进一步 对单个 pages 文稿进行自定义 这里我们是用首页的心形图像 来表示它是收藏列表中的 pageControl 的所有其他 API 表面完全没有发生变化
接下来 我们来看看 iOS 14 中的新型颜色选取器
对于已熟悉 macOS 颜色面板的用户而言 iPadOS 和 iOS 14 中的 新型颜色选取器感觉非常相似 颜色选取器是一个视图控制器 它可以很容易地从你的 app 中 以工作表或弹出框形式呈现出来 除了典型的代理回调外 它还有一个颜色属性 可以设置和读取以进行配置 如果呈现出来 它允许通过多种不同的方法来选择颜色 例如从网格中挑选...
从整个光谱梯度中选择一种颜色 或手动指定 带有红色、绿色和蓝色的那种颜色 或者甚至是一个 16 位进制代码 我们可以收藏常用颜色 并在 app 之间重复使用 所以 Pro App 允许用户轻松选择重要的东西 比如某种颜色、在一种情况下 以及在多种情况下使用 最后 和 macOS 面板一样 颜色选取器支持使用滴管器 从屏幕中任意处抓取颜色
当在 iPadOS 上运行多个 app 时 这个功能尤其强大 可以在屏幕上的任何地方轻松选择颜色 进行匹配然后重新使用
在 macOS 中 选择器使用标准颜色选择器面板 这允许使用相同的常见功能
让我们来看看如何设置和使用颜色选取器 在本例中 我们现有的 viewController 上 有一个 ColorPickerViewController 属性 当按下颜色按钮时 我们继续将 viewController 上的颜色 设置为当前使用的颜色 然后显示 ColorPickerViewController
如果用户完成了颜色选择 我们就继续在 app 中进行设置
如果用户撤消了颜色选择 我们可以放心地忽略这一颜色 在任何时候 我们都不用担心颜色是如何选取的 或是如何支持滴管器的 所有这些都由颜色选取器自动处理
虽然 iOS 和 iPadOS 中的 日期选择器并不是新控件 但是我们对它的通用性和用户体验 做了一些非常大的改进
iPadOS 和 iOS 新推出并支持 精简样式 就像之前介绍的 macOS 版本一样 iOS 中的精简样式 将时间和日期显示为字段 可以点击这些字段进行模式选择
当用户界面中的空间有限时 此功能特别有用 比如在有多个字段的表格视图或表单中 从日期一侧进行选择时 将显示日历模式 可以轻松选择任何给定日期
相比于传统的滚轮样式 这使得远期日期的选择更加快速 并且更好地优化了 iPad 上的光标交互 当轻点时间时 键盘就可以用来选择时间
正如前面所述 macOS Catalina 和之后的 iOS 13.4 SDK 及其更新版 都支持精简样式 这有助于你已优化 或未优化的 Catalyst app 更好地支持在 Mac 上显示日期选择器 使用日历模式时 日期选择器控件的大小类似于 UILabel 单击日期的组件 会显示一个用于选择日期的日历模式 还可以通过在字段中 输入值来设置日期和时间 此外 如果在给定的情境中 只需要时间或只需要日期 app 可以将选择器限制为仅该字段的部分 此外 iOS 14 推出了日期选择器的内联样式 在选择日期是用户界面的主要功能 并且根本不需要添加模式步骤的情况下 这一功能特别有用 这对于从滚轮样式迁移到 更多屏幕空间的 iPad app 特别有用
这种呈现方式本身 与精简样式中所呈现的模式一致 只是它填充了控件中的内容 而不是在控件中呈现出来
这三种新样式最大的优点是 UIDatePicker 的所有 API 都保持不变 所以 新的样式可以很容易地 根据不同情况进行采用甚至调整 只有 app 的布局会受影响 让我们看看如何使用这些新样式吧 在这里 我们看到 创建日期选择器并设置初始日期 在 iOS 14 中完全没有任何改变 我们还可以为选择设置最近和最远日期 要使用新的样式 我们要做的就是设置首选样式 在这里我们将其设置为精简样式
如果需要 我们还可以 自定义日期选择器的区域和日历 新样式会显示相应的内容 在本例中 我们将显示日本的日历 我们可以看到 现在的年份 是如何显示在之前年份显示的地方的
如果这种情况与时间无关 我们还可以将选择仅限为日期
日期选择器仍然只是一个 UIControl 所以 当值发生变化时 它很容易就得到通知 然后读取新的日期 当用户在 app 中选择日期时 新的日期选择器样式 为其提供了更好的使用体验 并且 app 无需处理 许多不同日历或跨平台交互的固有复杂性
现在 将由我的同事 David Duncan 来为大家介绍 谢谢 Eric 我是 David Duncan 我将讨论菜单和 UIAction 的改善之处 让我们先来了解一下 iOS 是如何将快速、轻量级的菜单交互 运用到 UI 的更多地方 iOS 14 中任何 app 都可轻松将菜单添加 至 UIButtons 和 UIBarButtonItems
这个例子展示了 Safari 浏览器是如何 使用菜单以让你的指尖拥有更多力量 让我们深入了解一下这种交互
轻点标签切换按钮会执行默认操作 显示 Safari 浏览器标签切换器
在 iOS 14 中 长按此按钮 将显示包含更多选项的菜单 你可以立即滑动手指选择某一项 抬起手指后将激活此项
让我们看看 如何在你的 app 中添加此类菜单
UIButton 和 UIBarButtonItem 可直接支持菜单 添加菜单就再简单不过了 只需将菜单分配给任一类菜单属性 然后 UIKit 将负责在长按时显示此菜单 但是在某些情况下 你不想等待 让我们看看这个交互 (提醒 带些零食) 提醒事项使用 More 按钮 将几个动作组合在一起 不同于我们 Safari 浏览器的例子 当你触碰该按钮时 这一菜单会立即显示 和之前一样 用户可以滑动手指 并以流畅的手势快速选择一个动作 在 UIButton 和 UIBarButtonItem 中 选择这种交互的方式有所不同 对于 UIButton 将 showsMenuAsPrimaryAction 设置为 true 会使按钮在触碰时立即显示其菜单
对于 UIBarButtonItem 提供菜单但不设置首要动作 表示菜单应在触碰时显示 (触感触碰 快速 - 缓慢) 在 iOS 14 中 你还会看到 由导航栏 Back 按钮自动提供的菜单
该菜单创建了一个标准加速器 这可以在任何 app 中跳回至导航堆栈中
考虑到适当情况下的自定义后退按钮 菜单标题会自动进行选择
如果你使用自定义标题视图 但没有设置导航项的标题 请考虑设置 backButtonTitle 以保证良好的用户体验
到目前为止 你所看到的 新的菜单支持是由 UIControl 提供的
你已经看到了 showsMenuAsPrimaryAction 它决定了是长按还是触碰以触发菜单
UIControl 提供了对其 contextMenuInteraction 的访问渠道 以及启用该交互的属性 为了支持自定义的基于菜单的用户界面 你可以将 UIControl 编入子集 将 ContextMenuInteractionDelegate 的实现进行覆盖
要在菜单手势被识别时采取行动 你可以注册 menuActionTriggered 控件事件 现在让我们看看菜单中强大的新功能 以补充你可以使用它们的新地方 (用户界面延迟菜单元素) UIDeferredMenuElement 增加了异步提供菜单项的能力
正如我们的例子显示的那样 UIKit 在等待提供最终的菜单项时 会呈现一个标准的加载用户界面
这些项在提供后会被缓存起来 以便再次显示菜单 UIDeferredMenuElement 对于生成复杂的菜单也很有用 因为这些项只有在显示时才需要 接下来 让我们重点看下 UIContext- MenuInteraction 的两大新功能
UpdateVisibleMenu 允许你更新 当前呈现给用户的菜单 你会收到该菜单的副本 并返回一个菜单以代替它
为了使这个 API 超级易用 UIMenu 更改了行为 不再强制其子代为不可更改 允许你更新和返回传递给你区块的菜单 而不是创建一个新的菜单 现在 UIContextMenuInteraction 提供了对交互外观的查询功能 当显示预览时 该属性可能会返回丰富 对于仅菜单的交互 此属性可能会返回精简或者全无 虽然控件总是使用精简的外观 但你的交互可能会 根据触发方式显示丰富或精简 这就是 iOS 中的一些新功能 可以为菜单带来更多的功能 接下来 让我们看看 UIAction 的是如何改进 以让用户输入的操作比以往更容易 在 iOS 13 中 UIKi 推出了 UIAction 使共享事件处理代码变得更加容易 如需复习 请参见 WWDC 2019 中的 “为 iOS 13 更新你的用户界面”部分 iOS 14 扩展了你在 app 中 可以使用 UIAction 的地方和方式
UIBarButtonItem 增加了新的 初始化表达式来创建带有动作和菜单的项 他们让你可以轻松地创建 对轻点、当前菜单 或两者都有反应的 BarButtonItems 而且几乎每一个参数都是可选的 所以你只需要指定那些你需要的参数 让我们一起看一下
这里我们使用 iOS 14 中的新 API 来配置 viewController 的工具条项
首先 我们创建一个系统项 轻点该项会触发一个动作 长按则会触发一个菜单
接下来 我们使用新 fixedSpacewidth API 来添加一个 fixedSpace
然后我们添加一个自定义项 配置为在触碰时显示图像和呈现菜单
现在 使用新的 API 添加一个 flexibleSpace
最后 一个项将使用 primaryAction 的标题或图像 并在轻点时触发处理程序 和 BarButtonItems 一样 所有控件都可以用 UIAction 进行构造 但是有两个控件 UIButton 和 UISegmentedControl 还有另外的行为
UIButton 增加了一个新的初始化表达式 在接受 UIAction 的同时接受按钮类型
类型默认为 system 并且 primary action 的标题和图像 在适当的时候用于配置按钮
和其他用 primaryAction 创建的控件一样 该动作被注册来处理 primaryActionTriggered 控件事件 这导致轻点按钮时 动作处理程序被调用
在我们讨论 Segmented Control 对 UIAction 的支持之前 让我们看看在 iOS 14 之前 你如何进行配置
首先 使用字符串数组创建控件 接下来 添加 位于代码其他位置的处理程序以调用方法 然后 该方法必须假定映射可能更改 从而切换到选定的段 并且当映射确实发生更改时 编译器无法帮助你发现问题 iOS 14 让这一切变得更加简单
通过 UIAction 创建分段控件的过程是这样的 使用 UIAction 数组创建控件 每个数组定义一个段的标题或图像
但和之前不同的是 我们不需要添加一个事件处理程序 当该段被选中时 UIKit 会自动调用动作的处理程序 而且只调用该段
不再需要 switch 语句 不需尝试捕捉问题的默认情况 处理程序就在控件创建的旁边 而且编译器可以帮助我们 保持配置和对用户输入的响应同步
这里我们使用一个枚举来生成动作 这意味着 我们可以只添加一个新的枚举案例 我们的分段控件的行为就会自动更新
而且你仍然可以 将其与控件事件处理相结合 达到两全其美的效果
UISegmentedControl 通过一个新的 初始化表达式以开始对 UIAction 的采用 并增加了新的方法 来添加、删除、更新和查找段 正如我们已经看到的那样 与 UIAction 相关联的段 只有在被选中时 才会调用该动作的处理程序
iOS 14 有很多东西可以改善 iPhone、iPad 和 Mac Catalyst 的 app 通过利用库存控件上的新外观 UIPageControl 上的新可自定义性 以及 UIDatePicker 的新样式 来更新用户界面 (更新你的用户界面) 采用 ColorPickerController 来满足你的所有颜色选择需求 使你的用户可以轻松地 选择任何他们能看到的颜色 通过菜单让用户可以 更简单、更快捷地使用你的 app 通过手指的快速滑动即可开始任何任务
通过确保后退按钮菜单的清晰和正确 以支持在你的 app 中实现快速导航
并在 UIAction 上采取行动 简化和分享处理用户输入的代码 我迫不及待地想看到你如何改善你的 app 感谢观看
-
-
4:34 - UIPageControl example
let pageControl = UIPageControl() pageControl.numberOfPages = 5 pageControl.backgroundStyle = .prominent pageControl.preferredIndicatorImage = UIImage(systemName: "bookmark.fill") pageControl.setIndicatorImage( UIImage(systemName: "heart.fill"), forPage: 0)
-
6:56 - UIColorPickerViewController example
var color = UIColor.blue var colorPicker = UIColorPickerViewController() func pickColor() { colorPicker.supportsAlpha = true colorPicker.selectedColor = color self.present(colorPicker, animated: true, completion: nil) } func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) { color = viewController.selectedColor } func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) { // Do nothing }
-
10:04 - UIDatePicker example
let datePicker = UIDatePicker() datePicker.date = Date(timeIntervalSinceReferenceDate: timeInterval) datePicker.preferredDatePickerStyle = .compact datePicker.calendar = Calendar(identifier: .japanese) datePicker.datePickerMode = .date datePicker.addTarget(self, action: #selector(dateSet), for: .valueChanged)
-
14:20 - UIDeferredMenuElement example
button.menu = UIMenu(title: "", children: [ UIMenu(title: "", options: .displayInline, children: (1...2).map { UIAction(title: "Static Item \($0)") { action in }}), UIDeferredMenuElement({ completion in DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { completion([UIMenu(title: "", options: .displayInline, children: (1...2).map { UIAction(title: "Dynamic Item \($0)") { action in }})]) } }), ])
-
14:50 - updateVisibleMenu example
self.contextMenuInteraction.updateVisibleMenu { currentMenu -> UIMenu in currentMenu.children.forEach { element in guard let action = element as? UIAction else { return } action.state = Bool.random() ? .off : .on action.attributes = Bool.random() ? [.hidden] : [] } return currentMenu }
-
16:05 - UIBarButtonItem example
let saveAction = UIAction(title: "") { action in } let saveMenu = UIMenu(title: "", children: [ UIAction(title: "Copy", image: UIImage(systemName: "doc.on.doc")) { action in }, UIAction(title: "Rename", image: UIImage(systemName: "pencil")) { action in }, UIAction(title: "Duplicate", image: UIImage(systemName: "plus.square.on.square")) { action in }, UIAction(title: "Move", image: UIImage(systemName: "folder")) { action in }, ]) let optionsImage = UIImage(systemName: "ellipsis.circle") let optionsMenu = UIMenu(title: "", children: [ UIAction(title: "Info", image: UIImage(systemName: "info.circle")) { action in }, UIAction(title: "Share", image: UIImage(systemName: "square.and.arrow.up")) { action in }, UIAction(title: "Collaborate", image: UIImage(systemName: "person.crop.circle.badge.plus")) { action in }, ]) let revertAction = UIAction(title: "Revert") { action in } self.toolbarItems = [ UIBarButtonItem(systemItem: .save, primaryAction: saveAction, menu: saveMenu), .fixedSpace(width:20.0), UIBarButtonItem(image: optionsImage, menu: optionsMenu), .flexibleSpace(), UIBarButtonItem(primaryAction: revertAction), ]
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。