主頁 > 移動端開發 > SwiftUI - 一起來仿寫微信APP之一首頁串列視圖

SwiftUI - 一起來仿寫微信APP之一首頁串列視圖

2020-09-10 15:28:27 移動端開發

簡介

最近在學習 SwiftUI ,我一般都是先去學習界面布局,所以就想著仿寫一下經常使用的軟體的界面,所以先拿微信開刀,因為不想一次性發太多的內容,所以只好將主題分解,一部分一部分地去講,接下來我們一起來學習吧,

如果你嘗試過使用 SwiftUI 撰寫界面,你會發現是如此地舒心,我已深深地愛上了它,當然它的坑并不少,畢竟才剛出來,最低支持系統是 iOS13,估計還得等個幾年才會慢慢在公司里使用上吧,但是這并不妨礙我們的學習,

在這篇文章里,我會一步一步撰寫微信的首頁串列視圖,一步一步將代碼呈現上來,并仔細地講解,我相信你們都可以看懂的,先來看看效果圖,

很簡單吧?是很簡單,但是在撰寫的時候還是有些技巧在里面,畢竟,簡單才不容易勸退嘛,在開始前先講一下這篇文章將會用到的一些布局與組件,先給大家一個印象,方便后面的閱讀理解,

HStack - 水平布局

VStack - 垂直布局

Text - 文本控制元件

Spacer - 擴展空間,使容器填滿布局空間

Image - 影像控制元件

List - 串列控制元件

Divider - 分隔線控制元件

作業環境

Xcode - Version 11.3.1 (11C504)

Swift - version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15)

開始撰寫代碼

撰寫串列行

我們來先把頭像添加進來,

Image("1")
    .resizable() // 1
    .frame(width: 46, height: 46) // 2
    .cornerRadius(6)// 3

1 - 在 SwiftUI 中,如果需要控制影像的大小,則必須先呼叫resizable修飾

2- 設定影像大小

3 - 設定圓角大小,四個角的大小都相同

因為布局是橫向的,所以我們在外層使用HStack包裹起來,然后添加聯系人名字和最后發訊息時間,

HStack {
    // 頭像

    HStack {
        Text("女神")
            .font(.body) // 1

        Spacer()

        Text("下午 2:55")
            .font(.caption)
            .foregroundColor(Color.gray.opacity(0.5)) // 2
    }
}

1 - 使用 font 修飾字體,這里使用了蘋果提供的標準字體,蘋果還提供了 largeTitle, title, headline, subheadline, body, callout, footnote, caption,

2 - 使用 foregroundColor 修飾字體顏色,因為 gray 的灰色還是太黑了,所以這里又使用了 opacity 去修飾透明度為50%,使它顯得更淡一點,

名字下方顯示的是是最后發送或接收的訊息內容,因此我們在外層使用 VStack 包裹起來,

VStack(alignment: .leading, spacing: 6) { // 1
    // 名稱和時間

    Text("對不起,你是個好人")
        .font(.callout)
        .foregroundColor(Color.gray)
}

// 1 - 設定VStack里子控制元件居左對齊,默認是居中對齊,再設定子控制元件的間隙為 6 個像素,這樣比較符合微信上面的設計,

現在樣子已經出來了,我們先預覽下效果,

我們給最外層的HStack增加padding,使它更美觀一些,引數填寫.all代表四周都需要邊框,經過我的眼力觀察,它的默認是 16px 的樣子,

HStack {
    // 頭像、名稱、時間、訊息內容
}
.padding(.all)

有了間距,好看多了,

接下來創建一個視圖,它負責裝載行視圖,起名為GCMainRow

struct GCMainRow: View {
    var body: some View {
        HStack {
            Image("1")
                .resizable()
                .frame(width: 46, height: 46)
                .cornerRadius(6)
            
            VStack(alignment: .leading, spacing: 6) {
                HStack {
                    Text("女神")
                        .font(.body)

                    Spacer()

                    Text("下午 2:55")
                        .font(.caption)
                        .foregroundColor(Color.gray.opacity(0.5))
                }
                Text("對不起,你是個好人")
                    .font(.callout)
                    .foregroundColor(Color.gray)
            }
        }
        .padding(.all)
    }
}

然后在ContentView改為呼叫GCMainRow(),這樣代碼就好看很多了,

struct ContentView: View {
    var body: some View {
        GCMainRow()
    }
}

撰寫串列 List

好了,現在讓我們來撰寫串列視圖吧,我們在最外層使用List包裹GCMainRow,回圈 20 個視圖,資料多點才可以讓我們滾動,

List(0 ..< 20) { _ in // 1
    GCMainRow()
}

1 - 因為我們不需要用到回圈的一些資料,所以我們使用 _ 去忽略它,

List控制元件默認的都會有邊距,下圖黃色是GCMainRow的大小,可以看得出來旁邊有空白的填充,這對我們當前的設計來說不太友好,因此我們需要想辦法去掉這些邊距填充,

List提供了listRowInsets來控制行的邊距(上下左右),我們來試著使用一下,

List(0 ..< 20) { item in
    GCMainRow()
        .listRowInsets(EdgeInsets())
}

我們發現,這樣寫是沒有作用的,listRowInsets的生效條件是“不能直接在List中使用,需要配合For Each陳述句才能生效”,我們再修改一下代碼,

List {
    ForEach(0 ..< 20) { item in
        GCMainRow()
            .listRowInsets(EdgeInsets())
    }
}

好了,這次生效了,這就是我們要的結果,

自定義分隔線

我們仔細觀察一下分隔線,在微信里分隔線是左對齊在名稱和訊息內容的,所以我們需要把現有的分隔線隱藏掉,然后再實作它,

在這里講解一下,List是基于UITableView去實作的,這意味著我們可以通過appearance全域修改它的所有屬性,正如我們現在需要取消它默認的分隔線,將separatorStyle設定為.none即可,

init() {
    UITableView.appearance().separatorStyle = .none
}

因為分隔線是貼著右邊緣的,所以我們需要在包裹著名稱、時間、訊息內容的VStack外層再包裹一層VStack,在其中再添加分隔線Divider,并將里層的VStack設定右邊距,最后將最外層的HStackpadding改為上和左邊距,是不是聽得有點懵?沒關系,看看代碼就很容易理解了,

HStack(alignment: .top) { // edit
    // 頭像
    VStack { // new
        VStack(alignment: .leading, spacing: 6) {
            // 名稱、時間、訊息內容
        }
        .padding(.trailing) // new
        Divider() // new
    }
}
.padding(.top) // edit
.padding(.leading) // edit

我們現在來看一下效果,

未讀訊息小紅點

未讀訊息在頭像的右上方,小紅點的中心點是位于頭像的右上頂端,我們可以使用overlay疊加一個視圖,來制作小紅點吧,

Image("1")
		// ...
    .overlay(
        Color.red // 1
            .frame(width: 16, height: 16)
            .cornerRadius(8)
            .offset(x: 23, y: -23) // 2
)

// 1 - Color 本身也是一個視圖組件,這是官方的定義 @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) extension Color : View { }

// 2 - 設定視圖的偏移量,那么23是怎樣得出來的呢?很簡單,因為默認的overlay視圖是位于父視圖的中心,那么我們要將它放置在右上角,那么只需要寬高都除以2就可以了,那么這里的結果就是,x軸增加23px,y軸減少23px

接下來是未讀數量,和上面的相似,在Color視圖上利用overlay疊加Text視圖就可以了,

Color.red
    .overlay( // 1
        Text("1")
            .font(.caption)
            .foregroundColor(.white)
)
    .frame(width: 16, height: 16)
    .cornerRadius(8)
    .offset(x: 23, y: -23)

// 1- 值得注意的是,因為文本也是需要偏移到右上角的,所以必須放在前面,不然它默認就是居中的

至此,代碼演示結束,預覽一下靜態圖,文章開頭有 gif 動態圖效果,

總結

好了,這篇文章就到這里,篇幅有點長了,不過沒關系,我們來總結一下關鍵點:

  1. List默認是有行邊距的,要取消或修改它的行邊距,我們必須通過For Each再配合上listRowInsets才能實作,
  2. List是基于UITableView去實作的,這意味著我們可以通過appearance全域修改它的所有屬性,
  3. 使用overlay可以給視圖疊加一個視圖,

Demo 原始碼下載

我已經把 Demo 上傳至 GitHub 上面,專案名字是 SwiftUI-Tutorials,目錄名為GCWechatList,有需要的朋友可以去下載運行一下,當然你也可以跟著文章去做一遍,這樣更有利于你掌握此方面的知識,

文章篇幅有點長,雖然教的東西也挺簡單,但概述得比較詳細,任何東西都是先從簡單入手的,才不會造成勸退不是嗎?哈哈,此文章針對于新手而言還是很友好的,對于已經會的人來講就可能廢話有點多了,如果必須要噴,請輕噴,我比較玻璃心,

如果本文章對你有幫助,請關注我,你的關注就是我后續寫文章的動力,下期會更精彩噢!

關于作者

博文作者:GarveyCalvin

微博:https://weibo.com/feiyueharia

博客園:https://www.cnblogs.com/GarveyCalvin

本文著作權歸作者,歡迎轉載,但必須保留此段宣告,并給出原文鏈接,謝謝合作!

公眾號

作者第一次運營公眾號,請你們一定要關注我的公眾號,給我點動力,后期主要運營公眾號為主,這是第二篇發布的文章,需要你們的支持,謝謝你們!

QQ群

一起討論 SwiftUI,群主喜歡看熱鬧,當吃瓜人員,進來時填寫你在哪里看到此文章的,并介紹下自己,一句話就行,

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/2557.html

標籤:iOS

上一篇:iOS面試題---Objective_C語言特性:分類、擴展、代理、通知、KVO、KVC、屬性

下一篇:IOS App打包發布完整流程

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more