在2022年9月刚刚结束的苹果秋季发布会上,除了常规的手机等硬件设备新品发布,伴随而来一个新的软件功能灵动岛(DynamicIsland);灵动岛是将前置镜头和软件通知结合在一起的一个全新功能,2017年发布的iPhone10打电话时候,左上角的那颗胶囊应该就是这个功能的前身,灵动岛上更进一步,不同应用可以展现出不同的样式,本篇文章将从软件开发角度,探索灵动岛的展现形式、功能限制、如何具体实现、适用场景等各方面的问题;帮助还不了解相关信息的开发者快速理解这一新的展现形式,并结合自身产品形态做出创新。 元素及展示位置iPhone锁屏(LockScreen)页面灵动岛(DynamicIsland)灵动岛截图显示要求和限制基本流程开发框架配置ActivityAttributes创建ActivityWidget显示视图生命周期管理启动状态更新停止跳转适用场景初探总结参考概览 灵动岛(DynamicIsland)相关API,隶属于LiveActivityFramework,出现在iOS16。1系统;LiveActivities负责在iPhone锁屏(LockScreen)和灵动岛(DynamicIsland)中显示应用程序的最新数据。这使得人们一眼就能看到实时信息,并可以进行一些简单交互。元素及展示位置 接下来,我们详细介绍一下能够利用LiveActivity,展示UI元素与用户产生互动的位置;iPhone锁屏(LockScreen)页面 锁屏页面上半部分可以定制增加小组件,需要iOS16系统; 灵动岛(DynamicIsland) 灵动岛,要求iOS16。1系统,iPhone14ProiPhone14ProMax机型; 目前仅有以下系统应用已经支持灵动岛:OngoingcallSharePlayMusicNowplayingappsTimerMapsdirectionsVoicememosScreenRecordingPersonalHotspot 我们通过一段动图展示一下灵动岛在实际使用中的效果(动图文件较大,可能需要时间加载); 通过简单分析可以看到,展示区域主要分为两个部分:音乐播放左侧显示封面,右侧显示波纹计时器;导航左侧显示即时图标,右侧显示剩余时间导航,下个路口,转弯方向;录音机,左侧显示录音状态,右侧录音时长; 另外,如果App实现了灵动岛,但是在不支持的设备上(即iPhone14ProiPhone14ProMax机型之外的所有机型),会在LockScreen会展示一种新的锁屏组件,位置在锁屏页面下半部分,如下图所示: 目前苹果已经开放了API给开发者定制属于自己APP的灵动岛功能。灵动岛截图显示 在截图时,灵动岛区域是否会出现在截图照片中吗?经过初步测试,如果灵动岛内无任务时,截图不会显示灵动岛灵动岛有任务时,截图会显示灵动岛要求和限制 一个LiveActivity可以激活长达8小时,除非App通过API或用户终止它,否则。超过此限制,系统将自动结束。当一个LiveActivity结束时,系统立即将其从灵动岛(DynamicIsland)中删除。然而,LiveActivity会一直保持在锁定屏幕上,直到用户删除它。 每个LiveActivity运行在自己的沙盒里,不像widget,不能获取网络或接受位置更新;要更新活跃的LiveActivity的动态数据,有两种方式:应用程序中使用ActivityKit框架;允许LiveActivity接收远程推送通知;灵动岛实现基本流程 注:获得远程推送更新需要用户授权开发框架配置 灵动岛开发除了依赖新增的LiveActivity框架,也需要依赖WidgetKit、SwiftUI,即你的App需要有一个小组件的ExtensionTarget,并且创建WidgetBundle,增加新的ActivityWidget;mainstructHyWidget:WidgetBundle{varbody:someWidget{HotWidget()UgcEntryWidget()新增LiveActivityCoffeeDeliveryActivityWidget()}} 此外,App的配置文件Info需要增加NSSupportsLiveActivities,并设置为true; ActivityAttributes ActivityAttributes相当于数据模型Model,具体细分为动态数据和静态数据;ActivityAttributes协议描述了出现在LiveActivity中的内容。它的内部类型ContentState表示LiveActivity的动态内容。 下面的例子展示了一个咖啡外卖应用程序的ActivityAttributes协议的实现。该应用程序的LiveActivity显示已订购的咖啡名称为静态数据,而CoffeeDeliveryStatus为动态数据,随着时间的推移而变化。structCoffeeDeliveryAttributes:ActivityAttributes{publicstructContentState:Codable,Hashable{varcurrentStatus:CoffeeDeliveryStatus}varcoffeeName:String}enumCoffeeDeliveryStatus:Codable,Sendable,CaseIterable{caserecieved,preparing,outForDeliveryvardisplayText:String{switchself{case。recieved:returnRecievedcase。preparing:returnBrewingcase。outForDelivery:returnOnitsway!}}varlongText:String{switchself{case。recieved:returnWeverecievedyourorder。case。preparing:returnOurbaristasarehardatworkbrewingupyourcup!case。outForDelivery:returnGetready,yourbrewisspeedingovertoyourightnow。}}}创建ActivityWidget显示视图 灵动岛有三种视图形式,从左到右依次是:紧凑视图最小视图扩展视图 三种视图之间可以进行切换;当一个人在动态岛中触摸并长按紧凑或最小视图时,以及当一个实时活动更新时,扩展视图就会出现。在不支持灵动岛的设备上,解锁屏幕展开的视图显示为LiveActivity更新的横幅。为了确保系统能够在每个位置显示你的APP的实时活动,APP编写代码时必须支持所有视图。扩展视图,由于区域空间较大,进一步分割出下面具体区域 每一部分均可程序定制展示内容;接下来了解代码如何实现各部分视图:structCoffeeDeliveryActivityWidget:Widget{varbody:someWidgetConfiguration{returnActivityConfiguration(for:CoffeeDeliveryAttributes。self){contextinCoffeeDeliveryActivityWidgetView(attributes:context。attributes,state:context。state)}dynamicIsland:{contextinDynamicIsland{DynamicIslandExpandedRegion(。leading,priority:。greatestFiniteMagnitude,content:{扩展区域的左侧视图})DynamicIslandExpandedRegion(。trailing,content:{扩展区域的右侧视图})}compactLeading:{紧凑视图左侧区域视图}compactTrailing:{紧凑视图右侧区域视图}minimal:{最小视图展示}}}} 其中ActivityConfiguration结构体是这部分的核心;publicstructActivityConfiguration:WidgetConfigurationwhereAttributes:ActivityAttributes ActivityConfiguration结构体遵循WidgetConfiguration协议,其中Attributes泛型参数遵循ActivityAttributes协议,而前面介绍过的CoffeeDeliveryAttributes就是ActivityAttributes协议的实现; ActivityConfiguration的初始化init方法如下所示:publicinitContent(forattributesType:Attributes。TypeAttributes。self,ViewBuildercontent:escaping(ActivityViewContext)Content,dynamicIsland:escaping(ActivityViewContext)DynamicIsland)whereContent:View 上面代码中就是实现了ActivityConfiguration的init方法,包含三个参数:attributesType指明需要传入的content模型类型,这里指定为CoffeeDeliveryAttributes。self;第二个参数content,指定一个闭包,它为出现在锁定屏幕上的活动创建视图。当你提醒某人更新的实时活动内容时,这个视图也会以横幅的形式出现在不支持灵动岛的设备的主屏幕上;第三个参数dynamicIsland,构建灵动岛的内部UI实现。 DynamicIsland结构体,用于构建灵动岛各部分具体UI;用于实现紧凑视图、最小视图、扩展视图的各部分UI;生命周期管理 ActivityKit中定义了Activity对象,用于管理LiveActivity从启动到状态更新、结束,完整的生命周期流程;启动APIpublicstaticfuncrequest(attributes:Attributes,contentState:Activity。ContentState,pushType:PushType?nil)throwsActivity示例Task{letattributesCoffeeDeliveryAttributes(coffeeName:coffeeName)letstateCoffeeDeliveryAttributes。ContentState(currentStatus:。recieved)do{tryawaitMainActor。run{letactivitytryActivityCoffeeDeliveryAttributes。request(attributes:attributes,contentState:state,pushType:nil)。。。。print(Startedactivity)}catch(leterror){print(Errorstartingactivity(error)(error。localizedDescription))}} 现在,让我们开始Activity,需要传入状态state和属性attributes,启动Activity。注意:这里特别区分attributes和state就是为了针对静态数据(attributes)和动态数据(state)分别处理,后续只有动态数据才会被更新。状态更新APIpublicfuncupdate(usingcontentState:Activity。ContentState)async示例funcupdateActivity(state:CoffeeDeliveryStatus){letstateCoffeeDeliveryAttributes。ContentState(currentStatus:state)Task{awaitliveActivity?。update(using:state)}} 更新动态数据。停止funcstop(){Task{awaitliveActivity?。end(using:nil,dismissalPolicy:。immediate)awaitMainActor。run{liveActivitynil}}} 立即停止liveActivity。跳转 灵动岛支持DeepLink,可以跳转进入App;具体来说:对于所有小组件,包括灵动岛,在小组件的视图层次结构中添加widgetURL(:)视图修饰符。如果小组件的视图层次结构包含多个widgetURL修饰符,则行为未定义。 对于使用WidgetFamily的小组件,如WidgetFamily。systemMedium,WidgetFamily。systemLarge或WidgetFamily。systemextrallarge,将一个或多个链接控件添加到小部件的视图层次结构中。可以同时使用widgetURL和Link控件。如果交互以Link控件为目标,则系统使用该控件中的URL。对于小部件中其他任何地方的交互,系统使用widgetURL视图修饰符中指定的URL。ViewBuildervarbody:someView{ZStack{AvatarView(entry。character)。widgetURL(entry。character。url)。foregroundColor(。white)}。background(Color。gameBackground)}适用场景初探 最后,我们从产品角度初步探讨一下LiveActivity及灵动岛的适用场景;可以发现不论是在灵动岛展示信息还是在锁屏界面展示信息,这类信息需要满足实时性较强,用户持续关注,比如正在进行中的比赛分数,正在配送的餐食还有多久送达;这类信息在一个相对较短时间段内、高频被更新,比较适合呈现在灵动岛;所以一般来说,下面细分类型的App适合增加LiveActivity及灵动岛的适配:体育赛事类App运动监测类App外卖配送类App总结 本篇文章完整介绍了创建灵动岛这一新的UI交互形式所需要的开发流程,开发者需要注意设计数据模型时,区分好哪些动态数据需要被更新,哪些静态数据保持不变;另外,我们也初步探讨了灵动岛的适用场景,对于那些产品形态需要及时更新状态信息的App,快速适配灵动岛,将会给用户带来更好的体验,值得尝试。参考https:developer。apple。comdocumentationactivitykitdisplayinglivedataonthelockscreenwithliveactivitieshttps:developer。apple。comdocumentationwidgetkitcreatingawidgetextension 作者:狐友技术团队 来源:微信公众号:搜狐技术产品 出处:https:mp。weixin。qq。comsgI2vgx9cXiIAND08OgZNzQ