UIScrollView在Autolayout中没有正确调整大小

时间:2015-07-22 02:12:25

标签: ios swift uiscrollview autolayout

我正在尝试使用通用设备将Ray Wenderlich UIScrollView Tutorial的第1部分转换为Autolayout。我目前在导航控制器中嵌入了UITableView,将UIViewControllerViewControllerUIScrollView(没有自定义类)相关联。导航控制器有一个不透明的导航栏,没有工具栏。 UIViewController的属性可以在下面相册的第一张图片中看到。

Image Album

只有四个故事板限制(如下所示),我的视图看起来像是专辑中的第二张图片,scrollView的框架尺寸不正确600x536。为了解决这个问题,我决定在运行时再次在viewDidLoad() 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 InsetsExtend Edges Under Top BarsExtend Edges Under Opaque Bars(请参阅第一张图片)之外,我还在代码中禁用它们,但无济于事。
  • 我无法使用插图,因为缩放后UIScrollView的框架会发生变化。

如何让UIScrollView成为一个恒定,合适的尺寸?

谢谢。

类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)
}

1 个答案:

答案 0 :(得分:0)

解决!感谢Working with Top Layout Guide in UIScrollView through Auto Layout。我不认为UIScrollView会使topLayoutGuide的行为有所不同,但显然它确实如此。事实证明我不需要设置约束; scrollView.layoutIfNeeded()可以解决问题!我的scrollView现在是一个常量375x667,删除了调整大小问题并给出了self.topLayoutGuide.length = 64.这使我可以通过减去self.topLayoutGuide.length中的centerScrollViewContents()来垂直居中。我也在centerScrollViewContents()中致电viewWillLayoutSubviews()。这是我的新代码:

@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()
}

所有其他功能均未更改。