Open djk3000 opened 1 year ago
小组件可以在主屏幕上实现内容展示和功能跳转。 系统会向小组件获取时间线,根据当前时间对时间线上的数据进行展示。点击正在展示的视觉元素可以跳转到APP内,实现对应的功能。
可以通过在主屏幕上长按点击编辑添加自己程序的小组件。
通过视频学习了一下怎么实现这个小组件。
import SwiftUI import WidgetKit struct ContentView: View { //创建一个组来共享这个数据 @AppStorage("streak", store: UserDefaults(suiteName: "group.com.shgbit.Widgetdemo")) var streak = 0 var body: some View { ZStack { Color.black .ignoresSafeArea() VStack(spacing: 60) { ZStack { Circle() .stroke(.white.opacity(0.1), lineWidth: 20) let pct = Double(streak) / 50 Circle() .trim(from: 0, to: pct) .stroke(.blue, style: StrokeStyle(lineWidth: 20, lineCap: .round,lineJoin: .round)) .rotationEffect(.degrees(-90)) VStack { Text("Streak") .font(.largeTitle) Text(String(streak)) .font(.system(size: 70)) .bold() } .foregroundColor(.white) } .padding(50) Button { streak += 1 //根据标识更新小部件 WidgetCenter.shared.reloadTimelines(ofKind: "WidgetExtension") } label: { ZStack { RoundedRectangle(cornerRadius: 20) .foregroundColor(.blue) .frame(height: 50) Text("+1") .foregroundColor(.white) } } } } } }
import WidgetKit import SwiftUI /** 一些方法和主程序联动的方法 */ struct DataService { @AppStorage("streak", store: UserDefaults(suiteName: "group.com.shgbit.Widgetdemo")) var streak = 0 func log() { streak += 1 } func progress() -> Int { return streak } } struct Provider: TimelineProvider { let data = DataService() /** 这是一个占位方法,用于返回定义的结构中的数据,以便在 Widget 预览时显示占位数据。 */ func placeholder(in context: Context) -> SimpleEntry { SimpleEntry(date: Date(), streak: data.progress()) } /** 这是获取快照数据的方法。当 Widget 处于更新周期之外或因其他原因需要立即更新时,系统会调用此方法。 */ func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) { let entry = SimpleEntry(date: Date(),streak: data.progress()) completion(entry) } /** 生成一个时间线,该时间线来控制多久之后刷新这个组件,这里是一小时刷一次,也可以通过和主程序的联动来刷新小组件界面 */ func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) { var entries: [SimpleEntry] = [] // Generate a timeline consisting of five entries an hour apart, starting from the current date. let currentDate = Date() for hourOffset in 0 ..< 5 { let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)! let entry = SimpleEntry(date: entryDate, streak: data.progress()) entries.append(entry) } let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) } } /** 数据结构 */ struct SimpleEntry: TimelineEntry { let date: Date let streak: Int } /** 小组件的View */ struct WidgetExtensionEntryView : View { var entry: Provider.Entry let data = DataService() var body: some View { // Text(entry.date, style: .time) // Text(String(data.progress())) ZStack { Circle() .stroke(.white.opacity(0.1), lineWidth: 20) let pct = Double(data.progress()) / 50 Circle() .trim(from: 0, to: pct) .stroke(.blue, style: StrokeStyle(lineWidth: 20, lineCap: .round,lineJoin: .round)) .rotationEffect(.degrees(-90)) VStack { Text("Streak") .font(.largeTitle) Text(String(data.progress())) .bold() } .foregroundColor(.white) } .padding(20) } } struct WidgetExtension: Widget { //标识用来和内部程序控制 let kind: String = "WidgetExtension" var body: some WidgetConfiguration { //这个闭包小部件的视图 StaticConfiguration(kind: kind, provider: Provider()) { entry in WidgetExtensionEntryView(entry: entry) .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.black) } //编辑组件时的名称 .configurationDisplayName("My Widget") .description("This is an example widget.") .supportedFamilies([.systemSmall,.systemLarge,.systemMedium]) //部件大小 } } /** 预览视图 */ struct WidgetExtension_Previews: PreviewProvider { static var previews: some View { WidgetExtensionEntryView(entry: SimpleEntry(date: Date(), streak: 1)) .previewContext(WidgetPreviewContext(family: .systemSmall)) } }
Widget 小组件
小组件可以在主屏幕上实现内容展示和功能跳转。 系统会向小组件获取时间线,根据当前时间对时间线上的数据进行展示。点击正在展示的视觉元素可以跳转到APP内,实现对应的功能。
可以通过在主屏幕上长按点击编辑添加自己程序的小组件。
实现
通过视频学习了一下怎么实现这个小组件。
知识点:
参考资料