Swift Practice # 153 SwiftUI GeometryReader 與Safe Area初探
上一篇理解了CLLocation的使用方式去取得指定的兩個經緯度直線距離,大概知道如何實作在side project上。
大致的前置作業都完成,準備開始寫side project,但是腦海思索著一個問題,當初在UIKit能透過Storyboard來處理元件跟Safe Area的問題,畢竟在瀏海機與舊指紋機兩者個Safe Area有著大大的不同,為了避開元件顯示的問題,我自己會盡量把元件放在Safe Area,避免遭遇到瀏海與其他的狀況。
UIKit的Safe Area 位置與尺寸
上面三張圖片讓元件透過去equal Safe Area去綁定元件的大小,大致透過這樣的方式使元件不會超過Safe Area。從上圖iPhone 12 Pro得知我們需要的一些尺寸數值
Screen Size:390 × 844
Safe Area:390 × 763
上方狀態欄height:47
下方Home Indicator height:Screen Size 減 Safe Area 減狀態欄 等於 34。
不過可以注意到右上方的圖height都是766為什麼會是763?這產生了我的好奇,所以我重新做了一個跟Safe area比例1:1的Button來查看尺寸。
從上圖得知Safa Area的高是763沒錯,另外得知上方的狀態欄的高是47,從這邊確認好UIKit看到的iPhone 12 Pro的Safe Area的定位與寬高。至於UIkit的height766就讓我們後續再理解了。
SwiftUI GeometryReader 初探
先嘗試透過官方說明來理解GeometryReader的說明:
A container view that defines its content as a function of its own size and coordinate space.This view returns a flexible preferred size to its parent layout.
可以理解的是可以協調View的空間,更加靈活的處理與父層的layout。可以從官方得知,這不是完全拿來處理Safe Area的問題。就我目前的一部分理解,SwiftUI在預設空間時,會將View放在Safe Area內,除非我們使用了.ignoresSafeArea()。下方的程式碼讓我自己確認View的處理會在Safe Area內執行。
從上圖加總可已得到762.9視為763,也就是跟Safe Area的height一樣。
SwiftUI GeometryReader 與 Safe Area
從網路上的資源得知,GeometryReader可以取得Safe Area的尺寸,嘗試列印確認尺寸大小。
在SwiftUI中 iPhone 12 Pro 的 GeometryReader的Size是390與763,跟UIKit的Safe Area的尺寸一樣。
GeometryReader 近似視圖深度
從上面的程式碼與圖片可以看到在沒有設定Vstack或是Zstack的狀態,在GeometryReader內是類似像是ZStack一樣,不是像some view內會依序排列。這是在練習當中的一個發現。
GeometryReader 與 Spacing
上圖的程式碼中可以發現到我們透過Geometry的寬度/3設置Text與Button,但是系統自動幫我們做出了白色間距,截圖看了一下這白色間距的距離為8,從這點可以看到SwiftUI會自動產生height8的spacing,再注意上方GIF內下方可以看到三個元件的高是254.3。
下面我嘗試設定spacing為0並再確認結果。
從上面的GIF內可以看到白色間距已經不見了,但觀察到了一件事,不管有沒有設定spacing,三個元件的height都是254.3,但又讓我產生疑問,那到底spacing的距離會不會影響佈局?這個時候我回去查看沒有預設spacing的程式碼確認GeometryReader內VStack的尺寸。
上圖內發現到整個VStack已經變成779,超越了Safe Area的763,而差距也可以得知是16兩個spacing各自為8的height。從這點可以看到若是我們沒有特別設定spacing,整個GeometryReader的尺寸將會超過Safe Area,在使用上可能會造成Home indicator遮擋,因為整個高是從上方的狀態欄47的height去開始往下調整,所以會影響到的就是下方的Home indicator。
GeometryReader上下方的SafeArea顏色
從上方的程式碼與Preview可以看到spacing為0 GeometryReader的VStack的height為763,但Preview的圖可以看到上方的SafeArea被渲染成紅色,下方則為綠色,這又帶來了下一個問題,如果想要讓Safe Area不要被自動渲染,該怎麼處理?
方法一:
第一個方法我透過包覆一層ZStack放入顏色當作背景色,再放入一個Text,透過這個方法上下方的Safe就沒有被渲染成紅色與綠色。
方法二:
方法二則透過在.background來處理,塞入指定的形狀的顏色背景
透過上面兩個方法,可以讓Safe Area不會自動地去渲染靠近他的顏色,目前還不確定是什麼原因造成的,但至少先透過解法來解決問題,而造成問題的原因也是未來要慢慢去理解的事,搞懂怎麼用跟成因還是相對重要的。
GeometryReader 與 Safe Area 可以不一樣大小
上圖的Gif可以看到GeometryReader的大小變成655,原因在於同一個VStack內我們還存在著一個height100的Text,加上自動spacing的height8組成了整個763的Safe Area的大小。從這點來看可以得知GeometryReader不一定是完全跟Safe Area一樣大。
上述就是自己關於GeometryReader的認識,本質上來說Safe Area的空間算是GeometryReader的一個延伸,並不只是完全可拿來聚焦在Safe Area,只是剛好你使用在最外層,那GeometryReader就可以跟Safe Area達到一致在透過size的比例去指定元件跟SafeArea大小的相對關係,但這也要注意到spacing產生的空間問題,認真思考SwiftUI帶來了便利性,但深度鑽研還是可以發現很多系統幫你處理好,但你想自己設定的一些狀況與可能性。持續加油!!
參考資料:
螢幕尺寸
iPhone Safe Area