SwiftUI100天:使用SwiftUI搭建一个单位转换App

简介: 在本章中,你将学会使用SwiftUI搭建一个单位转换App。

image.png

前言

为了更加熟悉和了解SwiftUI,本系列将从实战角度出发完成100个SwiftUI项目,方便大家更好地学习和掌握SwiftUI

这同时也是对自己学习SwiftUI过程的知识整理。

如有错误,以你为准。

项目搭建

首先,创建一个新的SwiftUI项目,命名为UnitConversion

image.png

逻辑分析

样式部分我们的思路很简单,我们输入一个数字,它可以是时、分、秒,然后系统会自动输出转换后的结果。

当然,为了让App更加灵活,我们可以设置输入的数字的单位,也可以指定输出内容的单位

页面样式

image.png

App标题

标题部分,我们使用Text文字作为标题,当然我们也可以使用Navigation的方式,示例:

// 标题
func titleView() -> some View {
    HStack {
        Text("时分秒转换")
            .font(.title)
            .fontWeight(.bold)
        Spacer()
    }
}
复制代码

image.png

单位转换菜单

为了让单位转换更加灵活,我们需要构建了一个转换菜单,供用户自定义转换单位

首先先声明转换菜单的默认值,示例:

@State var beforeMenu: String = "时"
@State var afterMenu: String = "秒"
复制代码

然后可以使用Menu菜单构建转换菜单的样式,示例:

// 输入值类型
func beforeMenuView() -> some View {
    Menu {
        Button("时") { self.beforeMenu = "时" }
        Button("分") { self.beforeMenu = "分" }
        Button("秒") { self.beforeMenu = "秒" }
    } label: {
        Label(beforeMenu, systemImage: "chevron.down")
            .foregroundColor(.gray)
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 10, maxHeight: 60)
            .background(Color(.systemGray6))
            .cornerRadius(8)
    }
}
// 输出值类型
func afterMenuView() -> some View {
    Menu {
        Button("时") { self.afterMenu = "时" }
        Button("分") { self.afterMenu = "分" }
        Button("秒") { self.afterMenu = "秒" }
    } label: {
        Label(afterMenu, systemImage: "chevron.down")
            .foregroundColor(.gray)
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 10, maxHeight: 60)
            .background(Color(.systemGray6))
            .cornerRadius(8)
    }
}
复制代码

image.png

上述代码中,我们使用Menu构建了2个菜单,转换前菜单默认为“”,转换后菜单默认为“”,而当我们点击菜单时,后重新给beforeMenuafterMenu赋值,就可以达到单位菜单切换的效果。

其他样式部分我们就很简单,使用系统自带的Image图标,做一个点击下拉的样式。整体交互如下:

image.png

数值输入框

数值输入部分,我们也需要提前声明两个变量存储转换前转换后的值,示例:

@State var beforeText: String = ""
@State var afterText: String = "0"
复制代码

另外为了展示效果,在数值输入前,我们可以声明一个变量来改变是否展示转换结果,示例:

@State var showResult: Bool = false
复制代码

然后是数值输入的样式,我们使用TextField作为输入框,接收用户输入的数值内容,示例:

// 输入输出值
func numberView() -> some View {
    HStack(spacing: 20) {
        TextField("请输入", text: $beforeText)
            .keyboardType(.decimalPad)
            .foregroundColor(.black)
            .font(.system(size: 17))
            .padding()
        Spacer()
        if showResult {
            Text("="+afterText+afterMenu)
                .foregroundColor(.black)
                .font(.system(size: 14))
                .padding()
        }
    }
    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 10, maxHeight: 120)
    .background(Color(.systemGray6))
    .cornerRadius(8)
}
复制代码

image.png

上述代码中,我们使用TextField作为数值输入框,然后接收到的输入内容绑定到beforeText参数,然后给TextField设置修饰符,键盘默认为数字键盘

对于转换后结果部分,我们在showResultTrue时展示,内容绑定afterText

整体样式布局

var body: some View {
    VStack(spacing: 20) {
        titleView()
        HStack {
            beforeMenuView()
            afterMenuView()
        }
        numberView()
        Spacer()
    }.padding(.horizontal)
}
复制代码

至此,样式部分我们就完成了。

计算方法

下面,我们来完成计算部分,计算部分也比较简单,我们知道时、分、秒的转换都是60的倍数,我们用最简单的逻辑书写公式,示例:

// 计算方法
func calculateMethod() {
    if beforeMenu == "时" && afterMenu == "分" {
        afterText = String((Double(beforeText) ?? 0) * 60)
    } else if beforeMenu == "时" && afterMenu == "秒" {
        afterText = String((Double(beforeText) ?? 0) * 3600)
    } else if beforeMenu == "分" && afterMenu == "秒" {
        afterText = String((Double(beforeText) ?? 0) * 60)
    } else if beforeMenu == "分" && afterMenu == "时" {
        afterText = String((Double(beforeText) ?? 0) / 60)
    } else if beforeMenu == "秒" && afterMenu == "分" {
        afterText = String((Double(beforeText) ?? 0) / 60)
    } else if beforeMenu == "秒" && afterMenu == "时" {
        afterText = String((Double(beforeText) ?? 0) / 3600)
    } else {
        afterText = beforeText
    }
}
复制代码

然后将计算方法使用在我们输入值改变时调用我们计算的方法,示例:

.onChange(of: beforeText) { _ in
    if beforeText != "" {
        self.showResult = true
        calculateMethod()
    } else {
        self.showResult = false
    }
}
复制代码

完成后,我们预览下项目成果。

项目预览

image.png

不错不错!


相关文章
|
iOS开发
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(五)(3)
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(五)
160 0
|
前端开发 数据处理 iOS开发
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(五)(2)
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(五)
92 0
|
iOS开发 Kotlin 容器
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(五)(1)
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(五)
125 0
|
存储 缓存 前端开发
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(四)(2)
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(四)
128 0
|
前端开发 Swift iOS开发
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(四)(1)
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(四)
206 0
|
存储 PHP Swift
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(三)(2)
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(三)
167 0
|
前端开发 iOS开发
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(三)(1)
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(三)
153 0
|
iOS开发 开发者 容器
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(二)(2)
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(二)
141 0
|
iOS开发
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(二)(1)
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(二)
135 0
|
Swift iOS开发 容器
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(一)(3)
实战编程·使用SwiftUI从0到1完成一款iOS笔记App(一)
165 0