我在MyView文件中以编程方式创建了一个scrollView。
let myScrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.isUserInteractionEnabled = true
return scrollView
}()
使用可视格式语言我将所有约束设置为等于superView。
func setupViews() {
self.frame = UIScreen.main.bounds
addSubview(myScrollView)
addConstraintsWithFormat(format: "H:|[v0]|", views: myScrollView)
addConstraintsWithFormat(format: "V:|[v0]|", views: myScrollView)
}
我的scrollView有一个按钮和一个标签。
在viewDidLayoutSubviews中的viewController中,我设置了contentSize:
myView.myScrollView.contentSize = CGSize(width: self.view.frame.size.width, height: self.view.frame.size.height + 200)
一切正常:我可以滚动,myScrollView的高度是完美的,但宽度仅适用于iPhone X.
以下是iPhone SE的示例:
ScrollView比屏幕宽。在iPhone Plus中,它比屏幕小。
我做错了什么,我该如何解决?
先感谢您!
首先,永远不要在addSubview
做layoutSubviews()
。这意味着您在每个布局中添加视图。您可能最终在层次结构中有几个scrollView。
其次,你可以做一个scrollView.frame = bounds
并相应地计算你的实际contentSize
。内容大小与scrollView的frame
无关。你需要获得最底层的视图并获得他的最大值。 X轴也是如此。如果您希望内容仅垂直滚动,那么像contentSize = CGSize(width: width, height: lastViewInScrollView.frame.maxY)
这样的东西可以工作。
如果你绝对需要VFL,至少要正确计算你的contentSize
(即scrollView
中包含的视图的实际帧)
对于在scrollView外部进行布局的视图,可能是您为这些视图设置了错误的大小。
使用自动布局和滚动视图时,无需计算任何显式大小。在loadView
中创建滚动视图(纯粹的程序化应用程序很可能会在这里完成)或viewDidLoad
:
override func loadView() {
...
addScrollView()
addScrollViewHeader()
// add subviews
addScrollViewFooter()
}
func addScrollView() {
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1).isActive = true
scrollView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 1).isActive = true
}
Apple的文档中有一些规则可以使其与autolayout一起使用,例如,如果我没记错的话,不依赖于滚动视图本身来确定其中任何子视图的大小。但我们的想法是确保最外侧视图(最顶部,最底部,最左侧,最右侧)锚定到滚动视图,滚动视图的内容大小将自动缩放。
所以我要做的是在顶部和底部创建透明视图,以便为我拉伸滚动视图的内容大小,然后中间的任何内容都会自动展开和收缩滚动视图。我使用这些页眉/页脚视图而不是简单地向最顶层约束和最底层约束添加常量(在滚动视图的顶部和底部创建一些额外填充)的原因是因为常量似乎被忽略。表面上必须是视图和内容大小边缘之间的“物理”接触以拉伸它。
func addScrollViewHeader() {
scrollViewHeader.isUserInteractionEnabled = false
scrollViewHeader.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(scrollViewHeader)
scrollViewHeader.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
scrollViewHeader.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
scrollViewHeader.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollViewHeader.heightAnchor.constraint(equalToConstant: Shared.statusBarHeight + 32).isActive = true
}
//中间的子视图
func addScrollViewFooter() {
scrollViewFooter.isUserInteractionEnabled = false
scrollViewFooter.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(scrollViewFooter)
scrollViewFooter.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
scrollViewFooter.topAnchor.constraint(equalTo: lastView.bottomAnchor).isActive = true
scrollViewFooter.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollViewFooter.heightAnchor.constraint(equalToConstant: 32).isActive = true
// and the most important constraint to make it work
scrollViewFooter.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
}