目前swiftUI最低支持iOS13崭篡,蘋果還在不斷升級完善,目前還不成熟,因為現在widget必須用swiftUI布局响蓉,所以有幸把swiftUI應用到項目。當我寫swiftUI的demo時感覺這東西好簡單EZ哨毁,但是真到了項目中是各種坑
編輯代碼的兩種方式
1.代碼
2.preview畫布枫甲,拖拽控件,檢查器,inspector
因為preview有時有問題想幻,也不方便調試粱栖,需要維護一套假數據,所以一般用代碼脏毯。
布局
swiftUI控件大多為結構體
基本布局需要三個Stack:
HStack
:水平布局闹究,X軸
VStack
:垂直布局,Y軸
ZStack
:層疊布局抄沮,Z軸
可以看做是一個三維坐標系
如果原來寫過flutter會對這個布局很熟悉跋核,HStack相當于Row,VStack相當于Colum,但是swiftUI叛买,HStack的alignment只有垂直對齊方式砂代,VStack的alignment只有水平對齊方式,對齊方式是指Stack內部元素的對齊方式率挣,而不是Stack本身刻伊,Stack的實際大小是根據里面子視圖的大小來撐開的,如果Stack內部只有一個元素椒功,不管你設置任何對齊方式都是不起作用的
比如有一個需求捶箱,設置一個圖片緊貼左上角
EZ啊
VStack(alignment: .leading){
Image("cloudy")
}
發(fā)現是居中,然后修改
ZStack(alignment:.topLeading){
Image("cloudy")
}
還是居中沒變动漾,是因為Stack內部就一張圖片丁屎,所以Stack就是圖片大小,需要撐開Stack才能設置內部坐上對齊旱眯,修改如下
ZStack(alignment:.topLeading){
Color(.clear)
Image("cloudy")
}
用Color來撐開Stack晨川,當然也可以用別的方式,比如
VStack(alignment: .leading){
HStack(alignment: .top){
Image("cloudy")
Spacer()
}
Spacer()
}
用Spacer()
撐開Stack
通過這三種Stack互相嵌套可以實現各種復雜的布局
需要注意的是删豺;這三種Stack中的控件之間默認是有間距的共虑,所以需要指定間距,比如VStack(spacing:0)
布局通用屬性
細節(jié)的位置變化需要用到frame
呀页,offSet
妈拌,position
,padding
蓬蝶,layoutPriority
frame
只能指定寬高
.frame(minWidth: ,maxWidth: , minHeight: ,maxHeight:)用來給調用者一個大小限制尘分,不能超出這個限制
idealWidth: ,idealHeight: 理想大小。必須配合.fixedSize(horizontal: true, vertical: false)才能生效丸氛,例如:
.frame(idealWidth: 300)
.fixedSize(horizontal: true, vertical: false)//設置在哪個方向強制生效音诫,水平方向還是垂直方向
min寬高,類似于UIKit自動布局的>=
max寬高雪位,類似于UIKit自動布局的<=
offSet
:在視圖應有的位置加上偏移量
position
:在上層容器強制定位,相當于UIKit里的frame(x,y),但是這里的x雹洗,y指的是視圖中心點的位置
padding
:內邊距
.padding(20)內邊距都為20
.padding(.leading,20)左側內邊距為20
.padding([.top, .leading],20)左側上側內邊距為20
layoutPriority(0)
:視圖優(yōu)先級香罐,默認為0
Space()
撐開子控件到父控件的最大長度,經常用时肿,比如在屏幕最左邊和最右側顯示兩個文字對齊
HStack{
Text("n")
Spacer()
Text("w")
}
獲取上層視圖空間大小庇茫,這個很常用
GeometryReader{proxy in
Text(String(describing: proxy.size))
}
常用控件
視圖分為:
緊湊視圖:大多數控件屬于這一類型,控件中的內容決定控件的實際大小
貪婪視圖:Circel,Spacer,Color等螃成,控件在父視圖范圍內會盡可能多的去鋪滿剩余空間
一般有內容的視圖是緊湊類型旦签,容器類視圖為貪婪類視圖
Text
.truncationMode(.middle)//設置超出文本的省略方式
.lineLimit(1)//默認不限制行數
.font(.system(size: 85))//字體過大,超過顯示區(qū)域會整體消失寸宏,不顯示
Image:
如果圖片大小和顯示大小不一樣宁炫,需要手動設置圖片的大小,需要先設置.resizable()氮凝,否則frame寬高不生效
Image("forecast_icon_clound")
.resizable()
.frame(width: 22, height: 22)
.fixedSize(horizontal: true, vertical: true)//這句可以不加
.aspectRatio(contentMode: .fill)
Button羔巢,Picker,Slider罩阵,WebView竿秆,TextField,ScrollView這些用法和UIKit相似稿壁,只是把UI前綴去了
List類似于TableView
GridView:有LazyHGrid幽钢,LazyVGrid,相當于collectionView
let gridItem = [GridItem(.flexible(),spacing: 0)]
LazyHGrid(rows: gridItem, spacing:0) {
ForEach(0...10,id:\.self) { index in
setUpCell()
}
}
Group把控件裝到這個組里面傅是,可以進行一些統(tǒng)一配置
Path劃線咐吼,折線虛線都可以,舉一個虛線的例子:
Path{ path in
path.move(to: CGPoint(x: 0, y: 100))
path.addLine(to: CGPoint(x: 200, y: 100))
}
.stroke(Color(white: 1, opacity: 0.2),style: StrokeStyle(lineWidth: 1, lineCap: .round, lineJoin:.round, dash: [1,2], dashPhase: 0))
屬性裝飾器
理解 SwiftUI 里的屬性裝飾器
@State 屬性變化伤极,刷新UI鲫咽。用于一個對象內屬性修飾
@StateObject 用于生成和管理狀態(tài)屬性的生命周期
@ObservedObject 修飾共享狀態(tài)從外部傳遞進來的屬性,修飾的屬性要實現ObservableObject協(xié)議
ObservableObject協(xié)議溃斋,對應屬性內要實現
var age = 100 {
willSet {
objectWillChange.send()
}
}
簡寫是用@Published修飾@Published var age = 100
需要注意的是多層監(jiān)聽屬性傳遞都要用@ObservedObject修飾界拦,所以有了@EnvironmentObject
@EnvironmentObject 修飾全局,避免多個對象傳遞用@ObservedObject修飾
ParentView()
.environmentObject(user)
struct ParentView : View{
var body: some View {
ChindView()
}
}
struct ChindView : View {
@EnvironmentObject var user : UserModel
}
@Binding 修飾的屬性變?yōu)橐脗鬟f