1、先在项目里创建一个Widget Target
2、一定要勾选 Include live Activity,然后输入名称,点击完成既可。
3、在 Info.plist 文件中声明开启,打开 Info.plist 文件添加 NSSupportsLiveActivities,并将其布尔值设置为 YES。
4、我们创建一个IMAttributes,
struct IMAttributes: ActivityAttributes {public typealias IMStatus = ContentStatepublic struct ContentState: Codable, Hashable {var callName: Stringvar imageStr : Stringvar callingTimer: ClosedRange<Date>}var callName: Stringvar imageStr : Stringvar callingTimer: ClosedRange<Date>
}
5、灵动岛界面配置
struct IMActivityWidget: Widget {var body: some WidgetConfiguration {ActivityConfiguration(for: IMAttributes.self) { context in// 创建显示在锁定屏幕上的演示,并在不支持动态岛的设备的主屏幕上作为横幅。// 展示锁屏页面的 UI} dynamicIsland: { context in// 创建显示在动态岛中的内容。DynamicIsland {//这里创建拓展内容(长按灵动岛)DynamicIslandExpandedRegion(.leading) {Label(context.state.callName, systemImage: "person").font(.caption).padding()}DynamicIslandExpandedRegion(.trailing) {Label {Text(timerInterval: context.state.callingTimer, countsDown: false).multilineTextAlignment(.trailing).frame(width: 50).monospacedDigit().font(.caption2)} icon: {Image(systemName: "timer")}.font(.title2)}DynamicIslandExpandedRegion(.center) {Text("\(context.state.callName) 正在通话中...").lineLimit(1).font(.caption).foregroundColor(.secondary)}}//下面是紧凑展示内容区(只展示一个时的视图)compactLeading: {Label {Text(context.state.callName)} icon: {Image(systemName: "person")}.font(.caption2)} compactTrailing: {Text(timerInterval: context.state.callingTimer, countsDown: true).multilineTextAlignment(.center).frame(width: 40).font(.caption2)}//当多个Live Activities处于活动时,展示此处极小视图minimal: {VStack(alignment: .center) {Image(systemName: "person")}}.keylineTint(.accentColor)}}
}
6、在需要的地方启动的地方调用,下面是启动灵动岛的代码
let imAttributes = IMAttributes(callName: "wqd", imageStr:"¥99", callingTimer: Date()...Date().addingTimeInterval(0))//初始化动态数据let initialContentState = IMAttributes.IMStatus(callName: name, imageStr: "ia.imageStr", callingTimer: Date()...Date().addingTimeInterval(0))do {//启用灵动岛//灵动岛只支持Iphone,areActivitiesEnabled用来判断设备是否支持,即便是不支持的设备,依旧可以提供不支持的样式展示if #available(iOS 16.1, *) {if ActivityAuthorizationInfo().areActivitiesEnabled == true{}} else {// Fallback on earlier versions}let deliveryActivity = try Activity<IMAttributes>.request(attributes: imAttributes,contentState: initialContentState,pushType: nil)//判断启动成功后,获取推送令牌 ,发送给服务器,用于远程推送Live Activities更新//不是每次启动都会成功,当已经存在多个Live activity时会出现启动失败的情况if deliveryActivity.activityState == .active{_ = deliveryActivity.pushToken}
// deliveryActivity.pushTokenUpdates //监听token变化print("Current activity id -> \(deliveryActivity.id)")} catch (let error) {print("Error info -> \(error.localizedDescription)")}
6.此处只有一个灵动岛,当一个项目有多个灵动岛时,需要判断更新对应的activityfunc update(name:String) {Task {let updatedDeliveryStatus = IMAttributes.IMStatus(callName: name, imageStr: "ia.imageStr", callingTimer: Date()...Date().addingTimeInterval(0))for activity in Activity<IMAttributes>.activities{await activity.update(using: updatedDeliveryStatus)}}}
7、停止灵动岛
func stop() {Task {for activity in Activity<IMAttributes>.activities{await activity.end(dismissalPolicy: .immediate)}}
}
相关推荐:
更多技术文章:https://www.imgeek.net/