iOS_灵动岛<Dynamic Island>

news/2024/7/20 20:20:50 标签: ios

灵动岛

  • 简介
  • 开发
    • 新增权限
    • 创建小组件
    • 编写小组件
      • 编写数据模型
      • 编写页面样式<`SwiftUI`>
    • 数据更新

简介

苹果在 iPhone 14 Pro 及 iPhone 14 Pro MAX 上推出了灵动岛。灵动岛可以通过点按、长按、轻扫来进行交互,最多支持两个应用同时“登岛”。
灵动岛全称 Dynamic Island,作为 iOS 中实时活动(Live Activities)功能的一部分,用来展示需要实时更新的消息。

  • 展现形式
    展现形式有三种:Compact <紧凑>、Minimal <最小化>、Expanded <扩展>,在开发提交的时候,必须适配这三种形式
  • UI尺寸适配<尺寸单位Points>
    圆角半径均为 44
机型紧凑< Leading Side>紧凑< Trailing Side >最小化扩展
14 Pro52.33 * 36.6752.33 * 36.6736.67 * 36.67371 * (84-160)
14 Pro Max62.33 * 36.6762.33 * 36.6736.67 * 36.67408 * (84-160)
  • 颜色适配
    无法更改灵动岛的背景颜色,只能更改文字颜色、素材颜色、灵动岛边框颜色等。UI 适配需要考虑系统的深色模式,必要情况可以使用两套 UI。

  • 开发适配

    • 苹果在 iOS 16.1 正式对外开放了灵动岛适配框架 ActivityKit,第三方 App 可以使用这些 ActivityKit 完成灵动岛适配工作。注意 ActivityKitAPI 目前仅适用于 iPhone。灵动岛使用 WidgetKitSwiftUI 完成 UI 开发工作,ActivityKit 在其中扮演创建 Activity,请求数据,更新数据,结束 Activity 的角色。
    • 需要打开"实时活动权限",才可以使用灵动岛功能。
  • 开发注意要点

    • 灵动岛的实时信息要有明确的开始和结束时间点
    • 当一个实时信息持续超过 8 小时,系统会从灵动岛移除这个 App 的信息
    • 当一个实时活动结束时,灵动岛上的展示信息也会立即被系统移除
    • App 要能够响应灵动岛的点击信息,跳转到 App 中的正确子页面,而不是停留在 App 的首页

开发

新增权限

在主项目的Info.plist中添加NSSupportsLiveActivities = YES

创建小组件

  1. Xcode 中打开你的 App 项目,并选取File(文件) >New(新建) >Target(目标)。
  2. Application Extension(App 扩展) 组中,选择Widget Extension(小组件扩展),然后点按Next(下一步)。
  3. 输入你的扩展的名称。
  4. 如果小组件提供用户可配置的属性,请选中Include Configuration Intent(包含配置意图) 复选框。
  5. 点按Finish(完成)。

编写小组件

编写数据模型

数据模型,需要遵循ActivityAttributes协议

struct DynamicAttributes: ActivityAttributes {
    // 动态数据
    public struct ContentState: Codable, Hashable {
        var value: Int
    }
    // 静态数据
    var name: String
}

编写页面样式<SwiftUI>

struct DynamicLiveActivity: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: DynamicAttributes.self) { context in
            // 通知区域
            // Lock screen/banner UI goes here
            VStack {
                Text("Hello")
            }
            .activityBackgroundTint(Color.cyan)
            .activitySystemActionForegroundColor(Color.black)

        } dynamicIsland: { context in
            DynamicIsland {
                // 扩展
                // Leading Space
                DynamicIslandExpandedRegion(.leading) {
                    Text("Leading")
                }
                // Bottom
                DynamicIslandExpandedRegion(.bottom) {
                    Text("bottom")
                }
                // Trailing Space
                DynamicIslandExpandedRegion(.trailing) {
                   Text("trailing")
                }
                // Center Space
                DynamicIslandExpandedRegion(.center) {
                    Text("center")
                }                
            } compactLeading: {
                // 紧凑
                Text("L")
            } compactTrailing: {
                // 紧凑
                Text("T")
            } minimal: {
                // 最小化
                Text("Min")
            }
            .widgetURL(URL(string: "http://www.apple.com"))
            .keylineTint(Color.red)
        }
    }
}

数据更新

class DynamicManager {
    static let shared: DynamicManager = DynamicManager()
    private init () {}
    /// 开始
    /**
     active 处于活动中
     ended 已经终止且不会有任何更新,但依旧在锁屏界面展示
     dismissed 结束且不再展示
     */
    func stratDynamicActivity() {
        // 初始化静态数据
        let dynamicAttributes = DynamicAttributes(name: "ceshi", data: "ceshiData")
        // 初始化动态数据
        let initialContentState = DynamicAttributes.ContentState(value: 100, id: 1000)
        
        do {
            // 启用灵动岛
            // 灵动岛只支持iPhone,areActivitiesEnabled用来判断设备是否支持,
            // 即便是不支持的设备,依旧可以提供不支持的样式展示
            if ActivityAuthorizationInfo().areActivitiesEnabled == true {
                        
            }
            let deliveryActivity = try Activity<DynamicAttributes>.request(attributes: dynamicAttributes,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)")
        }
    }
    /// 更新
    func updateDynamicActivity() {
        Task {
            let newContent = DynamicAttributes.ContentState(value: 10, id: 10)
            //此处只有一个灵动岛,当一个项目有多个灵动岛时,需要判断更新对应的activity
            for activity in Activity<DynamicAttributes>.activities {
                await activity.update(using: newContent)
            }
        }
    }
    /// 停止
    /**
     结束分为两种
     .default 系统默认,结束后在锁屏界面保留4小时
     .immediate 立即结束,不会在锁屏界面停留
     */
    func stopDynamicActivity() {
        Task {
            //此处只有一个灵动岛,当一个项目有多个灵动岛时,需要判断更新对应的activity
            for activity in Activity<DynamicAttributes>.activities {
                await activity.end(nil,dismissalPolicy: .immediate)
            }
        }
    }
}


注意事项
灵动岛的活动状态一共有3种:
active 处于活动中
ended 已经终止且不会有任何更新,但依旧在锁屏界面展示
dismissed 结束且不再展示


参考链接:苹果开发网站


http://www.niftyadmin.cn/n/699460.html

相关文章

什么是DevOps? 什么是DORA?

1. 前言 对于搞云原生应用的同学&#xff0c;对于DevOps和DORA应该都不陌生。但对于传统应用程序开发的同学&#xff0c;经常被DevOps, Microservice, CICD, DORA这些新颖的名词搞得晕头转向。那么到底什么是DevOps? 什么是DORA呢&#xff1f; 2. 解析 2.1 DevOps DevOps并…

在 TypeScript 中有效地使用 keyof 和 typeof 来表示类型

在本文中&#xff0c;我们将学习如何通过组合类型运算符和枚举来提取和声明常量类型typeof&#xff0c;以使您的代码库得到优化。keyof 先决条件 为了获得更好的编码体验&#xff0c;您应该在 IDE 中安装 TypeScript&#xff0c;例如VSCode。它将为您提供许多基本功能&#xff…

【ES实战】索引别名的使用说明

索引别名 文章目录 索引别名带有过滤器的别名RoutingWrite Index REST单一添加一个别名示例: 索引创建是增加别名删除别名检索现有别名示例: 索引别名可以通过API的方式进行操作一个索引别名可以映射到一个或一个以上的索引索引名和索引别名不能重复&#xff0c;在集群中都是唯…

2023年03月份青少年软件编程Python等级考试试卷五级真题(含答案)

一、单选题(共25题&#xff0c;共50分) 1.已知一个列表lst [2,3,4,5,6]&#xff0c;lst.append(20)&#xff0c;print(lst)的结果是&#xff1f;&#xff08;C&#xff09;&#xff08;2分&#xff09; &#xff08;append是列表后面追加20这个元素&#xff09; A.[10,2,3,4,…

【C++初阶】C++入门——C++介绍、命名空间、输入输出

目录 一、C前言介绍1.1 什么是C?1.2 C的发展史 二、C关键字三、命名空间3.1 为什么要有命名空间&#xff1f;3.2 命名空间定义3.3 每一个命名空间都是一个作用域3.4 命名空间的使用方法3.5 嵌套的命名空间3.6 C标准库的命名空间 四、C输入和输出 一、C前言介绍 1.1 什么是C?…

【保姆级】Redis安装教程(Windows版)

Redis安装教程&#xff08;Windows版&#xff09; 文章目录 Redis安装教程&#xff08;Windows版&#xff09;1.下载安装包2. 安装注意事项3. 注意事项4. 登录Redis客户端5. 停止Redis服务附&#xff1a;详细安装步骤附&#xff1a;RESP&#xff08;Redis桌面管理&#xff09;使…

Web服务器群集:Nginx+Tomcat实现负载均衡与动静分离集群

目录 一、理论 1.多实例 2.Nginx负载均衡 3.Nginx动静分离 4.配置NginxTomcat负载均衡 5.配置NginxTomcat动静分离集群 6.Nginx 四层代理配置 二、实验 1.配置NginxTomcat负载均衡 2.、配置NginxTomcat动静分离集群 三、问题 1.服务器群集与集群的区别 四、总结 一…

Uipath Excel 实战01-自动生成流水号最佳方法

Uipath RPA 自动生成流水号最佳方法&#xff0c;提高RPA 性能&#xff0c;速度毫秒级。通过本案例将学会Excel 写入单元格、Excel 自动填充公式、Excel 自动调整列范围、保存Excel 文件以及使用Excel 函数。 公式参考&#xff1a; Excel公式参考&#xff1a; Excel CONCATENAT…