系统要求#
iOS 14及以上
三种显示模式#
systemSmall(2x2)、systemMedium (4x2)、systemLarge(4x4)
创建Widget#
官方文档: https://developer.apple.com/documentation/widgetkit/creating-a-widget-extension
创建方式1: Xcode > File > New > Target
创建方式2:Xcode > 选中项目工程 -> Editor > Add Target
信息填写:
- Product Name : 除了不要直接命名Widget, 其他的任意,一般我们取名Widgets 或者应用名+Widgets, 比如:Widgets, MyAppWidgets , MusicAppWidgets等等
- Team: 有团队就勾选,不勾选也可以在工程中去设置
- Organization Identifier: 有就写你自己的组织名称,测试就随意写
- 勾选:Include Live Activity、Include Control、Include Configuration App Intent
文件结构:
文件名是根据Product Name自动生成带这个前缀的文件名,假设我创建时的Product Name为 Widgets
, 那么自动生成的文件名如下:
- WidgetsBundle.swift : 入口文件
- AppIntent.swift: 意图文件
- Widgets.swift: 默认的示例文件,这个作为参考,自己可另外创建相同类型文件来自定义自己的Widget界面元素
- WidgetsControl.swift :组件控制, 这个系统要求iOS18+才支持
- WidgetsLiveActivity.swift: 灵动岛活动
示例说明:
我们以音乐播放器为示例,创建了项目
Widget入口文件#
import WidgetKit
import SwiftUI
@main
struct WidgetsBundle: WidgetBundle {
var body: some Widget {
//可以添加最多5个Widget, 每个可以设置3个显示模式
PlayerStandardWidget()
//PlayerRichWidget()
//PlayerOtherWidget()
//WidgetsLiveActivity()
}
}
在body中可以创建最多5个Widget, 每个可以设置3个显示模式
AppIntent意图文件#
定义播放器三个操作意图:PlayerPlayPrevIntent、PlayerPlayPauseIntent、PlayerPlayNextIntent
import WidgetKit
import AppIntents
@available(iOS 17.0, *)
struct ConfigurationAppIntent: WidgetConfigurationIntent {
static var title: LocalizedStringResource = "Configuration"
static var description = IntentDescription("This is an example widget.")
// An example configurable parameter.
@Parameter(title: "Favorite Emoji", default: "😃")
var favoriteEmoji: String
}
//以下为播放器的:播放上一首,播放暂停,播放下一首意图操作
@available(iOS 16, *)
struct PlayerPlayPrevIntent: AppIntent {
static var title: LocalizedStringResource = "PlayerPlayPrevIntent"
func perform() async throws -> some IntentResult {
//触发移除后会自动调用这个方法,执行自己的操作事件逻辑
AppGroupsShared.setValue("playPrev", forKey: DataKeys.udKey_control_command)
return .result()
}
}
@available(iOS 16.0, *)
struct PlayerPlayPauseIntent: AppIntent {
static var title: LocalizedStringResource = "PlayerPlayPauseIntent"
func perform() async throws -> some IntentResult {
AppGroupsShared.setValue("togglePlayPause", forKey: DataKeys.udKey_control_command)
return .result()
}
}
@available(iOS 16, *)
struct PlayerPlayNextIntent: AppIntent {
static var title: LocalizedStringResource = "PlayerPlayPauseIntent"
func perform() async throws -> some IntentResult {
AppGroupsShared.setValue("playNext", forKey: DataKeys.udKey_control_command)
return .result()
}
}
创建自定义Widget#
新建一个 PlayerStandardWidget.swift
的文件
刷新Widget方式#
WidgetCenter.shared.reloadTimelines(ofKind:"XXX")
WidgetCenter.shared.reloadAllTimelines()
可以刷新指定widget, 也可以直接刷新所有。
参考资料#
https://www.jianshu.com/p/40e438b40a0b
https://segmentfault.com/a/1190000037602578?utm_source=sf-related
官方示例下载参考#
https://developer.apple.com/documentation/swiftui/backyard-birds-sample