大多数浏览器和
Developer App 均支持流媒体播放。
-
小组件的新位置
小组件生态系统正不断扩展:了解如何使用最新版 WidgetKit API 让你的 App 在所有地方保持出色的外观。我们将向你展示如何识别小组件的背景、动态调整布局以及为生动渲染准备颜色,从而让你的小组件可以与任何环境无缝融合。
章节
- 0:00 - Introduction
- 1:44 - Transition to content margins
- 3:00 - Add a removable background
- 4:31 - Dynamically adjust layout
- 6:00 - Prepare for vibrant rendering
资源
相关视频
WWDC23
WWDC22
-
下载
♪ ♪
Kathryn:大家好 我是 Kathryn 一名 System Experience 的工程师 今天我将谈谈小组件的新位置 以及如何轻松优化小组件 从而使其 在所有地方都可以保持出色的外观 首先 我们先来快速回顾一下 小组件的历史 iOS 14 在主屏幕上引入了小组件 iOS 16 使用了同一个简单的 WidgetKit API 在锁定屏幕上引入了小组件 今年 小组件生态系统将扩展到 四个新位置: Mac 桌面 iPad 锁定屏幕 iPhone 新待机模式 以及 Apple Watch 新智能叠放 这就意味着用户将在更多位置 看到他们最喜欢的小组件 由于你的小组件也会自动出现在 这些位置 因此 确保其在任何位置 都可以保持外观精美尤为重要 得益于 Mac 对 iPhone 小组件的支持 即便你当前没有 macOS App 你也可以在 Mac 上使用小组件 我的朋友 Devon 和 Graham 曾经邀请我帮助他们 更新 Emoji Rangers 的小组件 以使其可以出现在这些新位置 你可能还记得 WWDC20 中的 “小组件‘边看边写’” 以及 WWDC22 中的 “复杂功能和小组件:重新加载” 首先 我们会谈谈小组件新的内容外边距 以及 如何在 Apple Watch 上 向其进行过渡 接着 我们会为小组件添加 可以自动移除的背景 然后 我们会对小组件进行修改 使其能够根据环境 动态扩展布局 最后 我们会确保小组件中的元素 均为生动渲染做好了准备 我们这就开始吧 今年 小组件推出的新功能是 内容外边距 内容外边距是自动应用于 小组件主体的填充 用来防止你的内容 过于接近小组件容器的边缘 该外边距的大小 取决于小组件显示的环境 在 watchOS 9 及更低版本上 小组件使用系统定义的安全区域 从而防止内容太过接近边缘 小组件可以通过向视图 添加类似 ignoresSafeArea 的 修饰符 从而延伸到安全区域之外 在 watchOS 10 及更高版本上 小组件中的安全区域 被内容外边距取代 这就意味着 类似于 ignoresSafeArea 的修饰符 不再对小组件产生影响 对于大多数小组件而言 该更改并不会影响其外观 但如果你的小组件中 存在过去忽视安全区域的内容 通过将 contentMarginsDisabled 修饰符添加到小组件配置中 你仍然可以实现相同的效果 其次 对于应保留在 默认内容外边距内部的内容 只需添加 padding 即可 你可以使用 widgetContentMargins 环境变量 获取当前环境默认的外边距 内容外边距以及这些新修饰符和变量 在所有 显示小组件的平台上均可使用 现在 我们来为 Emoji Rangers 小组件添加可移除背景 就和在 iPhone 上工作一样 小组件现有的配件系列也可以自动在 iPad 锁定屏幕上工作 并且 iPad 还可以在其旁边 显示 systemSmall 小组件 这就是小组件在锁定屏幕上的样子 在该环境中 我们需要去除其背景 以使其与其他小组件更加搭配 幸运的是 这样做十分简单 这里是 systemSmall 小组件 视图的代码 可以看到 该代码利用 ZStack 将 AvatarView 叠加在 gameBackground 的颜色上 为了使背景颜色可移除 我们只需要 在 View 中添加 containerBackground 修饰符 并将 gameBackground 颜色 放入其中即可 完成后 系统就可以根据当前的环境 自动移除小组件的背景 Apple Watch 中的智能叠放 也可以利用这个新 containerBackground 默认情况下 accessoryRectangular 小组件 在该环境中会获得深色材质背景 通过在 View 中添加相同的 containerBackground 修饰符 该小组件便会置于 和其他小组件相同的背景上 并与 App 的视觉识别相连 想要了解更多有关该新环境的信息 欢迎观看“Apple Watch 智能叠放的小组件设计” 对于照片和地图之类的小组件 由于缺乏特别的前景内容 所以没有移除背景的必要 在这种情况下 你可以在 WidgetConfiguration 中 添加 containerBackgroundRemovable 修饰符 并将其设置为 false 现在 我们来对 iPad 锁定屏幕及 待机模式中的布局进行优化 天气小组件便可以很好地说明 如何在背景移除的情况下更改布局
请注意观察小组件是如何在 针对高效利用空间的优化后 仍然保持着内容不变 将内容推到边缘 并放大重要元素 经过这些调整 小组件不仅更易于从远处查看 同时还可以和待机模式 实现更无缝的融合 此外 这些布局更改 也可以帮助小组件 与 iPad 锁定屏幕中的 配件系列小组件实现更好的融合 从而让所有系列的外观更为一致 现在让我们前往 Xcode 在小组件中实现这些更改 这里是用于 AvatarView 的代码 也就是 systemSmall 小组件 所使用的代码 在右侧的 Xcode Previews 中 我可以实时预览小组件的外观 当小组件显示在 容器背景被移除的环境中 其内容外边距便会自动缩小 从而使内容与边缘对齐 接着 我们就可以使用 showsWidgetContainerBackground 环境变量 来检测小组件的背景是否被移除 如果背景被移除 删掉 HeroNameView 中 英雄等级和经验等细节信息 并在下方重新展示它们
在该环境中 英雄的名字也会变得更大 现在 如果我们在环境间进行切换 布局就会自动 从初始视图变为放大的新视图
和配件系列小组件一样 系统系列小组件也可以 以生动渲染模式 显示在 iPad 锁定屏幕上 这意味着小组件将会被去色 然后根据锁定屏幕背景 进行适当着色 但如果是这样渲染的话 对比度问题 就会影响小组件的清晰度 例如 英雄头像就很难 从圆形背景中分辨出来 让我们回到 Xcode 中 对小组件进行修改 以使其在生动渲染模式下 将背景移除 让我们在待机夜间模式中看看吧 我们可以使用 widgetRenderingMode 环境变量 检测正在使用的渲染模式 然后更改 Avatar 中 includesBackground 参数 检查是否处于生动渲染模式
待机夜间模式 也可以使用生动渲染模式 因此我们的头像 在该环境下同样清晰可见 想进一步了解更多有关 小组件渲染模式的信息 欢迎观看 WWDC22 中的 “复杂功能和小组件:重新加载” 而想要了解更多有关 小组件新功能的信息 欢迎观看“让小组件栩栩如生” 我对小组件发生的更改十分兴奋 非常期待看到 你利用这些新功能增强小组件的 新想法 感谢你的观看 祝你生活愉快! ♪ ♪
-
-
2:08 - SafeAreasWidget
struct SafeAreasWidgetView: View { @Environment(\.widgetContentMargins) var margins var body: some View { ZStack { Color.blue Group { Color.lightBlue Text("Hello, world!") } .padding(margins) } } } struct SafeAreasWidget: Widget { var body: some WidgetConfiguration { StaticConfiguration(...) {_ in SafeAreasWidgetView() } .contentMarginsDisabled() } }
-
3:19 - EmojiRangerWidget systemSmall
struct EmojiRangerWidgetEntryView: View { var entry: Provider.Entry @Environment(\.widgetFamily) var family var body: some View { switch family { case .systemSmall: ZStack { AvatarView(entry.hero) .widgetURL(entry.hero.url) .foregroundColor(.white) } .containerBackground(for: .widget) { Color.gameBackground } } // additional cases } }
-
3:48 - EmojiRangerWidget accessoryRectangular
var body: some View { switch family { case .accessoryRectangular: HStack(alignment: .center, spacing: 0) { VStack(alignment: .leading) { Text(entry.hero.name) .font(.headline) .widgetAccentable() Text("Level \(entry.hero.level)") Text(entry.hero.fullHealthDate, style: .timer) }.frame(maxWidth: .infinity, alignment: .leading) Avatar(hero: entry.hero, includeBackground: false) } .containerBackground(for: .widget) { Color.gameBackground } // additional cases }
-
4:22 - PhotoWidget
struct PhotoWidget: Widget { public var body: some WidgetConfiguration { StaticConfiguration(...) { entry in PhotoWidgetView(entry: entry) } .containerBackgroundRemovable(false) } }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。