0
点赞
收藏
分享

微信扫一扫

使用SwiftUI搭建一个倒计时App,让你做饭时不再焦虑~

在本章中,你将学会使用​​SwiftUI​​​搭建一个倒计时​​App​​。

项目背景

每逢周末,总要在家里煮顿饭,才对得起满冰箱的菜,和打扫得干干净净的厨房。

在做海鲜的时候,常常会需要准确计时,煮久了不好吃,煮得时间太短又不熟。

这时候,就需要有一个倒计时的​​App​​,帮助我们很好地控制时间。

那么本章,我们就来使用​​SwiftUI​​​搭建一个倒计时​​App​​。

项目搭建

首先,创建一个新的​​SwiftUI​​​项目,命名为​​CountDown​​。

使用SwiftUI搭建一个倒计时App,让你做饭时不再焦虑~_Swift

样式预览

使用SwiftUI搭建一个倒计时App,让你做饭时不再焦虑~_修饰符_02

背景圆环

背景圆环的样式,我们可以使用​​Circle​​圆形形状来搭建,示例:

// 背景圆环
func progressTrackView() -> some View {
Circle()
.fill(Color.clear)
.frame(width: 250, height: 250)
.overlay(Circle().stroke(Color.black.opacity(0.09), lineWidth: 15))
}

使用SwiftUI搭建一个倒计时App,让你做饭时不再焦虑~_SwiftUI_03

上述代码中,我们创建了一个新的视图​​progressTrackView​​。

我们使用​​Circle​​​构建背景圆环,使用​​fill​​​修饰符填充颜色去掉背景,再使用​​frame​​​修饰符设置大小,最后使用​​overlay​​修饰符赋予了圆环线宽做边框。

进度圆环

完成背景圆环后,我们来完成进度圆环。

首先我们需要两个倒计时参数,一个是总倒计时时间,一个是倒计时当前时间,示例:

@State var totalCountdown: CGFloat  = 30
@State var counter: Int = 10

然后我们还需要创建一个方法获得开始时的进度位置,示例:

// 获得开始进度
func startProgress() -> CGFloat {
return (CGFloat(counter) / CGFloat(totalCountdown))
}

同样,我们还需要创建一个方法来获得结束时的进度位置,示例:

// 获得结束进度
func completed() -> Bool {
return startProgress() == 1

完成这些基础准备后,我们就可以来构建进度圆环视图了,示例:

// 进度圆环
func progressBarView() -> some View {
Circle()
.fill(Color.clear)
.frame(width: 250, height: 250)
.overlay(
Circle()
.trim(from: 0, to: startProgress())
.stroke(style: StrokeStyle(lineWidth: 15, lineCap: .round, lineJoin: .round))
.rotationEffect(.init(degrees: -90))
.foregroundColor(
withAnimation(.easeInOut(duration: 0.2)) {
completed() ? Color.green

使用SwiftUI搭建一个倒计时App,让你做饭时不再焦虑~_SwiftUI_04

上述代码中,我们构建了一个进度圆环视图​​progressBarView​​。

我们依旧使用​​Circle​​​来构建圆环,我们在​​Circle​​​圆环的基础上​​overlay​​覆盖一个圆环,外边的圆环需要和背景圆环尺寸保持一致。

进度圆环使用​​trim​​​绘制进度,使用​​stroke​​​修饰符绘制边框,使用​​rotationEffect​​​进度旋转获得进度变化,使用​​foregroundColor​​​绘制背景颜色,当进度​​为0​​的时候变成绿色。

进度时间

完成背景圆环和进度圆环后,还需要显示当前的进度时间,我们可以创建一个方法来获得格式化的时间,示例:

// 获得格式化时间
func counterToMinutes() -> String {
let currentTime = Int(totalCountdown) - counter
let seconds = currentTime % 60
let minutes = Int(currentTime / 60)
return "\(minutes):\(seconds < 10 ? "0" : "")\(seconds)"

上述代码中,我们构建了一个格式化字符串的方法​​counterToMinutes​​,主要为了根据秒钟转换为格式化的字符串。

然后我们构建进度时间样式,示例:

// 进度时间
func progressTimeView()-> some View {
Text(counterToMinutes())
.font(.system(size: 48))
.fontWeight(.black)
}

使用SwiftUI搭建一个倒计时App,让你做饭时不再焦虑~_Swift_05

操作按钮

倒计时App的操作按钮和之前做过的计时器App的操作类似,一个开始按钮,点击开始按钮后,开始按钮变成暂停按钮。

另一个是重置按钮,点击重置后,回归初始状态。

首先我们需要先声明一个开始状态的参数,示例:

@State var isStart = false

然后使用​​Image​​和系统图标构建样式部分,示例:

// 操作按钮
func btnView() -> some View {
HStack(spacing: 55) {
// 开始按钮
Image(systemName: self.isStart ? "pause.fill" : "play.fill")
.font(.system(size: 40))
.foregroundColor(.white)
.frame(minWidth: 0, maxWidth: 80, minHeight: 0, maxHeight: 80)
.background(self.isStart ? .red : .green)
.clipShape(Capsule())
.onTapGesture {
self.isStart.toggle()
}

// 重置按钮
Image(systemName: "arrow.clockwise")
.font(.system(size: 40))
.foregroundColor(.white)
.frame(minWidth: 0, maxWidth: 80, minHeight: 0, maxHeight: 80)
.background(.blue)
.clipShape(Capsule())
.onTapGesture {
self.counter = 0
withAnimation(.default) {
self.totalCountdown = 30
}
}
}.padding(.bottom, 55)
}

使用SwiftUI搭建一个倒计时App,让你做饭时不再焦虑~_SwiftUI_06

上述代码中,我们构建了一个操作栏视图​​btnView​​。

这里使用​​HStack​​横向视图排布了2个按钮,当我们点击开始按钮时,样式会随​​isStart​​变化,以便于我们操作开始和暂停。

重置按钮,我们也加了一个点击事件,点击时将当前进度​​counter​​​设置为0,总进度​​totalCountdown​​设置回30。

开始计时

为达到倒计时效果,我们需要创建一个方法,当我们开始计时时,若当前进度小于总进度,则当前进度累加,示例:

// 开始计时
func startCounting() {
if self.isStart {
if (self.counter < Int(self.totalCountdown)) {
self.counter += 1
}else {
self.isStart.toggle()
}
}
}

然后我们声明一个变量,返回以给定间隔重复发出当前日期的发布者,示例:

@State var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

最后,我们将计时方法加到视图中,并排布已经创建好的元素。示例:

var body: some View {
VStack {
Spacer()
ZStack {
progressTrackView()
progressBarView()
progressTimeView()
}
Spacer()
btnView()
}.onReceive(timer) { time in
self.startCounting()
}
}

项目预览

使用SwiftUI搭建一个倒计时App,让你做饭时不再焦虑~_SwiftUI_07

恭喜你,完成了整个项目的全部内容!

快来动手试试吧。

如果本专栏对你有帮助,不妨点赞、评论、关注~

举报

相关推荐

0 条评论