简介
Widget不是一个小型的App,它是一种新的桌面内容展现形式,展示在Home Screen上,能快速提供用户关心的内容是重点,主要用于弥补主App无法及时展示用户所关心的数据。
优秀的Widget有三个特点:
- 简单明了
充分利用狭小的屏幕空间展示最核心(用户最关心)的信息,并且要简洁明了、设计新颖,便于快速浏览,用户不用思考这个Widget怎么使用。高效是一个优秀Widget的核心。 - 恰当展示
必须和用户紧密结合,与用户的行为所关联,比如早上起床,用户希望看一下天气;起床后,用户希望看一下当天的安排,等等。为此,苹果系统提供了一个叫Smart Stacks(智能叠放)的功能,Smart Stacks是一个Widgets的集合。系统会根据每个人的习惯,自动显示用户当前时间点最需要的Widget。PS:开发者不能开发Smart Stack - 个性化定制
苹果给Widget提供了一定的个性化定制能力
1. widget组件尺寸
- small
2x2 icon区域,水平方向2个icon、竖直方向2个icon - medium
4X2 icon区域,水平方向4个icon、竖直方向2个icon - large
4X4 icon区域,水平方向4个icon、竖直方向4个icon
具体图片尺寸
2. 个性化配置
苹果提供Widget的可配置能力
- StaticConfiguration:对于没有用户可配置属性的窗口小组件,也就是用户无需配置,展示的内容只和用户信息有关系。例如,显示一般市场信息的股市窗口小组件。
- IntentConfiguration:对于具有用户可配置属性的窗口小组件,也就是支持用户配置及用户意图的推测功能。例如,需要一个跟踪号的包裹跟踪小组件。
交互及展示
Widget的UI是无状态的
- 不支持播放动画gif、视频
- 不支持滚动
- 不支持主动刷新视图
唯一支持的只有用户点击和DeepLink唤起主app
- WidgetURL:点击区域是Widget的所有区域,small类型只能用这种
- Link:可以细分点击区域
Widget的刷新机制
Widget的核心是Timeline,即一条时间线,在对应的时间点展示对应的UI
时间线由一个或多个时间线入口TimelineEntry以及一个重载策略ReloadPolicy组成,该重载策略会通知WidgetKit何时请求后续时间线。
重载策略(接下来这段时间Timeline的刷新策略)有以下几种策略:
- atEnd: 指Timeline执行到最后一个时间片的时候再刷新
- atAfter: 指在某个时间以后有规律的刷新
- never:指以后不需要刷新了,什么时候需要重新刷新需要App重新告知 Widget
重新加载时间线使小组件保持最新
Widget的刷新完全由WidgetCenter控制。需要通过生成一个新的时间线来替换旧的时间线,Reload Timeline并不是直接刷新Widget,而是WidgetCenter重新请求下一个时间线的数据。
系统提供两种方式来刷新Timeline:
- System Reloads:由系统主动、按时发起,会reload下一时间线的数据;系统还会借助端智能的能力,动态决策每个不同的TimeLine的System Reloads的频次。例如被查看次数很大程度上直接决定了System Reloads的频率。还有一些由于设备环境变化触发的行为也会触发System Reloads,比如设备时间进行了变更。这种方案由系统决策,不能符合特殊需求。
- App Reloads:由App主动通知小组件,你需要更新了。分两种场景,应用在前台运行和应用在后台运行。当应用在前台运行的时候,App可以直接请求WidgetCenter的API来触发刷新时间线;当应用处于后台时,后台推送(Background Notification)也可以触发刷新时间线。
示例:每5分钟刷新一下时间线
最短间隔为5分钟,即使设置的时间小于5分钟,系统也会按5分钟进行调用
网易新闻刷新间隔为5分钟;我的天气刷新间隔为30分钟
let currentDate = Date()
//逃逸闭包传入匿名函数 当调用completion时调用该匿名函数刷新Widget
DataLoader.fetch { result in
let testData: TestData
if case .success(let fetchedData) = result {
testData = fetchedData
} else {
testData = TestData(content: "本次更新失败,等待5分钟后下一次更新.",time:"失败")
}
let entry = SimpleEntry(date: currentDate, test: testData.content, str: testData.time, configuration: configuration)
// //第二个时间片
// let entryDate = Calendar.current.date(byAdding: .minute, value: 1, to: currentDate)!
// let entry2 = SimpleEntry(date: entryDate, test: "2", str: testData.time, configuration: configuration)
// 设定下次刷新的时间是5分钟后
let refreshDate = Calendar.current.date(byAdding: .minute, value: 5, to: currentDate)!
let timeline = Timeline(entries: [entry], policy: .after(refreshDate))
// let timeline = Timeline(entries: [entry], policy: .atEnd)
completion(timeline)
}
Widget的显示内容
- PlaceholderView(占位view):在Widget实际数据显示之前,显示的占位符UI,相当于tableView显示数据之前的占位UI,此UI中不应有任何用户数据。很可能你不一定看得到这个PlaceholderView,如果你的Widget数据加载逻辑比较耗时间,这个PlaceholderView的作用就体现出来了。
- snapshot()(快照):编辑窗口屏幕时,左上角选择添加小组件时候,第一次展示小组件会加载预览快照,这个方法里主要提供了一些示例数据,最好是真实数据,用于时间线不能展示的时候展示给用户。snapshot方法提供的数据,应该尽量快速.
网友评论