iOS 小组件开发:灵动岛开发

灵动岛配置

首先,灵动岛实际上是一个小组件,就像 iOS 14 小部件一样,这也是为什么我会放在小组件的部分来讲。

1、创建 Target

让我们来创建一个新的 Widget Target,来到 File -> New -> Target...,创建一个 Widget Extension

一定要勾选 Include live Activity,然后输入名称,点击完成既可。

2、添加 Info.plist 配置

项目要启用灵动岛,需要在 Info.plist 文件中声明开启,打开 Info.plist 文件添加 NSSupportsLiveActivities,并将其布尔值设置为 YES。

展示部分

当我们创建这个 Target Extension 并且勾选了 Include live Activity 之后,Xcode 会自动帮我们创建出来一个灵动岛的模版,我目前用的是 Xcode 15,可以看下 Xcode 自动生成的模版预览:

灵动岛有三种渲染模式,第一种是紧凑型,当只有你的应用在应用在使用灵动岛时,会展示成这样:

第二种叫最小型样式,是当你的应用和别人的应用都在使用灵动岛时,会显示成下面这种样式,系统会决定展示哪个 App 的灵动岛,并使用每个活动的最小演示显示两个实时活动:

第三种是展开的灵动岛样式,当用户触摸并按住紧凑或最小的演示文稿时,它会显示,这种样式可以显示更多的内容:

代码部分

主要代码分为两部分,一部分是 ActivityAttributes,主要用来提供灵动岛上展示的数据:

 
 

css

复制代码

struct MyLiveActivityAttributes: ActivityAttributes { public struct ContentState: Codable, Hashable { var emoji: String } var name: String }

当我们需要展示灵动岛的时候需要创建一份 ActivityAttributes

另一部分是灵动岛的 UI 展示:

 
 

scss

复制代码

struct MyLiveActivityLiveActivity: Widget { var body: some WidgetConfiguration { ActivityConfiguration(for: MyLiveActivityAttributes.self) { context in // 展示锁屏页面的 UI VStack { Text("\(context.attributes.name) \(context.state.emoji)") } .activityBackgroundTint(Color.cyan) .activitySystemActionForegroundColor(Color.black) } dynamicIsland: { context in DynamicIsland { // 展开样式 UI DynamicIslandExpandedRegion(.leading) { Text("左侧") } DynamicIslandExpandedRegion(.trailing) { Text("右侧") } DynamicIslandExpandedRegion(.bottom) { Text("底部 \(context.state.emoji)") Text("内容:\(context.attributes.name) 自定义内容") } } compactLeading: { // 紧凑型样式左边 UI Text("左") } compactTrailing: { // 紧凑型样式右边 UI Text("右 \(context.state.emoji)") } minimal: { // 最小型样式 UI Text(context.state.emoji) } .widgetURL(URL(string: "http://www.apple.com")) .keylineTint(Color.red) } } }

ActivityConfiguration 的第一个 block 用来渲染展示锁屏页面的 UI,dynamicIsland 就是用来渲染灵动岛的内容了。

DynamicIsland 对象中,第一部分用来渲染展开样式的 UI,compactLeading 用来展示紧凑型样式左边 UI,compactTrailing 用来展示紧凑型样式右边 UI,minimal 用来展示最小型样式 UI。

关于 UI 部分,可以自由发挥,但要注意每个区域的大小。

启动灵动岛

我们在主 App 的 ViewController 中渲染三个按钮来模拟用户达到某个条件后启动/更新和关闭灵动岛:

 
 

swift

复制代码

import ActivityKit class ViewController: UIViewController { var activity: Activity<MyLiveActivityAttributes>? = nil override func viewDidLoad() { super.viewDidLoad() createButton(title: "启动灵动岛", y: view.center.y - 100, selector: #selector(start)) createButton(title: "更新灵动岛", y: view.center.y - 50, selector: #selector(update)) createButton(title: "关闭灵动岛", y: view.center.y, selector: #selector(end)) } private func createButton(title: String, y: CGFloat, selector: Selector) { let button = UIButton(type: .system) button.setTitle(title, for: .normal) button.sizeToFit() view.addSubview(button) button.center.x = view.center.x button.frame.origin.y = y button.addTarget(self, action: selector, for: .touchUpInside) } @objc private func start() { // 创建灵动岛 let attributes = MyLiveActivityAttributes(name: "iOS 新知") let state = MyLiveActivityAttributes.ContentState(emoji: " ") let content = ActivityContent<MyLiveActivityAttributes.ContentState>(state: state, staleDate: nil) do { self.activity = try Activity<MyLiveActivityAttributes>.request(attributes: attributes, content: content) } catch let error { print("出错了:\(error.localizedDescription)") } } @objc private func update() { let state = MyLiveActivityAttributes.ContentState(emoji: " ") Task { await activity?.update(using: state) } } @objc private func end() { Task { await activity?.end() } } }

启动灵动岛需要创建一个 ActivityAttributes,和一个 ActivityContent,然后调用 request(attributes: content:) 方法既可,这个方法会返回一个 Activity 对象,我们保留这个对象,后面更新和关闭灵动岛的时候使用。

更新灵动岛只需要使用上边的 Activity 对象,调用 update(using:) 方法。

关闭灵动岛只需要使用上边的 Activity 对象,调用 end() 方法。

最后看一下效果。

当我们启动 App,点击 "启动灵动岛" 按钮,然后把应用退到后台(前台不展示),就可以看到灵动岛上出现了我们设置的 UI:

然后看下锁屏页面,推送通知区域会看到出现了我们渲染的内容:

长按灵动岛,可以从紧凑模式变成扩展模式:

点击灵动岛可以打开 App,然后点击 "更新灵动岛" 按钮,再次退到后台,可以看到灵动岛已经刷新了:

最后点击 "关闭灵动岛" 按钮,再退到后台,灵动岛消失。

这里每天分享一个 iOS 的新知识,快来关注我吧

猜你喜欢

转载自blog.csdn.net/m0_60961651/article/details/135448577