Dynamic Island
Learn how EasyAppSwiftUI builds Dynamic Island experiences
Overview
EasyAppWidgetLiveActivity leverages ActivityKit to deliver Lock Screen banners and Dynamic Island experiences. This guide covers how EasyAppWidgetAttributes and reusable components power the Dynamic Island layout and how to keep the main app and extension in sync.
Architecture
- Widget configuration
EasyAppWidgetLiveActivitydeclares anActivityConfiguration, supplying views for both Lock Screen anddynamicIslandcontexts. - View components Live Island regions live in
EasyAppSwiftUI/EasyAppWidget/WidgetsComponents/LiveActivityComponents.swift. - Data model
EasyAppWidgetAttributesandEasyAppWidgetAttributes.ContentStatemust remain identical between the main app and widget extension; a mismatch leads to decoding failures.
Key Structure
struct EasyAppWidgetLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: EasyAppWidgetAttributes.self) { context in
LiveActivityLockScreen(
attributes: context.attributes,
state: context.state
)
.activityBackgroundTint(.clear)
.activitySystemActionForegroundColor(.primary)
} dynamicIsland: { context in
DynamicIsland {
DynamicIslandExpandedRegion(.leading) {
LiveActivityExpandedLeading(
attributes: context.attributes,
state: context.state
)
}
DynamicIslandExpandedRegion(.trailing) {
LiveActivityExpandedTrailing(
attributes: context.attributes,
state: context.state
)
}
DynamicIslandExpandedRegion(.bottom) {
LiveActivityExpandedBottom(
attributes: context.attributes,
state: context.state
)
}
} compactLeading: {
LiveActivityCompactLeading(attributes: context.attributes, state: context.state)
} compactTrailing: {
LiveActivityCompactTrailing(attributes: context.attributes, state: context.state)
} minimal: {
LiveActivityMinimal(attributes: context.attributes, state: context.state)
}
.widgetURL(URL(string: "easyapp://live-activity?path=live-activity"))
.keylineTint(.blue)
}
}
}.widgetURLprovides a tap target that can be replaced with your own deep link..keylineTintcontrols the keyline color; align this with brand accents.
Region Components
- Expanded regions (
LiveActivityExpandedLeading/Trailing/Bottom) present primary content, metrics, and actions; customize them using data from attributes and state. - Compact regions (
LiveActivityCompactLeading/Trailing) condense information into icons and short labels for the collapsed island. - Minimal region (
LiveActivityMinimal) uses an animated gradient background with the emoji for subtle status feedback. - Lock Screen banner (
LiveActivityLockScreen) shares the same attributes and offers space for additional action cards.
Data & Updates
EasyAppWidgetAttributesdescribes static details such as the user name or task label.EasyAppWidgetAttributes.ContentStatecarries live fields (emoji, progress). Update the state viaActivity.update(using:)to refresh the island.- Keep the following files synchronized across targets:
EasyAppSwiftUI/Common/EasyAppWidgetAttributes.swiftEasyAppWidget/Common/EasyAppWidgetAttributes.swiftConsistency is critical; the Live Activity will fail if either side changes fields without matching the other (see previous fix experience).
Launch & Debug
- Request a Live Activity from the main app:
let activity = try Activity<EasyAppWidgetAttributes>.request( attributes: EasyAppWidgetAttributes(name: "World"), contentState: EasyAppWidgetAttributes.ContentState(emoji: "😀"), pushType: nil ) - Run the
EasyAppWidgetExtensionscheme on hardware or a simulator that supports Dynamic Island (iPhone 14 Pro or later). - Use
#Previewblocks with.dynamicIsland(.compact/.expanded/.minimal)in Xcode to verify layouts. - Call
activity.update(using:)to push state changes and observe Dynamic Island animations.
Design Tips
- Follow Human Interface Guidelines: keep compact labels to ~6–8 characters to prevent clipping.
- Use helpers like
AnimatedProgressBarandPulsingStatusIndicatorto show real-time metrics. - Apply
.buttonStyle(PlainButtonStyle())to action buttons so Dynamic Island commands blend with the glassmorphic look. - Prepare localized strings in
EasyAppWidgetAttributesor viaLocalizedStringResourcewhen supporting multiple locales.
Troubleshooting
- Live Activity fails to start: ensure
NSSupportsLiveActivities = trueis set in the main appInfo.plistand test on real devices when possible. - Decoding errors: confirm
EasyAppWidgetAttributes.ContentStatematches between app and extension (past issues arose from mismatched fields). - Missing actions: verify
DynamicIslandExpandedRegionclosures actually return the desired buttons and that they trigger logic. - Preview build failures: supply mock data or guard runtime-only code with
#if DEBUG.
Refer to the multiple #Preview blocks at the bottom of LiveActivityComponents.swift for compact, expanded, and Lock Screen samples.
Last updated on