简单的天气预报App – 原型设计
SIMPLE WEATHER APP SWIFTUI – PROTOTYPING
前面三讲里面基本上完成了OpenWeatherMap API的数据请求和处理。本片我们暂时放下Swift,看看SwiftUI中的原型搭建和设计。
新建一个空白的项目,并且新建一个Swift UI文件,PrototypingView.swift。
修改App的默认启动Swift UI界面为PrototypingView()。
// SwiftUITestApp.swift
// SwiftUITest
import SwiftUI
@main
struct SwiftUITestApp: App {
var body: some Scene {
WindowGroup {
PrototypingView()
// ContentView()
}
}
}
接下来用Swift UI的基本元素来搭建界面原型。
// PrototypingView.swift
// SwiftUITest
import SwiftUI
struct PrototypingView: View {
var body: some View {
ZStack() {
//背景
Rectangle()
.fill(Color.gray)
.edgesIgnoringSafeArea(.all)
//天气主块
VStack {
Text("City name")
Text("24°C")
.font(.system(size: 60))
Text("icon")
Text("Weather")
Text("Max & Min")
}
.frame(width:260, height: 280)
.background(Color.white)
}
}
}
struct PrototypingView_Previews: PreviewProvider {
static var previews: some View {
PrototypingView()
}
}
简单的几行代码,我们先建立一个ZStack(),SwiftUI的ZStack是一种堆叠方式,它将子视图在Z轴上重叠排列,这是3D内容的轴线。它对于创建重叠的内容很有用,比如图片上的文字。它的工作方式与其他两种堆叠类型,VStack和HStack完全相同。
ZStack中越靠前的代码越先被渲染,越靠后的代码相当于“堆叠在屏幕最上层”。所以在设计相互堆叠的UI内容时,需要注意ZStack中代码的先后顺序。
我们获取的内容还有湿度,风速,日出等等数据。简单的用块状先描述一下。
添加一个HStack,并且在内部添加两个VStack,每个VStack中添加两个Text组件。
HStack {
VStack {
Text("Humidity")
Text("Pressure")
}
VStack {
Text("Wind")
Text("Wind")
}
}
细心点你就能发现,我们把所有的组件都直接放到了ZStack中,ZStack默认渲染是居中向上(向屏幕到眼睛的方向z轴上堆叠渲染)。所以我们需要在ZStack的背景后加入一个VStack,并在这个总容器中做元素的排版。
经过修改后,我们的代码如下,我建议大家自己在Live Preview中测试每行代码的作用,更改参数后会出现什么样的结果。
var body: some View {
ZStack() {
//背景
Rectangle()
.fill(Color.gray)
.edgesIgnoringSafeArea(.all)
VStack {
//天气主块
VStack {
Text("City name")
Text("24°C")
.font(.system(size: 60))
Text("icon")
Text("Weather")
Text("Max & Min")
}
.frame(width:260, height: 200)
.background()
//分割上下部分的站位空间
Spacer()
HStack {
//湿度和气压
VStack {
Text("Humidity")
Text("Pressure")
}
.padding()
.background()
.frame(maxWidth: .infinity)
//风速和风向
VStack {
Text("Wind Speed")
Text("Wind deg")
}
.padding()
.background()
.frame(maxWidth: .infinity)
}
//日出日落时间
HStack {
Text("sunrise time")
Text("sunset time")
}
.padding()
.background()
}
.padding()
}
}
结果是下图这个结构。直径所有的数据元素都已经放到了界面中,我们可以考虑一下详细设计了。按照我个人的习惯我还是会在这个UI原型项目中完成,在完全确定界面构成之前我一般不会在生产项目中修改代码。
接下来,我们去项目默认自带的ContentView(),逐步构造界面元素。同时别忘记吧App默认启动的视图切换到ContentView()。
// ContentView.swift
// SwiftUITest
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack {
Image("BgImage")
.resizable()
.aspectRatio(contentMode: .fill)
.edgesIgnoringSafeArea(.all)
VStack {
//......
}
我们向项目中拖入一张背景图片,大家按照自己的需求自行选择。
完整代码如下,我们获得了一个基本看得过得去的天气界面:
// ContentView.swift
// SwiftUITest
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack {
Image("BgImage")
.resizable()
.aspectRatio(contentMode: ContentMode.fill)
.edgesIgnoringSafeArea(.all)
.frame(maxWidth: UIScreen.main.bounds.width)
VStack {
VStack {
Text("Nagoya, JP")
.font(.system(size: 20, weight: .medium))
.opacity(0.5)
Text("12°C")
.font(.system(size: 100, weight: .light, design: .serif))
.opacity(0.75)
Image(systemName: "cloud")
.font(.system(size: 50))
.padding(.bottom, 1)
.opacity(0.75)
Text("Clouds, Overcast Clouds")
.font(.system(size: 16))
.opacity(0.75)
HStack {
Text("H: 12°C")
.opacity(0.75)
Text("L: 8°C")
.opacity(0.75)
}
}
.padding(.all, 40)
.background(Color.white.opacity(0.25))
.cornerRadius(20)
.padding(.all, 10)
Spacer()
VStack{
HStack {
VStack(alignment: .leading) {
Text("Pressure: 1024 pHa")
.font(.system(size: 15))
Text("Humidity: 77%")
.font(.system(size: 15))
}
.padding()
.background(Color.white.opacity(0.5))
.cornerRadius(10)
Spacer()
VStack(alignment: .leading) {
Text("Wind Speed: 6m/s")
.font(.system(size: 15))
Text("Wind Direction: 30°C")
.font(.system(size: 15))
}
.padding()
.background(Color.white.opacity(0.5))
.cornerRadius(10)
}
.frame(maxWidth: .infinity)
HStack (){
Text("Sunrise: 06:26")
.font(.system(size: 15))
Spacer()
Image(systemName: "sun.and.horizon")
Spacer()
Text("Sunset: 19:44")
.font(.system(size: 15))
}
.padding(.vertical, 10)
.padding(.horizontal, 20)
.background(Color.white.opacity(0.5))
.cornerRadius(10)
.padding(.top, 6)
}
}.padding(20)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
下面我们吧这个原型实现到真实数据的项目中。
Happy coding!