用SwiftUI寫一個簡單頁面

級別:★☆☆☆☆
標簽:「iOS 13」「SwiftUI」「Xcode 11.1」
作者: 647
審校: QiShare團隊


前言:
之前同事WYongW寫了一篇《用Flutter寫一個簡單頁面》翰绊,本篇將和大家一起調(diào)研一下蘋果今年推出的SwiftUI框架漠魏。
接下來,讓我們一起入門一下SwiftUI(嘗嘗鮮)。


一溃肪、SwiftUI是什么啥寇?

1. 定義:

簡單來說荠藤,SwiftUI是蘋果在“WWDC-2019”推出的一款全新的“聲明式UI”框架斩个。
拆開看,Swift + UI脓恕。(由此可以看出Swift越來越重要)

2. 特點:
  • “簡潔迅速”的Swift:越來越簡潔的Swift語法膜宋,配上Swift迅速的優(yōu)勢。

  • “即視”的UI:降低調(diào)試成本炼幔,一邊寫code秋茫、一邊就可查看UI

  • 跨平臺:一套代碼乃秀,即可完成iOS肛著、iPadOS圆兵、macOSwatchOS的開發(fā)與適配策泣。

  • “聲明式”編程

簡單來說衙傀,對比之前的“指令式”編程抬吟,我們通常需要告訴計算機“怎么做”萨咕?
“聲明式”編程是讓我們告訴計算機“做什么”?(至于最底層怎么做火本,我們無需關(guān)心危队。)

舉個例子,對于寫UI而言钙畔,

  • 指令式編程:就是茫陆,怎么畫?把每個frame擎析、layout等等統(tǒng)統(tǒng)需要計算到位簿盅。
  • 聲明式編程:就是,畫什么揍魂?把想要的效果描述出來桨醋,其他都交給框架去做。
3. 開發(fā)環(huán)境:

這么新的技術(shù)肯定需要環(huán)境的支持现斋。SwiftUI所需要的開發(fā)環(huán)境喜最,如下:

  • Xcode:Xcode 11.1+
  • MacOS:MacOS 10.15+庄蹋。
  • iOS:iOS 13+瞬内。

PS:由于SwiftUI只能應(yīng)用與iOS 13系統(tǒng)以上的設(shè)備。
因此限书,這項技術(shù)不建議用在需要適配低版本(iOS 13 以下)的App上虫蝶。
不過如果是無需適配低版本的新項目,或者學(xué)習(xí)者全可以上手“玩一玩”倦西。
畢竟蘋果的新技術(shù)還是很有意思的嘛~

二秉扑、SwiftUI的基本組件(語法)

這塊知識比較“基礎(chǔ)”且“重要”。只有記住了這些基本組件调限,我們才能用較少的代碼開發(fā)出精美的App舟陆。

下面,我將給大家介紹一些重要的SwiftUI組件:

組件介紹:

名稱 含義
Text 用來顯示文本的組件耻矮,類似UIKit中的UILabel秦躯。
Image 用來展示圖片的組件,類似UIKit中的UIImageView裆装。
Button 用于可點擊的按鈕組件踱承,類似UIKit中的UIButton倡缠。
List 用來展示列表的組件,類似UIKit中的UITableView茎活。
ScrollView 用來支持滑動的組件昙沦,類似UIKit中的UIScrollView
Spacer 一個靈活的空間载荔,用來填充空白的組件盾饮。
Divider 一條分割線,用來劃分區(qū)域的組件懒熙。
VStack 將子視圖按“豎直方向”排列布局丘损。(Vertical stack
HStack 將子視圖按“水平方向”排列布局。(Horizontal stack
ZStack 將子視圖按“兩軸方向均對齊”布局(居中工扎,有重疊效果)

基本組件:

  • Text:用來顯示文本的組件徘钥,類似UIKit中的UILabel
Text("Hello, we are QiShare!").foregroundColor(.blue).font(.system(size: 32.0))
  • Image:用來展示圖片的組件肢娘,類似UIKit中的UIImageView呈础。
Image.init(systemName: "star.fill").foregroundColor(.yellow)
  • Button:用于可點擊的按鈕組件,類似UIKit中的UIButton橱健。
Button(action: { self.showingProfile.toggle() }) {
    Image(systemName: "paperplane.fill")
        .imageScale(.large)
        .accessibility(label: Text("Right"))
        .padding()
}
  • List:用來展示列表的組件而钞,類似UIKit中的UITableView
List(0..<5){_ in
        NavigationLink.init(destination: VStack(alignment:.center){
            Image.init(systemName: "\(item+1).square.fill").foregroundColor(.green)
            Text("詳情界面\(item + 1)").font(.system(size: 16))
    }) {
          //ListRow
       }
  • ScrollView:用來支持滑動的組件畴博,類似UIKit中的UIScrollView笨忌。

  • Spacer:一個靈活的空間,用來填充空白的組件俱病。

  • Divider:一條分割線官疲,用來劃分區(qū)域的組件。

布局組件:

  • VStack:將子視圖按“豎直方向”布局亮隙。(Vertical stack)

  • HStack:將子視圖按“水平方向”布局途凫。(Horizontal stack)

  • ZStack:將子視圖按“兩軸方向均對齊”布局。

功能組件:

  • NavigationView:負責(zé)App中導(dǎo)航功能的組件溢吻,類似UIKit中的UINavigationView维费。

  • NavigationLink:負責(zé)App頁面跳轉(zhuǎn)的組件,類似于UINavigationView中的pushpop功能促王。

NavigationView {
    List(0..<5){_ in
        NavigationLink.init(destination: VStack(alignment:.center){
            Image.init(systemName: "\(item+1).square.fill").foregroundColor(.green)
            Text("詳情界面\(item + 1)").font(.system(size: 16))
    }) {
          //ListRow
       }
}
.navigationBarTitle("導(dǎo)航\(item)",displayMode: .inline)
  • TabView:負責(zé)App中的標簽頁功能的組件犀盟,類似UIKit中的UITabBarController
TabView {
    Text("The First Tab")
        .tabItem {
            Image(systemName: "1.square.fill")
            Text("First")
        }
    Text("Another Tab")
        .tabItem {
            Image(systemName: "2.square.fill")
            Text("Second")
        }
    Text("The Last Tab")
        .tabItem {
            Image(systemName: "3.square.fill")
            Text("Third")
        }
}
.font(.headline)

三蝇狼、SwiftUI快速上手實踐

下面讓我們快速實現(xiàn)一個有TabView阅畴、NavigationView、List的Demo迅耘。

SF Symbols 是從 iOS 13macOS 10.15 開始內(nèi)置于系統(tǒng)中的字符圖標庫贱枣,它提供了上千種常見的線條圖標监署,而且我們可以任意地為它們設(shè)置尺寸,顏色等屬性纽哥。Apple 甚至準備了專門的app:SF Symbols 來幫助你查看可用的符號:

接下來就讓我們用這些Symbols制作個小Demo钠乏。

  • ContentView:
import SwiftUI

struct ContentView: View {
    
    @State var isLeftNav = false
    @State var isRightNav = false
    
    init() {
        //修改導(dǎo)航欄文字顏色
        UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: UIColor.systemBlue]
        UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: UIColor.systemBlue]
        UINavigationBar.appearance().tintColor = .systemBlue
    }
    
    var body: some View {
        TabView {
            
            // Tab1:
            NavigationView {
                List(Symbols, id:\.self) {
                    ListRow(symbol: $0)
                }
                .navigationBarTitle(Text("SF Symbols"))
                .navigationBarItems(leading: leftNavButton, trailing: rightNavButton)
            }.tabItem {
                Image.init(systemName: "star.fill")
                Text("Tab1").font(.subheadline)
            }
            
            // Tab2:
            NavigationView {
                Text("This is the second tab.")
            }.tabItem {
                Image.init(systemName: "star.fill")
                Text("Tab2").font(.subheadline)
            }
        }
    }
    
    var leftNavButton: some View {
        Button(action: { self.isLeftNav.toggle() }) {
            Image(systemName: "person.crop.circle")
                .imageScale(.large)
                .accessibility(label: Text("Left"))
                .padding()
        }
        .sheet(isPresented: $isLeftNav) {
            VStack {
                Text("Hello, we are QiShare!").foregroundColor(.blue).font(.system(size: 32.0))

                HStack {
                    Spacer()
                    Spacer()
                    Text("an iOS Team. ").fontWeight(.black).foregroundColor(.purple)
                    Spacer()
                    Text("We are learning SwiftUI.").foregroundColor(.blue)
                    Spacer()
                }
            }
        }
    }
    
    var rightNavButton: some View {
        Button(action: { self.isRightNav.toggle() }) {
            Image(systemName: "paperplane.fill")
                .imageScale(.large)
                .accessibility(label: Text("Right"))
                .padding()
        }
        .sheet(isPresented: $isRightNav, onDismiss: {
            print("dissmiss RrightNav")
        }) {
            ZStack {
                Text("This is the Right Navi Button.")
            }
        }
    }
}
  • ListRow:List對應(yīng)的Cell
struct ListRow: View {
    var symbol: String
    var body: some View {
        NavigationLink(destination: ListDetail(symbol: symbol)) {
            
            HStack {
                //圖片
                Image(systemName: symbol)
                    .resizable()
                    .frame(width: 60, height: 60)
                    .foregroundColor(Colors.randomElement())
                //分割
                Divider()
                Spacer()
                //文字
                Text(symbol)
                Spacer()
            }
        }
    }
}
  • ListDetail:
import SwiftUI

struct ListDetail: View {
    
    var symbol: String
    
    var body: some View {
        VStack {
            
            Text("Image:").font(.headline)
            
            Spacer()
            
            Image(systemName: symbol)
                .foregroundColor(Colors.randomElement())
                .imageScale(.large)
                .scaleEffect(3)
                .padding(.bottom, 100)
            
            Divider()
            
            Text("Image Name:").font(.headline)
            Spacer()
            Text(symbol)
                .font(.largeTitle)
            Spacer()
        }
        .navigationBarTitle(symbol)
    }
}

源碼:本文Demo


推薦文章:
iOS 控制日志的開關(guān)
iOS App中可拆卸一個framework的兩種方式
自定義WKWebView顯示內(nèi)容(一)
Swift 5.1 (6) - 函數(shù)
Swift 5.1 (5) - 控制流
Xcode11 新建工程中的SceneDelegate
iOS App啟動優(yōu)化(二)—— 使用“Time Profiler”工具監(jiān)控App的啟動耗時
iOS App啟動優(yōu)化(一)—— 了解App的啟動流程
iOS WKWebView的基本使用
Swift 5.1 (4) - 集合類型

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市春塌,隨后出現(xiàn)的幾起案子晓避,更是在濱河造成了極大的恐慌,老刑警劉巖摔笤,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件够滑,死亡現(xiàn)場離奇詭異垦写,居然都是意外死亡吕世,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門梯投,熙熙樓的掌柜王于貴愁眉苦臉地迎上來命辖,“玉大人,你說我怎么就攤上這事分蓖《В” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵么鹤,是天一觀的道長终娃。 經(jīng)常有香客問我,道長蒸甜,這世上最難降的妖魔是什么棠耕? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮柠新,結(jié)果婚禮上窍荧,老公的妹妹穿的比我還像新娘。我一直安慰自己恨憎,他們只是感情好蕊退,可當(dāng)我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著憔恳,像睡著了一般瓤荔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上钥组,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天输硝,我揣著相機與錄音,去河邊找鬼者铜。 笑死腔丧,一個胖子當(dāng)著我的面吹牛放椰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播愉粤,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼砾医,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了衣厘?” 一聲冷哼從身側(cè)響起如蚜,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎影暴,沒想到半個月后错邦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡型宙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年撬呢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妆兑。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡魂拦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出搁嗓,到底是詐尸還是另有隱情芯勘,我是刑警寧澤,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布腺逛,位于F島的核電站荷愕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏棍矛。R本人自食惡果不足惜安疗,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望茄靠。 院中可真熱鬧茂契,春花似錦、人聲如沸慨绳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脐雪。三九已至厌小,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間战秋,已是汗流浹背璧亚。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留脂信,地道東北人癣蟋。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓透硝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親疯搅。 傳聞我的和親對象是個殘疾皇子濒生,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 前言:之前同事WYongW寫了一篇《用Flutter寫一個簡單頁面》,本篇將和大家一起調(diào)研一下蘋果今年推出的Swi...
    齊舞647閱讀 6,049評論 2 11
  • 夏的腳步愈來愈遠 秋幔欧,靜靜地來臨 我還未從夏的夢中清醒 他已再次縈繞在我的夢中 才發(fā)現(xiàn)我們本是親密無間 驚喜在我心...
    野地百合_35b6閱讀 465評論 9 5
  • 根據(jù)市場調(diào)查的數(shù)據(jù)顯示,北京ui設(shè)計人才需求人數(shù)約為25731人浴井,所占比例為全國之首晒骇,高達29.2%;上海UI設(shè)計...
    早晨午后閱讀 77評論 0 0
  • 技能滋饲。 感覺這篇文會寫的像個人簡歷啊厉碟,不過喊巍,比起明天的寫自己十個優(yōu)點屠缭,這篇稍微能承受一些。 我想崭参,這次寫作是陪伴呵曹,...
    靜候師太閱讀 281評論 0 0
  • 曾有人說 給他一根杠桿 就可以撬動地球 我說 給我一根棍子 就可以打遍天下狗狗 這些都是吹牛逼 很多狗,人面狗身 ...
    開心點金石閱讀 248評論 2 4