SwiftUI學(xué)習(xí)-(第4節(jié))

1.List

下圖所示的List效果办素,在SwiftUI中,實(shí)現(xiàn)列表沒有OC和Swift那樣那么復(fù)雜,幾行代碼就實(shí)現(xiàn)了上述2種語言需要10幾行甚至更多行數(shù)的效果宙彪。

List展示信息

//
//  BoxListView.swift
//  BoxSwiftUI
//
//  Created by BoxJing on 2023/6/13.
//

import SwiftUI

struct BoxListView: View {
    @State private var students = Student.examples
    var body: some View {
        VStack(alignment: .leading) {
            navBarView
            List($students, id: \.name, editActions: .all) { student in
                studentView(student.wrappedValue)
            }
            .listStyle(.plain)
            .padding(.horizontal)
        }
        .safeAreaInset(edge: .bottom,alignment: .trailing, content: {
            Image(systemName: "plus.circle.fill")
                .font(.system(size: 66))
                .padding(.trailing)
                .symbolRenderingMode(.palette)
                .foregroundStyle(.white, Color.accentColor.gradient)
        })
    }
}
extension BoxListView {
    var navBarView: some View {
        HStack {
            Label("學(xué)生列表", systemImage: "person")
                .padding()
                .foregroundColor(.accentColor)
            Spacer()
            EditButton().buttonStyle(.bordered)
                .padding(.trailing)
                .environment(\.locale, .init(identifier: "zh-Hans"))
        }
    }
    func studentView(_ student: Student) -> some View {
        HStack {
            Text(student.name)
            Spacer()
            Text(student.age.formatted())
        }
    }
}
struct BoxListView_Previews: PreviewProvider {
    static var previews: some View {
        BoxListView()
    }
}
2. AnyLayout

有時(shí)候我們會(huì)遇到2種不同的布局情況,這時(shí)候可以用AnyLayout來實(shí)現(xiàn):

struct BoxDifferentLayout: View {
    @State var num:String = ""
    var body: some View {
        TextField("請輸入文字", text: $num)
        Spacer()
        let shouldUseVStack = (num.count % 2 == 0)
        let layout = shouldUseVStack ? AnyLayout(VStackLayout()) : AnyLayout(HStackLayout())
        layout {
            Text("文字1")
            Text("文字2")
        }
    }
}

當(dāng)輸入的文字長度為奇數(shù)時(shí)候2個(gè)文字會(huì)橫向排列瘸爽,當(dāng)文字長度為偶數(shù)時(shí)候2個(gè)文字會(huì)垂直排列您访。

3. GeometryReader

當(dāng)我們需要獲取位置信息時(shí),我們在SwiftUI中可以使用GeometryReader剪决,它包含著一個(gè)視圖View的所有位置信息灵汪,會(huì)返回一個(gè)GeometryProxy實(shí)例,這使我們能夠訪問其容器的大小和坐標(biāo)柑潦。

var body: some View {
  GeometryReader { proxy in
// proxy 里面包含所有的位置信息(x,y,width,height)
  }
}

GeometryReader仍然需要我們在它的主體中聲明一個(gè)視圖享言,我們可以使用Color.clear創(chuàng)建一個(gè)隱形層:

var body: some View {
  customView
    .background(
      GeometryReader { proxy in
        Color.clear
      }
    )
}
4. PreferenceKey

SwiftUI提供了PreferenceKey的功能,這是SwiftUI通過視圖樹傳遞信息的方式渗鬼。
我們開始自定義一個(gè)PreferenceKey,即SizePreferenceKey:

struct SizePreferenceKey: PreferenceKey {
  static var defaultValue: CGSize = .zero
  static func reduce(value: inout CGSize, nextValue: () -> CGSize) {}
}

PreferenceKey是一個(gè)通用協(xié)議览露,需要一個(gè)靜態(tài)函數(shù)和一個(gè)靜態(tài)默認(rèn)值:
defaultValue是被使用,當(dāng)視圖沒有該屬性的顯式值時(shí)
reduce(value:nextValue:)將渲染樹中找到的value值與新的value值組合在一起譬胎。
我們將使用PreferenceKey來存儲(chǔ)我們的子元素的測量大小差牛,回到我們的示例:

var body: some View {
  childView
    .background(
      GeometryReader { geometryProxy in
        Color.clear
          .preference(key: SizePreferenceKey.self, value: geometryProxy.size)
      }
    )
}

現(xiàn)在子視圖的大小就在渲染樹的層次結(jié)構(gòu)中了!我們怎么讀取呢?
SwiftUI提供了一個(gè)View的extension,onPreferenceChange(_:perform:)它讓我們指定一個(gè)PreferenceKey堰乔,當(dāng)該P(yáng)referenceKey發(fā)生變化時(shí)就會(huì)觸發(fā)回調(diào)方法:

var body: some View {
  childView
    .background(
      GeometryReader { geometryProxy in
        Color.clear
          .preference(key: SizePreferenceKey.self, value: geometryProxy.size)
      }
    )
    .onPreferenceChange(SizePreferenceKey.self) { newSize in
      print("The new child size is: \(newSize)")
    }
}

由于onPreferenceChange偏化,任何對此PreferenceKey感興趣的父組件都可以提取值并在值更改時(shí)得到通知。
這種獲取子視圖大小的方法可以直接封裝為View的擴(kuò)展方便使用:

extension View {
  func getViewSize(onChange: @escaping (CGSize) -> Void) -> some View {
    background(
      GeometryReader { proxy in
        Color.clear
          .preference(key: SizePreferenceKey.self, value: proxy.size)
      }
    )
    .onPreferenceChange(SizePreferenceKey.self, perform: onChange)
  }
}

在使用的時(shí)候就方便很多:

var body: some View {
  BoxView
    .getViewSize { size in
      print("Size is: \(size)")
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末镐侯,一起剝皮案震驚了整個(gè)濱河市侦讨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌苟翻,老刑警劉巖韵卤,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異崇猫,居然都是意外死亡沈条,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門诅炉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拍鲤,“玉大人贴谎,你說我怎么就攤上這事〖疚龋” “怎么了擅这?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長景鼠。 經(jīng)常有香客問我仲翎,道長,這世上最難降的妖魔是什么铛漓? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任溯香,我火速辦了婚禮,結(jié)果婚禮上浓恶,老公的妹妹穿的比我還像新娘玫坛。我一直安慰自己,他們只是感情好包晰,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布湿镀。 她就那樣靜靜地躺著,像睡著了一般伐憾。 火紅的嫁衣襯著肌膚如雪勉痴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天树肃,我揣著相機(jī)與錄音蒸矛,去河邊找鬼。 笑死胸嘴,一個(gè)胖子當(dāng)著我的面吹牛雏掠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播劣像,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼磁玉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了驾讲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對情侶失蹤席赂,失蹤者是張志新(化名)和其女友劉穎吮铭,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體颅停,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谓晌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了癞揉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纸肉。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡溺欧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出柏肪,到底是詐尸還是另有隱情姐刁,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布烦味,位于F島的核電站聂使,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏谬俄。R本人自食惡果不足惜柏靶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望溃论。 院中可真熱鬧屎蜓,春花似錦、人聲如沸钥勋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽笔诵。三九已至返吻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間乎婿,已是汗流浹背测僵。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谢翎,地道東北人捍靠。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像森逮,于是被迫代替她去往敵國和親榨婆。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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