iOS 14 制作自己的桌面 Widget

swift 发布于 2020年08月06日

在上一篇文章中, 我和大家介绍了 iOS 14 Widget 的基本内容, 了解了组成 Widget 的主要几个组件. 这篇文章开始, 我会和大家一起对 Xcode 自带的默认项目做一些优化, 让大家更加深入的学习桌面 Widget.

如果需要了解上一篇内容, 可以查看 iOS 14 Widget 上手体验.

为了提起大家的兴趣, 我先展示一下完成这篇教程后, Widget 的效果图:

问题分析

正如我们上篇文章介绍的, iOS 自带的时钟 Widget 示例项目, 有很多可以完善的地方. 比如: 时钟 Widget 1个小时才刷新一次, 明显不符合实用场景. 示例程序的界面也非常简陋, 有很多优化空间.

优化改动

首先我们先来优化一下时钟的显示, Xcode 默认项目的时钟只显示了时和分, 并且1小时刷新1次, 我们先让它能显示到秒:

原代码:

struct widgetEntryView : View {
var entry: Provider.Entry

var body: some View {

Text(entry.date, style: .time)
}
}

改为:

struct widgetEntryView : View {
var entry: Provider.Entry

static let taskDateFormat: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "HH:mm:ss"
return formatter
}()
var body: some View {

Text("\(entry.date, formatter: Self.taskDateFormat)")

}
}

改动很简单, 原项目中, 使用 SwiftUI 中 Text 组件的 .time 参数设置显示风格, 我们改动后, 自定义了 DateFormatter 让最终的显示内容, 显示到秒, 运行一下项目, 可以看到 Widget 的显示内容改变了:

接下来我们再修改一下刷新时间, 这里我们只需要改两处地方:

for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!

改为:

for hourOffset in 0 ..< 60 {
let entryDate = Calendar.current.date(byAdding: .second, value: hourOffset, to: currentDate)!

我们这里将 0 ..< 5 改为 0 ..< 60 , 表示一次填充 60个 Timeline 实例, 并且每个实例中把 .hour 改为 .second. 代表从每小时刷新一次变为每秒刷新.

再次运行项目, 你就会看的 Wdiget 上面的时钟每秒都会更新了.

时钟外观

我们继续对外观做一些优化. 你还记得 Widget 添加界面中上面的标题吗:

这里的标题写的很随意, 我们之前也提提到过, 可以很容易的修改它们:

StaticConfiguration(kind: kind, provider: Provider(), placeholder: PlaceholderView()) { entry in
widgetEntryView(entry: entry)
}
.configurationDisplayName("My Widget")
.description("This is an example widget.")

把 Widget 入口代码最后两行修改一下:

.configurationDisplayName("桌面时钟")
.description("可以在桌面显示的实时时钟.")

再次运行项目:

嗯, 看起来好多了. 不过这个界面还是显得有些简陋. 我们继续优化一下:

widgetEntryView 的 body 继续修改:

var body: some View {

Text("\(entry.date, formatter: Self.taskDateFormat)")

}

修改为:

var body: some View {

ZStack {
Image("bg")
.resizable()
.scaledToFill()
.edgesIgnoringSafeArea(.all)
Text("\(entry.date, formatter: Self.taskDateFormat)")
.font(.system(size: 25))
.foregroundColor(.white)
.padding(.top, 90)
}
}

ZStack 是 SwiftUI 中的一种布局, 里面包含了两个组件 Image 和 Text, 你可以理解为 ZStack 中的组件从下到上堆叠起来.

Image 在最下面, 给它设置了一个背景图片.

Text 组件, 这次做了一些修改, 把它的字体, 文字颜色, 和位置重新设置了一下.

另外, Widget 下面会显示 app 的名称, 我们需要把主 app 的名称重新设置一下:

Display Name 这里, 我们设置为"桌面时钟". 重新运行项目, 你会看到下图:

修改默认尺寸

桌面 Widget 默认支持3种尺寸, 我们在上篇文章中也展示过. 但作为时钟应用, 我们只需要 1 种尺寸就够了. 你可以这样设置:

在我们之前的入口配置代码最下面, 再加上一行

.configurationDisplayName("桌面时钟")
.description("可以在桌面显示的实时时钟.")
.supportedFamilies([.systemSmall])

这样, 我们再添加 Widget 的时候, 就只有 1种尺寸可供选择:

这样的选择界面感觉完整多了吧.

完善 Placeholder 界面

最后还有一个事情, 还记得我们前面提到 placeholder 吗, 现在如果你重新运行项目, 桌面上的 Widget 会在开始的几秒内显示这样:

这是因为 placeholder 视图, 我们还是用的初始项目提供的. 所以这个地方也需要修改:

struct PlaceholderView : View {
var body: some View {
Text("Placeholder View")
}
}

修改为:

struct PlaceholderView : View {

var body: some View {

ZStack {
Image("bg")
.resizable()
.scaledToFill()
.edgesIgnoringSafeArea(.all)
}

}
}

我们把背景图放到了 PlaceholderView 里面, 这样在 Widget 初始加载的时候你看到的就是这样的界面了:

总结

经过上面几步修改后, 我们也做出了有点样子的 Wdiget 了. 当然, 这依然是比较基础的内容. 想用好 Widget, 你还要对 SwiftUI 有一定的了解. 如果大家感兴趣, 我还会继续为大家整理相关的内容. 也欢迎各位读者提出宝贵意见.


如果你觉得这篇文章有帮助,还可以关注微信公众号 swift-cafe,会有更多我的原创内容分享给你~

本站文章均为原创内容,如需转载请注明出处,谢谢。
关注微信公众号
发现更多精彩
swift-cafe