如何使用自动/动态设置滚动视图来适应内容视图



令人惊讶的是,这比我想象的要难。我遵循这个教程,这似乎相当简单,但我通过编程创建我的视图,而不是使用故事板。需要说明的是,我添加到内容视图中的内容是静态的,即它不会增长或增加。

下面是滚动视图和内容视图的定义:

lazy var contentView : UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
lazy var scrollView : UIScrollView = {
let scrollView = UIScrollView(frame: .zero)
scrollView.backgroundColor = .white
scrollView.frame = self.view.bounds
scrollView.bounces = true
scrollView.autoresizingMask = .flexibleHeight
scrollView.contentSize = CGSize(width: self.view.frame.width, height: contentView.frame.height)
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()

在viewdidload中添加滚动视图并在视图控制器中设置其约束:

view.addSubview(scrollView)
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true

然后我添加内容视图和约束:

scrollView.addSubview(contentView)
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
contentView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
let constraint = contentView.heightAnchor.constraint(equalTo: view.heightAnchor)
constraint.priority = UILayoutPriority(250)
constraint.isActive = true

问题是我不能一直滚动到底部。

初始注意事项

删除
scrollView.frame = self.view.bounds

scrollView一个frame是没有意义的,因为你稍后会通过使用约束给它一个框架。

删除
scrollView.autoresizingMask = .flexibleHeight

你正在使用约束,而不是自动调整大小蒙版,给滚动视图它的框架和以后的调整大小行为。

删除
scrollView.contentSize = CGSize(width: self.view.frame.width, height: contentView.frame.height)

一旦滚动视图受到约束的影响,你必须使用约束,而不是contentSize,给它一个决定滚动行为的内容大小。

添加内容视图

有了这些基础,让我们讨论一下如何将内容视图添加到滚动视图:

scrollView.addSubview(contentView)
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true

这并不是完全错误的,但它是非常过时的。你应该把内容视图固定在滚动视图的内容布局指南上;这就是它的作用。所以,在你有equalTo: scrollView的地方,把它改成equalTo: scrollView.contentLayoutGuide

滚动

好吧!现在一切都组装好了,我们准备讨论滚动。在这个配置中,使滚动视图可滚动的是内容视图比滚动视图本身大。到目前为止,这还不是真的;事实上,内容视图根本没有大小。所以我们必须给它一个大小。

你那样做的企图是相当微弱的。让我们提取给内容视图高度和宽度限制的关键行:
contentView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
contentView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true

(删除其他两行,因为它们现在没有真正做任何有用的事情。)内容视图比滚动视图大吗?好吧,也许,但如果是这样,只有一点点,因为内容视图只是主视图的大小,和滚动视图是相同的大小或稍微小一点。

因为我们只是在演示,所以最好让内容视图比滚动视图大很多,这样我们就可以进行一些主要的滚动。将第二行更改为:

contentView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier:2 ).isActive = true

是的,宝贝!现在我们可以真正滚动了

使内容更可见

仍然很难看到发生了什么(所有的东西都是白色的),所以我建议你用一些颜色填充内容视图,这将允许我们看到发生了什么。如下声明一个自绘制视图:

class MyView : UIView {
override class var layerClass : AnyClass { CAGradientLayer.self }
override func willMove(toSuperview newSuperview: UIView?) {
let lay = self.layer as! CAGradientLayer
lay.colors = [UIColor.red.cgColor, UIColor.green.cgColor]
}
}

现在改变

let view = UIView()

let view = MyView()

现在当你滚动到底部时,它是非常明显的;真正的绿色在底部。

总结下面是改正后的完整代码:

class MyView : UIView {
override class var layerClass : AnyClass { CAGradientLayer.self }
override func willMove(toSuperview newSuperview: UIView?) {
let lay = self.layer as! CAGradientLayer
lay.colors = [UIColor.red.cgColor, UIColor.green.cgColor]
}
}
class ViewController: UIViewController {

lazy var contentView : UIView = {
let view = MyView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
lazy var scrollView : UIScrollView = {
let scrollView = UIScrollView(frame: .zero)
scrollView.backgroundColor = .white
scrollView.bounces = true
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()

override func viewDidLoad() {
super.viewDidLoad()

view.addSubview(scrollView)
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true

scrollView.addSubview(contentView)
contentView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor).isActive = true
contentView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor).isActive = true
contentView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor).isActive = true
contentView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
contentView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier:2 ).isActive = true
}

}

最新更新