Text 控件
系统 Text控件 自带有时间计算的功能
优点: 不需要额外设置,系统级别刷新时间
缺点: 不能自定义
style | 例子 | 说明 |
---|---|---|
time | 12:00 AM 时分 | 时分 上午/下午 |
date | date June 3, 2019 | 年月日 |
relative | 2 houers, 23 min/1 year, 1 month | 写入日期对比现在日期的差多少 格式是 时分/年月 |
offset | +2 hours/-3 months | 写入日期对比现在日期的差多少 格式是 +多少/-多少 |
timer | 10:30:11 | 时分秒 |
效果
实现
import WidgetKit
import SwiftUI
import Intents
struct TimerClockProvider: IntentTimelineProvider {
func placeholder(in context: Context) -> TimerClockEntry {
TimerClockEntry(date: Date(), configuration: TimerClockIntent(), displaySize: context.displaySize)
}
func getSnapshot(for configuration: TimerClockIntent, in context: Context, completion: @escaping (TimerClockEntry) -> ()) {
let entry = TimerClockEntry(date: Date(), configuration: configuration, displaySize: context.displaySize)
completion(entry)
}
func getTimeline(for configuration: TimerClockIntent, in context: Context, completion: @escaping (Timeline) -> ()) {
var entries: [TimerClockEntry] = []
// 系统 text .timer
let currentDate = Date()
let entryDate = Calendar.current.date(byAdding: .hour, value: 1, to: currentDate)!
let entry = TimerClockEntry(date: entryDate, configuration: configuration, displaySize: context.displaySize)
entries.append(entry)
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
struct TimerClockEntry: TimelineEntry {
let date: Date
let configuration: TimerClockIntent
let displaySize: CGSize
}
// MARK: - Entry
struct TimerClockEntryView : View {
var entry: TimerClockProvider.Entry
var body: some View {
return VStack(alignment: .center) {
// 系统 text .timer
TimerClockView()
}
.background(
Rectangle().fill(Color.black)
.frame(width: entry.displaySize.width, height: entry.displaySize.height, alignment: .center)
)
}
}
// MARK: WidgetConfiguration
struct TimerClock: Widget {
let kind: String = "TimerClock"
var title: String = ""
var desc: String = ""
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: TimerClockIntent.self, provider: TimerClockProvider()) { entry in
TimerClockEntryView(entry: entry)
}
.configurationDisplayName(title)
.description(desc)
.supportedFamilies([.systemSmall])
}
}
struct TimerClockView: View {
var body: some View {
VStack {
Spacer()
Text("text .timer")
.foregroundColor(.red)
Spacer()
Text(Date().getCurrentDayStart(true), style: .timer)
.multilineTextAlignment(.center)
.foregroundColor(.red)
Spacer()
}
}
}
//获取当天开始的日期,给Date增加一个拓展方法
extension Date {
func getCurrentDayStart(_ isDayOf24Hours: Bool)-> Date {
let calendar:Calendar = Calendar.current;
let year = calendar.component(.year, from: self);
let month = calendar.component(.month, from: self);
let day = calendar.component(.day, from: self);
let components = DateComponents(year: year, month: month, day: day, hour: 0, minute: 0, second: 0)
return Calendar.current.date(from: components)!
}
}
添加TimeLine
添加TimeLine 让小组件定时刷新
优点: 可以自定义UI
缺点: 因为小组件刷新机制限制,小组件会卡顿。
小组件一天可以刷新40至70次。在iOS 16以下系统。可以设置一天的TimeLine。即是((24 * 60 * 60)/70)。所以iOS 16之后只能设置((24 * 60 * 60)/40)。所以会导致小组件有时候卡顿,不刷新。
TimelineReloadPolicy
let timeline = Timeline(entries: entries, policy: .never)
TimelineReloadPolicy | 说明 |
---|---|
atEnd | 等最后一个timeline 执行完刷新 |
never | 不自动重新加载 |
after | 指定时间刷新 |
倒计时小组件
在 getTimeline 设置刷新机制。 一分钟刷新
for hourOffset in 0 ..< 61 {
let entryDate = Calendar.current.date(byAdding: .second, value: hourOffset, to: currentDate)!
let num = 60 - hourOffset
let entry = CountdownClockEntry(date: entryDate, configuration: configuration, displaySize: context.displaySize, num: num)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .never)
效果
实现
import WidgetKit
import SwiftUI
import Intents
struct CountdownClockProvider: IntentTimelineProvider {
func placeholder(in context: Context) -> CountdownClockEntry {
CountdownClockEntry(date: Date(), configuration: CountdownClockIntent(), displaySize: context.displaySize, num: 0)
}
func getSnapshot(for configuration: CountdownClockIntent, in context: Context, completion: @escaping (CountdownClockEntry) -> ()) {
let entry = CountdownClockEntry(date: Date(), configuration: configuration, displaySize: context.displaySize, num: 0)
completion(entry)
}
func getTimeline(for configuration: CountdownClockIntent, in context: Context, completion: @escaping (Timeline) -> ()) {
var entries: [CountdownClockEntry] = []
// 倒计时
let currentDate = Date()
for hourOffset in 0 ..< 61 {
let entryDate = Calendar.current.date(byAdding: .second, value: hourOffset, to: currentDate)!
let num = 60 - hourOffset
let entry = CountdownClockEntry(date: entryDate, configuration: configuration, displaySize: context.displaySize, num: num)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .never)
completion(timeline)
}
}
struct CountdownClockEntry: TimelineEntry {
let date: Date
let configuration: CountdownClockIntent
let displaySize: CGSize
let num: Int
}
// MARK: - Entry
struct CountdownClockEntryView : View {
var entry: CountdownClockProvider.Entry
var body: some View {
return VStack(alignment: .center) {
// 倒计时
CountdownDemo(countdown: entry.num)
}
.background(
Rectangle().fill(Color.black)
.frame(width: entry.displaySize.width, height: entry.displaySize.height, alignment: .center)
)
}
}
// MARK: WidgetConfiguration
struct CountdownClock: Widget {
let kind: String = "CountdownClock"
var title: String = ""
var desc: String = ""
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: CountdownClockIntent.self, provider: CountdownClockProvider()) { entry in
CountdownClockEntryView(entry: entry)
}
.configurationDisplayName(title)
.description(desc)
.supportedFamilies([.systemSmall])
}
}
// MARK: - 倒计时
struct CountdownDemo: View {
var countdown: Int
var body: some View {
VStack {
Spacer()
Text("倒计时")
.foregroundColor(.red)
Spacer()
Text(countdown.description)
.multilineTextAlignment(.center)
.foregroundColor(.red)
Spacer()
}
}
}
时钟小组件
效果
实现
import WidgetKit
import SwiftUI
import Intents
struct CustomClockProvider: IntentTimelineProvider {
func placeholder(in context: Context) -> CustomClockEntry {
CustomClockEntry(date: Date(), configuration: CustomClockIntent(), displaySize: context.displaySize)
}
func getSnapshot(for configuration: CustomClockIntent, in context: Context, completion: @escaping (CustomClockEntry) -> ()) {
let entry = CustomClockEntry(date: Date(), configuration: configuration, displaySize: context.displaySize)
completion(entry)
}
func getTimeline(for configuration: CustomClockIntent, in context: Context, completion: @escaping (Timeline) -> ()) {
var entries: [CustomClockEntry] = []
// 自定义
let currentDate = Date()
// 小组件 一天有 40 ~ 70 次刷新机会
var time = ((24 * 60 * 60)/40)
if #available(iOS 16, *) {
time = ((24 * 60 * 60)/70)
}
for hourOffset in 0 ..< time {
let entryDate = Calendar.current.date(byAdding: .second, value: hourOffset, to: currentDate)!
let entry = CustomClockEntry(date: entryDate, configuration: configuration, displaySize: context.displaySize)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
struct CustomClockEntry: TimelineEntry {
let date: Date
let configuration: CustomClockIntent
let displaySize: CGSize
}
// MARK: - Entry
struct CustomClockEntryView : View {
@State var index = 0
@State var start: Date = Date()
var entry: CustomClockProvider.Entry
var body: some View {
let calendar = Calendar.current
let dateComponents = calendar.dateComponents([.hour, .minute, .second], from: entry.date)
var hour:Int = 0
var min:Int = 0
var second:Int = 0
if let h = dateComponents.hour,
let m = dateComponents.minute,
let s = dateComponents.second {
hour = h
min = m
second = s
}
return VStack(alignment: .center) {
// 自定义
CustomClockDemo(hour: hour, min: min, second: second)
}
.background(
Rectangle().fill(Color.black)
.frame(width: 300, height: 300, alignment: .center)
)
}
}
// MARK: WidgetConfiguration
struct CustomClock: Widget {
let kind: String = "CustomClock"
var title: String = ""
var desc: String = ""
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: CustomClockIntent.self, provider: CustomClockProvider()) { entry in
CustomClockEntryView(entry: entry)
}
.configurationDisplayName(title)
.description(desc)
.supportedFamilies([.systemSmall])
}
}
// MARK: - CustomClock
struct CustomClockDemo: View {
var hour: Int = 0
var min: Int = 0
var second: Int = 0
var body: some View {
VStack {
Spacer()
Text("自定义")
.foregroundColor(.red)
Spacer()
Text("\(hour):\(min):\(second)")
.foregroundColor(.red)
Spacer()
}
}
}
Github地址
懒得打的可以直接打开项目查看 Github地址 https://github.com/HahnLoving/iOS_Study