开发者社区 > 博文 > iOS16新特性:灵动岛适配开发与到家业务场景结合的探索实践
分享
  • 打开微信扫码分享

  • 点击前往QQ分享

  • 点击前往微博分享

  • 点击复制链接

iOS16新特性:灵动岛适配开发与到家业务场景结合的探索实践

  • 朔方****
  • 2023-08-16
  • IP归属:北京
  • 22960浏览

    灵动岛是苹果在iPhone 14 Pro和iPhone 14 Pro Max上首次提出的全新UI交互形式,创新性的让虚拟软件和硬件的交互变得更为流畅。当有来电、短信等通知时,灵动岛会变化形态,以便让用户能够更直观地接收到这些信息。

    而在用户使用一些应用App,比如音乐,并将其切换到后台时,灵动岛也能以另一种形态来显示这些软件,还可以通过轻点,重按等来实现的操作,比如切换歌曲。

    苹果在iOS16.1系统对第三方开放了灵动岛的API,并允许开发者基于灵动岛开发相应软件,越来越多的APP开始基于灵动岛的交互进行设计和开发,本文将简单介绍灵动岛开发的流程和将其与业务场景相结合的思考。

    接入灵动岛

    如果项目之前开发过widget小组件,已经添加过Widget Extension,并有WidgetBundle文件,那么可以直接基于其进行扩展开发。但要注意的是,灵动岛开发用到的是Live Activity,主要包括锁屏通知,顶部通知等样式:

    而并不是widget开发用到的Time Line形式,两者在UI形态上基本毫无关系,只是需要在WidgetBundle中实例化。如果之前没有开发过widget,可以参见另一篇文章:《Widget开发以及动态配置

    首先给工程添加Widget Extension:

    勾选Live Activity:

    建立Extension以后,系统会自动生成三个文件,除了widget开发用到的TimeLine相关内容的文件和WidgetBundle文件外,还会生成一个专门用来开发灵动岛Live Activity的文件:

    文件中已经自动生成了部分代码大纲,可以直接查看效果并基于其上进行开发:

    struct DJDynamicIslandAdvanceLiveActivity: Widget {
        var body: some WidgetConfiguration {
            ActivityConfiguration(for: DJDynamicIslandAdvanceAttributes.self) { context in
                // Lock screen/banner UI goes here
                VStack {
                    Text("Hello")
                }
                .activityBackgroundTint(Color.cyan)
                .activitySystemActionForegroundColor(Color.red)
    
            } dynamicIsland: { context in
                DynamicIsland {
                    // 点击灵动岛后展开的样式
                    // various regions, like leading/trailing/center/bottom
                    DynamicIslandExpandedRegion(.leading) {
                        Text("Leading")
                    }
                    DynamicIslandExpandedRegion(.trailing) {
                        Text("Trailing")
                    }
                    DynamicIslandExpandedRegion(.center) {
                        Text("Center")
                    }
                    DynamicIslandExpandedRegion(.bottom) {
                        Text("Bottom")
                        // more content
                    }
                } compactLeading: {
                    // compact模式(长条样式)左侧内容,一般放icon
                    Text("compactLeading")
                } compactTrailing: {
                    // compact模式(长条样式)右侧内容,一般放描述文案
                    Text("compactTrailing")
                } minimal: {
                    // minimal模式(其他APP挤占后的圆圈样式)
                    Text("minimal")
                }
                .widgetURL(URL(string: "http://www.apple.com"))
                .keylineTint(Color.red)
            }
        }
    }

    同时需要在info.plist中添加对Live Activity的支持,在TARGETS - Info - Custom iOS Target Properties中添加NSSupportsLiveActivities并设置为YES:

    不同展示样式

    灵动岛主要包括三种展示样式:

    灵动岛被重按后,展开的完整模式(expanded)

    此模式分为Leading、Trailing、Center和Bottom四个部分,在系统自动为我们生成的代码中,ActivityConfiguration的dynamicIsland中可以分别找到对应控制的代码段:

    dynamicIsland: { context in
                DynamicIsland {
                    // 点击灵动岛后展开的样式
                    // various regions, like leading/trailing/center/bottom
                    DynamicIslandExpandedRegion(.leading) {
                        Text("Leading")
                    }
                    DynamicIslandExpandedRegion(.trailing) {
                        Text("Trailing")
                    }
                    DynamicIslandExpandedRegion(.center) {
                        Text("Center")
                    }
                    DynamicIslandExpandedRegion(.bottom) {
                        Text("Bottom")
                        // more content
                    }
                }

    APP切后台后的长条形展示样式(compact)

    此形式分为两个部分:左边的Leading,一般用于放图片icon等;右边的Trailing,一般用与放置文案描述

    在系统自动为我们生成的代码中,ActivityConfiguration的dynamicIsland部分分别对应compactLeading和compactTrailing,可以在其中编写我们想要的UI展示:

    compactLeading: {
                    // compact模式(长条样式)左侧内容,一般放icon
                    Text("compactLeading")
                } compactTrailing: {
                    // compact模式(长条样式)右侧内容,一般放描述文案
                    Text("compactTrailing")
                } 

    其他APP切后台时,变化为灵动岛将本app挤占后展示的圆点模式(minimal)

    此形势一般用于放置图标icon或动态图等

    在系ActivityConfiguration的dynamicIsland部分对应minimal,可以在其中编写我们想要的UI展示

    minimal: {
                    // minimal模式(其他APP挤占后的圆圈样式)
                    Text("minimal")
                }

    动态数据更新

    上文说灵动岛视图布局是在ActivityConfiguration中编写的,而其上的数据更新依靠的是ActivityAttributes对象。需要注意的是,ActivityAttributes不需要跟ActivityConfiguration写在一起,就像view不需要跟model写在一起一样。

    苹果官方建议ActivityAttributes分为两部分:固定不变的属性(比如总数,订单号等等)和会动态变化的属性(比如配送员名称,配送时间等等)。官方给出的demo是披萨配送的app,我们可以参考它的Attributes声明规则:

    struct PizzaDeliveryAttributes: ActivityAttributes {
        public typealias PizzaDeliveryStatus = ContentState
    
        public struct ContentState: Codable, Hashable {
            var driverName: String
            var deliveryTimer: ClosedRange<Date>
        }
    
        var numberOfPizzas: Int
        var totalAmount: String
        var orderNumber: String
    }

    其中ContentState是会动态改变的部分。在完成布局编写后,实际的工程应用当中可以调用Activity对象的各种方法对灵动岛进行操作,包括开启,更新和关闭:

    调用Activity<ActivityAttributes>.request成功开启灵动岛后,将APP切到后台,就可以看到效果了,调用request以及Activity<ActivityAttributes>里每一个activity的update方法,都可以触发ActivityConfiguration的闭包调用,从它回掉的context可以获取到Attributes的数据内容,比如context.state.deliveryManName和context.attributes.totalAmount:

    与到家业务结合的思考

    灵动岛提供了一种全新的“通知交互”形式,不再是单调的一个横幅或者提示框,而是一个实时显示,动态更新的UI,就像他的名字“Live Activity”一样,是一场“直播”。

    现在很多竞品app都基于自己的业务场景推出了自己的灵动岛应用:

    饿了么

    直播吧


    对灵动岛的适配被形象地称为“登岛”,针对到家的业务场景,我们也做了一系列思考,最适用的业务场景也是下单后订单状态的实时更新“直播”,并且编写了Demo展示:

    灵动岛挂件

    灵动岛挂件是我们提出的另一种非常有意思的灵动岛应用。

    首先,灵动岛的各项UI数据如下:

    经过精确布局,可以在灵动岛上动态的展示一个会动的挂件,就像在灵动岛上养了一只可爱的宠物:

    我们会持续跟进最新的灵动岛技术动态,并且探索其他实用灵动岛的业务场景,利用这项技术带来更多的流量和利益点