SwiftUI - 常用Views / Modifies(一)

前言

從本篇文章開始,我們來學習SwiftUI中常用的ViewsModifies。首先我們需要使用起來,以后有機會再看看比較深層次的知識點。

一、與OC文件的比較

在學習之前,我們來比較一下SwiftUI文件和OC文件所對應的控件添加區(qū)塊的不同,新建項目,默認Interface選擇SwiftUI,Language選擇Swift,并且新增一個OC文件,查看之間不一樣的地方:

SwiftUI視圖添加

OC視圖添加

可見,在SwiftUI里面,多了Views(普通視圖)和Modifies(修飾視圖),左側列表中包括我們常用的所有視圖及容器控件,單擊左邊列表,右邊展示的是介紹及用法,所以一開始不知道怎么使用的話,可以參照右邊官方示例學習,或者更簡便的是可以直接拖拽進代碼里面,會自動生成代碼,不妨動手試下吧。

二、啟動圖設置

SwiftUI里面我們可以直接在TARGETS -- {主項目} -- info文件中直接設置啟動圖的一些屬性樣式,其中包括圖片,背景顏色等等,我們可以試著設置下啟動圖片

啟動圖設置

或者可以設置一個顏色值,就可以設置啟動時候的背景顏色,刪除上面添加的啟動圖,設置Background color
啟動背景顏色1

啟動背景顏色2

重啟工程,發(fā)現(xiàn)啟動背景顏色就改成了當前的AccentColor。(拓展:在Assets里面也可以自定義顏色值,當前的AccentColor也可用于項目代碼中,類似AccentColor一樣自定義一個顏色值,也可用于項目中)

三、常用Views / Modifies

1、Text & Label

Text 更像是OC中的UILabel,而Label更傾向于一個<標簽>:

VStack{
       Text("Hello, world!").padding().foregroundColor(Color("nowColor"))
       Label("Label1111", systemImage: "42.circle")
 }

其中nowColor為上方在Assets中自定義的顏色值,顯示效果如下:

Text & Label

Text里的字符串可以使用markdown語法,你也可以試試,更多使用:

//Text
Text("ContentView_Previews").italic()
.frame(width: 180,height: 100,alignment: .center)
.background(Color.red)
//Label
Label {
               //此處可以添加按鈕等視圖一樣可以實現(xiàn)
                Text("我是Label")
            } icon: {
                Circle().stroke(lineWidth: 5).foregroundColor(.red).frame(width: 34,height: 34,alignment: .center).overlay(Text("5"))
            }
2、Button / Link

按鈕及按鈕點擊事件,用法如下:

Button {
                print("tapbTN1")
            } label: {
                Text("button1").foregroundColor(.blue)
            }
            Button(action: {
                print("tapBtn2")
            }) {
                Text("Button2")
            }
            //簡單實用
            Button("button3") {
                print("buton3")
            }.foregroundColor(.green).font(.largeTitle) 

Link是鏈接外鏈的視圖:

 Link(destination: URL(string: "https://www.baidu.com")!) {
                Text("Link1")
            }
 Link("Link2", destination: URL(string: "https://www.baidu.com")!)
3、Image / AsyncImage

將Image視圖拖進代碼,如下:

Image("Image Name") 
//Image("33")

當我們將上文中33寫入時,發(fā)現(xiàn)圖片并不展示,此處有個坑,即此種寫法它會去找Assets里面有沒有33,上文中圖片33是直接拉進來的,所以不展示,那么我們可以用下面方式顯示33:

Image(uiImage: .init(named: "33")!)

但官方推薦使用在Assets里面添加圖片的方式,寫法簡單點。
另外注意圖片的填充方式:

//撐開屏幕,占滿父視圖(Vstack)剩余位置,不遵循寬高比(會壓縮)
Image(uiImage: .init(named: "33")!).resizable()
//會根據(jù)寬高比展示,寬 > 高 以屏幕寬為最大,高 > 寬 以父視圖剩余空間撐開,VStack上下?lián)伍_
Image(uiImage: .init(named: "66")!).resizable().scaledToFit()
//會根據(jù)寬高比展示,寬 > 高 以父視圖剩余空間撐開,VStack上下?lián)伍_,只展示圖片部分內容(會裁剪), 高 > 寬 以屏幕最大寬度,按寬高比展示圖片部分內容(會裁剪)
Image(uiImage: .init(named: "88")!).resizable().scaledToFill()

WWDC21 新出的AsyncImage類似我們OC中的三方庫SD_WebImage,

AsyncImage(url: URL.init(string: "https://img1.baidu.com/it/u=333716107,1538170532&fm=253&fmt=auto&app=138&f=JPEG?w=600&h=488")) { img in
                img.resizable()
            } placeholder: {
                ProgressView()
            }.frame(width: 120,height: 200)

其中img.resizable()不可省略,不寫的話,不能展示,即不寫的話就是沒有對加載結果圖片做顯示操作。

4、TimelineView / Canvas

TimelineView:按計劃地去更新View。比如多久刷新一次View,也可以設定開始日期然后以怎樣的時間間隔去刷新等。

  • 每隔一分鐘去更新
TimelineView(.everyMinute) { context in
                
 }
  • 從某個時間點開始,隔多久更新
TimelineView(.periodic(from: Date.now, by: 1.0)) { context in
       Text(context.date.description).font(.largeTitle)
 }

類似我們經常使用的NSTimer定時器,這種用法使用的比較多。

  • 以不規(guī)則的一組時間節(jié)點去刷新
TimelineView(.explicit(...

Canvas:繪制畫布,提供一塊區(qū)域供我們畫想畫的東西。

Canvas { context, size in
                context.stroke(Path(ellipseIn: CGRect(origin: .zero, size: size)), with: .color(.orange),lineWidth: 5)
            }.frame(width: 100,height: 50).border(.blue,width: 3)
Canvas畫布
5、TextEditor / TextField

使用TextEditor時需要指定frame,因為它的布局默認是填充滿父視圖剩余空間,功能上類似于TextView

TextEditor(text: .constant("hsjshjhajhjsh")).frame(width: 200,height: 200)

運行在模擬器上,發(fā)現(xiàn)鍵盤輸入后,TextEditor上的文字不變,這里需要定義數(shù)據(jù)@State var string = "okokokok",用string來裝載輸入的東西,@State我們此處不去做解釋。

TextEditor(text: $string).frame(width: 200,height: 200)

這樣才能達到實時顯示輸入內容。
TextField就是之前一樣的輸入框,使用如下:

TextField("PlaceHolder", text: $string).textFieldStyle(.roundedBorder).font(.largeTitle).frame(width: 200, height: 50)
                //.focused()光標是否在上面
                //捕捉點擊Return 按鈕事件
                .onSubmit {
                    print("點擊了Return")
                }

.textInputAutocapitalization()設置輸入框的英文文字是否大小寫:

  • .characters 輸入的字母全轉大寫
  • .words 輸入的字母以空格為分界,自動轉換為一個個單詞
  • .never 輸入內容全為小寫
    .disableAutocorrection() 設置鍵盤輸入時的矯正,但平時我們不怎么希望用到此功能,可置為truefalse。
    注意:當我們給輸入框添加圓角邊框時候,如果使用下面方式效果不是很好,顯示不全:
.border(.red,width: 1)
.cornerRadius(20)
正常思維

此時我們可以使用下面這種方式來給TextField添加邊框:

.overlay {
                    RoundedRectangle(cornerRadius: 20).stroke(.red,lineWidth: 10)
                }
添加邊框

輸入框使用中,我們需要關注鍵盤的隱藏,需要給界面一個點擊事件,例如輸入框在一個Vstack中,那需要給這個Vstack 添加點擊事件

.onTapGesture {
            print("tap")
            //熱區(qū)
            UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
        }

點擊Return能隱藏鍵盤,點擊上方區(qū)域時,發(fā)現(xiàn)點擊文字或別的視圖顯示區(qū)域可以隱藏鍵盤,但是Vstack區(qū)域內視圖顯示區(qū)域之外的空白區(qū)域不能將鍵盤隱藏,所以我們還需要給Vstack添加一個熱區(qū)

.contentShape(Rectangle())

熱區(qū)意思就是在這個Vstack區(qū)域內的點擊都能響應.onTapGesture事件。

6、Picker

一個彈窗選擇器(Selecter)控件,代碼如下:

enum Person: String{
        case Tom
        case Jim
        case Lily
        case Lucy
    }
    @State var selectedPerson = Person.Lily
    var body: some View {
        VStack {
            Picker(selection: $selectedPerson, label: Text("Picker")) {
                Text("Tom").tag(Person.Tom)
                Text("Jim").tag(Person.Jim)
                Text("Lily").tag(Person.Lily)
                Text("Lucy").tag(Person.Lucy)
            }
            Text("slected Person: \(selectedPerson.rawValue)")
        }
        .padding()
    }

Picker示例

.pickerStyle(.inline)當給Picker改變樣式時候,展示的樣式截然不同,此處使用.inline就類似.wheel的樣式,也可切換著看看.segmented,此種樣式就是UIKit里的UISegmentedControll。默認是.menu樣式。
(可以試著將Picker單獨放在NavigationView中查看.pickerStyle不一樣的地方)

拓展 1:SwiftUI中的文本長按選擇會出現(xiàn)Copy/Share...彈框,默認是關閉的:

//disabled 關閉 enabled 開啟
Text("slected Person").textSelection(.enabled)
Text長按功能
7、ProgressView

進度條ProgressView,

ProgressView(value: 0.5,total: 10,label: {
                //上面文字
                Text("Lcr")
            },currentValueLabel: {
                //下面文字
                Text("Lcr111")
            }).background(.green)

當加上背景顏色之后,感覺視覺效果不是很好(背景色會覆蓋進度條上下文字背景),所以個人覺得還是去掉上下文字,保留一條進度條就好,然后另外寫上下Text去展示需要展示的數(shù)據(jù)。
.tint(.red) 設置前面進度條的顏色。
ProgressView(),這種寫法默認(.circular)就是小菊花樣式,.linear 進度條樣式。
上面的進度條改變樣式后也可以變成小菊花樣式。

ProgressView().progressViewStyle(.circular)
ProgressView().progressViewStyle(.linear)
8、Slider

滑塊控件Slider

@State var speed = 0 //當前值
//value當前值,in值的范圍0-100,step每次滑動變化值,onEditingChanged監(jiān)聽滑動事件 
//.tint 滑塊左側進度條顏色
Slider(value:$speed,in: 0...100,step: 25,onEditingChanged: { editing in
                print(editing)
            }).tint(.red)

如果需要展示前后的數(shù)值文字:

Slider(value: $speed, in: 0...100,step: 25) {
                
            } minimumValueLabel: {
                Text("0")
            } maximumValueLabel: {
                //Text("100")
                Text("\(speed)")
            }

拓展:一個容器(如VStack)里面的字視圖最多不能超過10個View

9、Toggle / Stepper

類似OC中的UISwitch,開關控件

@State var toggleStatus = false

Toggle(isOn: $toggleStatus) {
                Text("Toggle")
            }.tint(.clear).colorMultiply(.orange)

Stepper類似購物車加減按鈕:

@State var value = 0

Stepper(value: $value, in: 0...9, step: 3) {
                Text("\(value)").font(.largeTitle)
            }

每次增加減少都是以3來計算。

@State var value = 0
    
    let colors:[Color] = [.orange, .red, .gray, .blue, .green, .purple, .pink]
    
    func stepperAction(isIncrement: Bool) {
        value = value + (isIncrement ? 1 : -1)
        if value >= colors.count {value = 0}
        if value < 0 {value = colors.count - 1}
    }

Stepper {
                Text("Value: \(value) Color: \(colors[value].description)").foregroundColor(colors[value]).font(Font.system(.title2).bold())
            } onIncrement: {
                stepperAction(isIncrement: true)
            } onDecrement: {
                stepperAction(isIncrement: false)
            }
Stepper示例

本文學習了一些基本的視圖控件的使用,有時間拿起鍵盤敲起來,動動手加深印象,gogogo!!!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容