Swift:UIScrollView+UIStackView构建可滑动页面

语言: CN / TW / HK

本文正在参加「金石计划 . 瓜分6万现金大奖」

前言

接上一篇,Swift:使用enum抹平数组元素差异,我通过将业务数数据,封装成为一个枚举带参的数组集合,将这个数组作为数据源去驱动UITableView显示页面,并且保证了页面的灵活性。

在留言中,有掘友提出可以通过使用UIScrollView+UIStackView的方法来构建页面。觉得是一个非常不错的点子,于是立即实践了一下。

基本思路

我们先还是回到业务数据枚举:

enum BusinessPart { case a(APart) case b(BPart) case c(CPart) case d(DPart) }

我们的DataSource数据源是这样的:

let dataSource = [a(aPart), b(bPart), c(cPart), d(dPart)]

如何将一个dataSource变成一个view呢?我们可以尝试在enum BusinessPart添加这样一个分类: ``` extension BusinessPart {

var view: UIView {

switch self {

case .a(let aPart):

let aView = AView()

aview.aPart = aPart

return aView

case .b(let bPart):

let bView = BView()

bView.bPart = bPart

return bView

case .c(let cPart):

let cView = CView()

cView.cPart = cPart

return cView

case .d(let dPart):

let dView = DView()

dView.dPart = dPart

return dView

}

} } `` 写完这个分类后,我们就可以通过map`函数来将枚举数组转换成为view数组了:

let views = ds.map { $0.view }

后面将其加入到UIStackView就可以了:

``` let stackView = UIStackView(arrangedSubviews: views)

`` 至于如何配置stackView的间距,方向,这些大家看看UIStackView`的API就可以啦。

UIScrollView+UIStackView,ScrollView如何滑动

如果大家之前有过通过SnapKitUIScrollView上添加子View的经历,一般都会知道,要保证ScrollView可以正常滑动,一般情况下,我们需要先要在ScrollView上面添加一个contentView,接着再将子View添加了到contentView上。

并且在最后一个子View进行布局的时候,对contentView的布局做一次布局更新,保证contentView的底部等于最后一个子View的底部。

而这个问题在UIScrollView+UIStackView的布局结构上同样需要注意!!!

``` scrollView.addSubview(stackView) stackView.snp.makeConstraints { make in make.edges.equalToSuperview() }

`` 在stackView.axis = .vertical时,你会发现ScrollView在纵向根本就无法滚动,必须像之前UIScrollView上面添加子View的经验,添加一个contentView`才行:

``` private func verticalLayout() { stackView.axis = .vertical stackView.spacing = 20 stackView.alignment = .fill

view.addSubview(scrollView)
scrollView.snp.makeConstraints { make in
    make.edges.equalToSuperview()
}

let contentView = UIView()

scrollView.addSubview(contentView)
contentView.snp.makeConstraints { make in
    make.edges.equalToSuperview()
    make.width.equalTo(kScreenWidth)
}

contentView.addSubview(stackView)
stackView.snp.makeConstraints { make in
    make.edges.equalToSuperview()
    make.bottom.equalTo(contentView.snp.bottom)
}

for _ in 0..<20 {
    stackView.addArrangedSubview(circle)
}

} ```

不过同时你会发现,如果stackView.axis = .horizontal时,就算不添加contentView,ScrollView在横向还是可以正常滑动:

``` private func horizontalLayout() { stackView.axis = .horizontal stackView.spacing = 20 stackView.alignment = .center

view.addSubview(scrollView)
scrollView.snp.makeConstraints { make in
    make.edges.equalToSuperview()
}

scrollView.addSubview(stackView)
stackView.snp.makeConstraints { make in
    make.edges.equalToSuperview()
}

for _ in 0..<20 {
    stackView.addArrangedSubview(circle)
}

} ```

以上两点大家在平时使用的时候都需要加以注意。

总结

本篇文章其实对上一篇文章里UI布局层面上的一点扩展,UIScrollView+UIStackView也可以说是一种不错的布局方案。

同时对于UIScrollView+UIStackView布局中的注意事项做了简单的提示。

不过我个人对于这种数据驱动型的页面构建,还是更倾向于使用UITableView这种通过数据源构建页面。因为当做进行下拉刷新操作的时候,UITableView就是傻瓜操作,但是如果是UIStackView,相当于要对stackView进行UI上的重构,从用户感知体验和性能上都差一些。

参考文档

UIStackView inside UIScrollView

UIKit: Programmatically embed a UIStackView in an UIScrollView using AutoLayout

自己写的项目,欢迎大家star⭐️

RxStudy:RxSwift/RxCocoa框架,MVVM模式编写wanandroid客户端。

GetXStudy:使用GetX,重构了Flutter wanandroid客户端。

本文正在参加「金石计划 . 瓜分6万现金大奖」