美文网首页iOS17适配指南
iOS17适配指南之Widget

iOS17适配指南之Widget

作者: YungFan | 来源:发表于2023-08-20 09:00 被阅读0次

    介绍

    • 增加containerBackground修饰符可以设置 Widget 的背景。
    • 增加widgetContentMargins环境变量可以设置 Widget 的边距。
    • 重要更新:可以通过AppIntent在不打开 App 的情况下进行交互操作,但交互的 View 目前仅支持 Button 与 Toggle。
    extension Button {
        public init<I: AppIntent>(
            intent: I,
            @ViewBuilder label: () -> Label
        )
    }
    
    extension Toggle {
        public init<I: AppIntent>(
            isOn: Bool,
            intent: I,
            @ViewBuilder label: () -> Label
        )
    }
    

    案例

    效果

    效果图.gif

    实现

    import AppIntents
    import Foundation
    import SwiftUI
    import WidgetKit
    
    // MARK: - Model
    class Counter {
        @AppStorage("count", store: UserDefaults(suiteName: "Widget2023")) static var count = 0
    
        static func incrementCount() {
            count += 1
        }
    
        static func decrementCount() {
            count -= 1
        }
    
        static func currentCount() -> Int {
            return count
        }
    }
    
    
    
    // MARK: - AppIntent
    struct CountIntent: AppIntent {
        static var title: LocalizedStringResource = "CountIntent"
        static var description: IntentDescription = IntentDescription("CountIntent")
    
        // AppIntent的输入参数
        @Parameter(title: "isIncrement")
        var isIncrement: Bool
    
        init() {
        }
    
        init(isIncrement: Bool) {
            self.isIncrement = isIncrement
        }
    
        func perform() async throws -> some IntentResult {
            if isIncrement {
                Counter.incrementCount()
            } else {
                Counter.decrementCount()
            }
            return .result()
        }
    }
    
    
    
    // 宿主App
    struct ContentView: View {
        @Environment(\.scenePhase) private var phase
        @State private var count = 0
    
        var body: some View {
            VStack {
                Text("Count: \(count)")
                    .font(.largeTitle)
                    .foregroundStyle(.primary)
    
                HStack {
                    Button {
                        count += 1
                        Counter.incrementCount()
                        WidgetCenter.shared.reloadAllTimelines()
                    } label: {
                        Image(systemName: "plus")
                            .font(.largeTitle)
                    }
    
                    Button {
                        count -= 1
                        Counter.decrementCount()
                        WidgetCenter.shared.reloadAllTimelines()
                    } label: {
                        Image(systemName: "minus")
                            .font(.largeTitle)
                    }
                }
            }
            .padding()
            .onChange(of: phase) {
                count = Counter.currentCount()
            }
        }
    }
    
    
    
    // MARK: - Widget
    struct Provider: TimelineProvider {
        func placeholder(in context: Context) -> SimpleEntry {
            SimpleEntry(date: Date(), count: "\(Counter.currentCount())")
        }
    
        func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) {
            let entry = SimpleEntry(date: Date(), count: "\(Counter.currentCount())")
            completion(entry)
        }
    
        func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
            let timeline = Timeline(entries: [SimpleEntry(date: Date(), count: "\(Counter.currentCount())")], policy: .atEnd)
            completion(timeline)
        }
    }
    
    struct SimpleEntry: TimelineEntry {
        let date: Date
        let count: String
    }
    
    struct CountWidgetEntryView: View {
        // iOS17新增环境变量,设置边距
        @Environment(\.widgetContentMargins) var margins
        var entry: Provider.Entry
    
        var body: some View {
            VStack {
                Text("Count: \(entry.count)")
    
                HStack {
                    // 交互
                    Button(intent: CountIntent(isIncrement: true)) {
                        Image(systemName: "plus.circle")
                    }
    
                    Button(intent: CountIntent(isIncrement: false)) {
                        Image(systemName: "minus.circle")
                    }
                }
                .font(.largeTitle)
            }
            .containerBackground(.fill.tertiary, for: .widget) // iOS17新增,设置小组件背景
            .padding(.top, margins.top) // 设置顶部边距
        }
    }
    
    struct CountWidget: Widget {
        let kind: String = "CountWidget"
    
        var body: some WidgetConfiguration {
            StaticConfiguration(kind: kind, provider: Provider()) { entry in
                CountWidgetEntryView(entry: entry)
            }
            .configurationDisplayName("CountWidget")
            .description("This is a CountWidget.")
        }
    }
    
    // MARK: - 预览
    #Preview(as: .systemSmall) {
        CountWidget()
    } timeline: {
        SimpleEntry(date: .now, count: "99")
    }
    
    #Preview(as: .systemMedium) {
        CountWidget()
    } timeline: {
        SimpleEntry(date: .now, count: "99")
    }
    
    #Preview(as: .systemLarge) {
        CountWidget()
    } timeline: {
        SimpleEntry(date: .now, count: "99")
    }
    

    相关文章

      网友评论

        本文标题:iOS17适配指南之Widget

        本文链接:https://www.haomeiwen.com/subject/csczpdtx.html