Skip to main content

简单的天气预报App – 原型设计

SIMPLE WEATHER APP SWIFTUI – PROTOTYPING
前面三讲里面基本上完成了OpenWeatherMap API的数据请求和处理。本片我们暂时放下Swift,看看SwiftUI中的原型搭建和设计。

新建一个空白的项目,并且新建一个Swift UI文件,PrototypingView.swift。

修改App的默认启动Swift UI界面为PrototypingView()。

Swift
//  SwiftUITestApp.swift
//  SwiftUITest

import SwiftUI

@main
struct SwiftUITestApp: App {
    var body: some Scene {
        WindowGroup {
            PrototypingView()
//            ContentView()
        }
    }
}

接下来用Swift UI的基本元素来搭建界面原型。

Swift
//  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组件。

Swift
            HStack {
                VStack {
                    Text("Humidity")
                    Text("Pressure")
                }
                
                VStack {
                    Text("Wind")
                    Text("Wind")
                }
            }

细心点你就能发现,我们把所有的组件都直接放到了ZStack中,ZStack默认渲染是居中向上(向屏幕到眼睛的方向z轴上堆叠渲染)。所以我们需要在ZStack的背景后加入一个VStack,并在这个总容器中做元素的排版。

经过修改后,我们的代码如下,我建议大家自己在Live Preview中测试每行代码的作用,更改参数后会出现什么样的结果。

Swift
    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()。

Swift
//  ContentView.swift
//  SwiftUITest
import SwiftUI

struct ContentView: View {
    var body: some View {
        ZStack {
            Image("BgImage")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .edgesIgnoringSafeArea(.all)
            
            VStack {
            //......
            }

我们向项目中拖入一张背景图片,大家按照自己的需求自行选择。

完整代码如下,我们获得了一个基本看得过得去的天气界面:

Swift
//  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!

API, Apple, Linux, Programming, Swift, Tutorial, Xcode