UIScrollView 在自动布局中未正确调整大小
UIScrollView Not Sizing Properly In Autolayout
我正在尝试将 Ray Wenderlich UIScrollView Tutorial 的第 1 部分转换为使用通用设备的自动布局。我目前在导航控制器中嵌入了一个 UITableView
,将 class ViewController
的 UIViewController
与 UIScrollView
(无自定义 class)连接起来.导航控制器有一个不透明的导航栏,没有工具栏。 UIViewController
的属性可以在下面相册的第一张图片中看到。
只有四个情节提要限制(如下所述),我的视图看起来像相册中的第二张图片,scrollView
的帧大小不正确 600x536
。为了解决这个问题,我决定在运行时再次添加约束,在 viewDidLoad()
in ViewController.swift
中。我现在总共有 8 个约束:
- 故事板上的 4 个约束条件:
scrollView.top
= topLayoutGuide.bottom
scrollView.bottom
= bottomLayoutGuide.top
scrollView.leading
= superView.leading
scrollView.trailing
= superView.trailing
ViewController.swift
中的 4 个约束:
scrollView.top
= topLayoutGuide
scrollView.bottom
= view.bottom
scrollView.leading
= view.leading
scrollView.trailing
= view.trailing
由于这些限制,在缩放之前,我的视图现在看起来像第三张专辑图像,scrollView
的帧大小仍然不正确 375x667
。缩放后,我的视图是正确的,看起来像第四张相册图像,scrollView
的帧大小正确 375x603
。其他一些注意事项:
self.topLayoutGuide.length = 0
。不应该是64吗? 20 个来自状态栏,44 个来自导航栏?
- 删除故事板约束会导致与没有编程约束相同的问题。为什么故事板约束仍然需要存在?
- 纯方法和混合方法我都试过了,都没有解决这个问题。
- 除了在故事板中禁用
Adjust Scroll View Insets
、Extend Edges Under Top Bars
和 Extend Edges Under Opaque Bars
(见第一张图片)外,我还在代码中禁用它们,但无济于事。
- 我无法使用插图,因为
UIScrollView
的框架在缩放后发生了变化。
如何让 UIScrollView
成为一个常数,合适的大小?
谢谢。
class ViewController: UIViewController, UIScrollViewDelegate
@IBOutlet var scrollView: UIScrollView!
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
//Reset the layout
scrollView.needsUpdateConstraints()
scrollView.setNeedsLayout()
scrollView.layoutIfNeeded()
//Set storyboard settings just in case
scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
self.extendedLayoutIncludesOpaqueBars = false
self.edgesForExtendedLayout = .None
self.automaticallyAdjustsScrollViewInsets = false
self.navigationController?.navigationBar.translucent = false
//Manually added constraints at runtime
var constraintTS = NSLayoutConstraint(item: scrollView, attribute: .Top, relatedBy: .Equal, toItem: topLayoutGuide, attribute: .Bottom, multiplier: 1.0, constant: 0)
var constraintBS = NSLayoutConstraint(item: scrollView, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Bottom, multiplier: 1.0, constant: 0)
var constraintLS = NSLayoutConstraint(item: scrollView, attribute: .Leading, relatedBy: .Equal, toItem: view, attribute: .Leading, multiplier: 1.0, constant: 0)
var constraintRS = NSLayoutConstraint(item: scrollView, attribute: .Trailing, relatedBy: .Equal, toItem: view, attribute: .Trailing, multiplier: 1.0, constant: 0)
view.addConstraint(constraintTS)
view.addConstraint(constraintBS)
view.addConstraint(constraintLS)
view.addConstraint(constraintRS)
println(scrollView.frame.width)
println(scrollView.frame.height)
//Original Ray Wenderlich code
let image1 = UIImage(named: "photo1")!
imageView = UIImageView(image: image1)
imageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: image1.size)
scrollView.addSubview(imageView)
scrollView.contentSize = image1.size
let scrollViewFrame = scrollView.frame
let scaleWidth = scrollViewFrame.width / scrollView.contentSize.width
let scaleHeight = scrollViewFrame.height / scrollView.contentSize.height
let minScale = min(scaleWidth, scaleHeight)
scrollView.minimumZoomScale = minScale
scrollView.maximumZoomScale = 1.0
scrollView.zoomScale = minScale
centerScrollViewContents()
}
func centerScrollViewContents() {
let boundsSize = scrollView.bounds.size
var contentsFrame = imageView.frame
if contentsFrame.size.width < boundsSize.width {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.width) / 2.0
} else {
contentsFrame.origin.x = 0.0
}
if contentsFrame.size.height < boundsSize.height {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.height) / 2.0
println("boundsSize.height: \(boundsSize.height)")
println("boundsSize.width: \(boundsSize.width)")
println("contentsFrame.origin.y: \(contentsFrame.origin.y)")
} else {
contentsFrame.origin.y = 0.0
}
imageView.frame = contentsFrame
}
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
func scrollViewDidZoom(scrollView: UIScrollView) {
centerScrollViewContents()
}
override func viewWillLayoutSubviews() {
println(self.topLayoutGuide.length)
}
已解决!感谢 Working with Top Layout Guide in UIScrollView through Auto Layout。我认为 UIScrollView 不会使 topLayoutGuide
的行为有所不同,但显然确实如此。还证明我不需要设置约束; scrollView.layoutIfNeeded()
成功了!我的 scrollView 现在是一个恒定的 375x667,消除了调整大小的问题并给出 self.topLayoutGuide.length
= 64。这允许我通过在 centerScrollViewContents()
中减去 self.topLayoutGuide.length
来使视图垂直居中。我也在viewWillLayoutSubviews()
中调用了centerScrollViewContents()
。这是我的新代码:
@IBOutlet var scrollView: UIScrollView!
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
//Redo constraints at runtime
scrollView.layoutIfNeeded()
//Original Ray Wenderlich code
let image1 = UIImage(named: "photo1")!
imageView = UIImageView(image: image1)
imageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: image1.size)
scrollView.addSubview(imageView)
scrollView.contentSize = image1.size
let scrollViewFrame = scrollView.frame
let scaleWidth = scrollViewFrame.width / scrollView.contentSize.width
let scaleHeight = scrollViewFrame.height / scrollView.contentSize.height
let minScale = min(scaleWidth, scaleHeight)
scrollView.minimumZoomScale = minScale
scrollView.maximumZoomScale = 1.0
scrollView.zoomScale = minScale
}
func centerScrollViewContents() {
let boundsSize = scrollView.bounds.size
var contentsFrame = imageView.frame
if contentsFrame.size.width < boundsSize.width {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.width) / 2.0
} else {
contentsFrame.origin.x = 0.0
}
if contentsFrame.size.height < boundsSize.height {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.height - self.topLayoutGuide.length) / 2.0
} else {
contentsFrame.origin.y = 0.0
}
imageView.frame = contentsFrame
}
override func viewWillLayoutSubviews() {
println(self.topLayoutGuide.length)
centerScrollViewContents()
}
所有其他功能均未更改。
我正在尝试将 Ray Wenderlich UIScrollView Tutorial 的第 1 部分转换为使用通用设备的自动布局。我目前在导航控制器中嵌入了一个 UITableView
,将 class ViewController
的 UIViewController
与 UIScrollView
(无自定义 class)连接起来.导航控制器有一个不透明的导航栏,没有工具栏。 UIViewController
的属性可以在下面相册的第一张图片中看到。
只有四个情节提要限制(如下所述),我的视图看起来像相册中的第二张图片,scrollView
的帧大小不正确 600x536
。为了解决这个问题,我决定在运行时再次添加约束,在 viewDidLoad()
in ViewController.swift
中。我现在总共有 8 个约束:
- 故事板上的 4 个约束条件:
scrollView.top
=topLayoutGuide.bottom
scrollView.bottom
=bottomLayoutGuide.top
scrollView.leading
=superView.leading
scrollView.trailing
=superView.trailing
ViewController.swift
中的 4 个约束:scrollView.top
=topLayoutGuide
scrollView.bottom
=view.bottom
scrollView.leading
=view.leading
scrollView.trailing
=view.trailing
由于这些限制,在缩放之前,我的视图现在看起来像第三张专辑图像,scrollView
的帧大小仍然不正确 375x667
。缩放后,我的视图是正确的,看起来像第四张相册图像,scrollView
的帧大小正确 375x603
。其他一些注意事项:
self.topLayoutGuide.length = 0
。不应该是64吗? 20 个来自状态栏,44 个来自导航栏?- 删除故事板约束会导致与没有编程约束相同的问题。为什么故事板约束仍然需要存在?
- 纯方法和混合方法我都试过了,都没有解决这个问题。
- 除了在故事板中禁用
Adjust Scroll View Insets
、Extend Edges Under Top Bars
和Extend Edges Under Opaque Bars
(见第一张图片)外,我还在代码中禁用它们,但无济于事。 - 我无法使用插图,因为
UIScrollView
的框架在缩放后发生了变化。
如何让 UIScrollView
成为一个常数,合适的大小?
谢谢。
class ViewController: UIViewController, UIScrollViewDelegate
@IBOutlet var scrollView: UIScrollView!
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
//Reset the layout
scrollView.needsUpdateConstraints()
scrollView.setNeedsLayout()
scrollView.layoutIfNeeded()
//Set storyboard settings just in case
scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
self.extendedLayoutIncludesOpaqueBars = false
self.edgesForExtendedLayout = .None
self.automaticallyAdjustsScrollViewInsets = false
self.navigationController?.navigationBar.translucent = false
//Manually added constraints at runtime
var constraintTS = NSLayoutConstraint(item: scrollView, attribute: .Top, relatedBy: .Equal, toItem: topLayoutGuide, attribute: .Bottom, multiplier: 1.0, constant: 0)
var constraintBS = NSLayoutConstraint(item: scrollView, attribute: .Bottom, relatedBy: .Equal, toItem: view, attribute: .Bottom, multiplier: 1.0, constant: 0)
var constraintLS = NSLayoutConstraint(item: scrollView, attribute: .Leading, relatedBy: .Equal, toItem: view, attribute: .Leading, multiplier: 1.0, constant: 0)
var constraintRS = NSLayoutConstraint(item: scrollView, attribute: .Trailing, relatedBy: .Equal, toItem: view, attribute: .Trailing, multiplier: 1.0, constant: 0)
view.addConstraint(constraintTS)
view.addConstraint(constraintBS)
view.addConstraint(constraintLS)
view.addConstraint(constraintRS)
println(scrollView.frame.width)
println(scrollView.frame.height)
//Original Ray Wenderlich code
let image1 = UIImage(named: "photo1")!
imageView = UIImageView(image: image1)
imageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: image1.size)
scrollView.addSubview(imageView)
scrollView.contentSize = image1.size
let scrollViewFrame = scrollView.frame
let scaleWidth = scrollViewFrame.width / scrollView.contentSize.width
let scaleHeight = scrollViewFrame.height / scrollView.contentSize.height
let minScale = min(scaleWidth, scaleHeight)
scrollView.minimumZoomScale = minScale
scrollView.maximumZoomScale = 1.0
scrollView.zoomScale = minScale
centerScrollViewContents()
}
func centerScrollViewContents() {
let boundsSize = scrollView.bounds.size
var contentsFrame = imageView.frame
if contentsFrame.size.width < boundsSize.width {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.width) / 2.0
} else {
contentsFrame.origin.x = 0.0
}
if contentsFrame.size.height < boundsSize.height {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.height) / 2.0
println("boundsSize.height: \(boundsSize.height)")
println("boundsSize.width: \(boundsSize.width)")
println("contentsFrame.origin.y: \(contentsFrame.origin.y)")
} else {
contentsFrame.origin.y = 0.0
}
imageView.frame = contentsFrame
}
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
func scrollViewDidZoom(scrollView: UIScrollView) {
centerScrollViewContents()
}
override func viewWillLayoutSubviews() {
println(self.topLayoutGuide.length)
}
已解决!感谢 Working with Top Layout Guide in UIScrollView through Auto Layout。我认为 UIScrollView 不会使 topLayoutGuide
的行为有所不同,但显然确实如此。还证明我不需要设置约束; scrollView.layoutIfNeeded()
成功了!我的 scrollView 现在是一个恒定的 375x667,消除了调整大小的问题并给出 self.topLayoutGuide.length
= 64。这允许我通过在 centerScrollViewContents()
中减去 self.topLayoutGuide.length
来使视图垂直居中。我也在viewWillLayoutSubviews()
中调用了centerScrollViewContents()
。这是我的新代码:
@IBOutlet var scrollView: UIScrollView!
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
//Redo constraints at runtime
scrollView.layoutIfNeeded()
//Original Ray Wenderlich code
let image1 = UIImage(named: "photo1")!
imageView = UIImageView(image: image1)
imageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: image1.size)
scrollView.addSubview(imageView)
scrollView.contentSize = image1.size
let scrollViewFrame = scrollView.frame
let scaleWidth = scrollViewFrame.width / scrollView.contentSize.width
let scaleHeight = scrollViewFrame.height / scrollView.contentSize.height
let minScale = min(scaleWidth, scaleHeight)
scrollView.minimumZoomScale = minScale
scrollView.maximumZoomScale = 1.0
scrollView.zoomScale = minScale
}
func centerScrollViewContents() {
let boundsSize = scrollView.bounds.size
var contentsFrame = imageView.frame
if contentsFrame.size.width < boundsSize.width {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.width) / 2.0
} else {
contentsFrame.origin.x = 0.0
}
if contentsFrame.size.height < boundsSize.height {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.height - self.topLayoutGuide.length) / 2.0
} else {
contentsFrame.origin.y = 0.0
}
imageView.frame = contentsFrame
}
override func viewWillLayoutSubviews() {
println(self.topLayoutGuide.length)
centerScrollViewContents()
}
所有其他功能均未更改。