純代碼佈局,也可以一樣的簡潔

語言: CN / TW / HK

theme: juejin highlight: xcode


“我報名參加金石計劃1期挑戰——瓜分10萬獎池,這是我的第3篇文章,點擊查看活動詳情

前言

在前兩篇文章講述了UIStackView佈局思想,使用方法以及一些實用的案例,在案例中使用xib結合UIStackView,缺少一些對純代碼的補充,這篇文章,我們主要聊聊如何使用StackView來寫純代碼佈局。

即便説過很多StackView的好,但是還是很多人認為複雜的頁面用不上,其實真正理解了StackView的佈局思想,不管是結構層級簡單的佈局亦或者複雜的佈局,也不管是使用Inferface Builder來構建UI,還是使用純代碼,都能夠遊刃有餘。

下面,我會使用swift演示使用純代碼是怎樣佈局的。如果有興趣,點擊下載Demo查看效果。下面所展示的代碼只是截取的佈局部分。

簡單佈局

簡單佈局,我歸納為,一行或者一列的元素組成的。通常有類頁面如設置頁、通訊錄。如下佈局中,一個hStack包含了image、label、button,組成了一個簡單的佈局。

結構如下:\ HStack: image + label + Button

swift /// 懶加載 private lazy var vStack = VStack(spacing: 16)

Note: 這裏的VStack實際上是對UIStackView的封裝以及添加了便攜式的初始化,並不是SwiftUIVStack

```swift /// 佈局代碼 addSubview(hStack) hStack.snp.makeConstraints { make in make.edges.equalToSuperview().inset(UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)) }

/// 這裏是使用的擴展方法 iconView.sizeConstraint = CGSize(width: 40, height: 40) title.heightConstraint = 30 follow.sizeConstraint = CGSize(width: 60, height: 30) hStack.addArrangedSubviewsMakeConstraint([iconView, title, hStack.spacer(), follow]) ```

NotesizeConstraint、heightConstraint、widthConstraint、addArrangedSubviewsMakeConstraint、spacer()這些都是自己添加分類方法。

嵌套佈局

嵌套佈局,我歸納為,界面的元素多樣化,需要使用兩個以上StackView的佈局(不同排列方向)。

結構如下:\ HStack:image + VStack + Button\ VStack:label + label

swift /// 懶加載 private lazy var hStack = HStack(spacing: 8, alignment: .center, distribution: .fill) private lazy var vStack = VStack(spacing: 4, alignment: .fill, distribution: .fill)

Noteswift可以寫出比OC更多的語法糖,這是語法的特性所在。從初始化方法上就可以看出。

```swift addSubview(hStack) hStack.snp.makeConstraints { make in make.edges.equalToSuperview().inset(UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)) }

iconView.sizeConstraint = CGSize(width: 50, height: 50) helpView.sizeConstraint = CGSize(width: 30, height: 30) hStack.addArrangedSubviewsMakeConstraint([iconView, vStack, hStack.spacer(), helpView]) vStack.addArrangedSubviews([title, detail]) ```

動態更新佈局

動態更新佈局,我歸納為,界面的元素多樣化,一些界面上的元素會有種狀態,繼而影響到其他的元素,最終會影響到整體的佈局。

結構如下:\ HStack:image + VStack + Button\ VStack:HStack + label\ HStack:label + label

其實整體的佈局,與上面的例子中僅僅只有細微的差別,這裏想要體現的是,修改stackView的屬性以及修改stackView中的排列視圖的width、height或者hidden相關的屬性,都會使stackView重新佈局。

```swift private lazy var hStack = HStack(spacing: 8, alignment: .center, distribution: .fill) private lazy var vStack = VStack(spacing: 4, alignment: .fill, distribution: .fill) private lazy var titleHStack = HStack(spacing: 4, alignment: .center, distribution: .fill)

private var isFollow: Bool = false { didSet { self.follow.isHidden = isFollow self.followLabel.isHidden = !isFollow } } ```

```swift addSubview(hStack) hStack.snp.makeConstraints { make in make.edges.equalToSuperview().inset(UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)) }

iconView.sizeConstraint = CGSize(width: 50, height: 50) follow.sizeConstraint = CGSize(width: 60, height: 30) hStack.addArrangedSubviewsMakeConstraint([iconView, vStack, hStack.spacer(), follow]) vStack.addArrangedSubviews([titleHStack, detail])

followLabel.sizeConstraint = CGSize(width: 50, height: 15) titleHStack.addArrangedSubviewsMakeConstraint([title, followLabel, titleHStack.spacer()]) ```

滾動佈局

StackView有時候也可以使用配合ScrollView一起使用,效果如同TableView,但是這個則需要使用好ScrollView的contentSize,使用frame佈局,則需要手動設置;使用自動佈局,則需要ScrollView中的contentView來填充,最終ScrollView的contentSize取決於contentView。

Simulator Screen Recording - iPhone 14 Pro - 2022-09-18 at 23.22.56.gif

有時候,寫個簡單的頁面,真的不需要那麼多代理,這不是更簡單嗎?

```swift view.addSubview(scrollView) scrollView.snp.makeConstraints { make in make.edges.equalTo(view.safeAreaLayoutGuide) }

scrollView.addSubview(vStack) vStack.snp.makeConstraints { make in make.edges.equalToSuperview(); make.width.equalToSuperview() } ```

結尾

文章使用了幾個簡單的實例,一點點的演變了不同的佈局方式,在我們日常開發中,或許有那些簡單極致的頁面,或許也有那些花裏胡哨的頁面,不管如何,佈局的思路都不會變,其實從實例中可以看出,佈局代碼所佔篇幅並不多,在配合使用一些擴展類,其實使用StackView純代碼佈局是不是比想象中要香很多呢。