swift-不能使用AutoLayout在UIScrollView中居中UIImageView

时间:2015-02-16 02:41:12

标签: ios swift uiscrollview uiimageview autolayout

我搜索了很多关于UIScrollView的{​​{1}}个文章,但都没有UIImageView信息。我所做的是:在AutoLayout中放置UIScrollView,约束前10名,前10名,后50名,后10名;将UIViewController置于UIImageView内,约束前0位,前0位,后0位,后0位。我想要的很简单:让我的UIScrollView适合我的UIImageView时app首次加载,让我的UIScrollView水平和垂直居中。现在我可以看到图像并恰好适合屏幕,但图像位于UIImageView的顶部。(注意:在这种情况下,我的图像宽度在缩放到最小UIScrollView之后等于宽度为zoomScale,缩放后的图像高度UIScrollView小于zoomScale的宽度。) 我真的无法将UIScrollView垂直移动到UIImageView的中心,无法找到我犯错的位置。非常感谢。

UIScrollView

3 个答案:

答案 0 :(得分:6)

小猪支持pic-o-matic的回答。我有一个案例,我需要将图像居中,只要它小于滚动视图框架。使用插图进行简单的解决方案。

if imageView.frame.height <= scrollView.frame.height {
        let shiftHeight = scrollView.frame.height/2.0 - scrollView.contentSize.height/2.0
        scrollView.contentInset.top = shiftHeight
    }
    if imageView.frame.width <= scrollView.frame.width {
        let shiftWidth = scrollView.frame.width/2.0 - scrollView.contentSize.width/2.0
        scrollView.contentInset.left = shiftWidth
    }

答案 1 :(得分:3)

我遇到了同样的问题。我找到了一个完美的解决方案,请查看这个github项目:https://github.com/evgenyneu/ios-imagescroll-swift

它本质上是如何工作的如下:它调整你的约束,如果它被缩小得足够远,使图像居中,并使其在宽度或高度超过容器的相应宽度或高度后进行缩放和滚动。

感谢这个帖子:Zooming UIImageView inside UIScrollView with autolayout(obj-c和swift solution available)!

//  ViewController.swift
//  image-scroll-swift
//
//  Created by Evgenii Neumerzhitckii on 4/10/2014.
//  Copyright (c) 2014 Evgenii Neumerzhitckii. All rights reserved.
//

import UIKit

let imageScrollLargeImageName = "wallabi.jpg"


class ViewController: UIViewController, UIScrollViewDelegate {

  @IBOutlet weak var scrollView: UIScrollView!
  @IBOutlet weak var imageView: UIImageView!

  @IBOutlet weak var imageConstraintTop: NSLayoutConstraint!
  @IBOutlet weak var imageConstraintRight: NSLayoutConstraint!
  @IBOutlet weak var imageConstraintLeft: NSLayoutConstraint!
  @IBOutlet weak var imageConstraintBottom: NSLayoutConstraint!

  var lastZoomScale: CGFloat = -1

  override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    imageView.image = UIImage(named: imageScrollLargeImageName)
    scrollView.delegate = self
    updateZoom()
  }

  // Update zoom scale and constraints
  // It will also animate because willAnimateRotationToInterfaceOrientation
  // is called from within an animation block
  //
  // DEPRECATION NOTICE: This method is said to be deprecated in iOS 8.0. But it still works.
  override func willAnimateRotationToInterfaceOrientation(
    toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {

    super.willAnimateRotationToInterfaceOrientation(toInterfaceOrientation, duration: duration)
    updateZoom()
  }

  func updateConstraints() {
    if let image = imageView.image {
      let imageWidth = image.size.width
      let imageHeight = image.size.height

      let viewWidth = view.bounds.size.width
      let viewHeight = view.bounds.size.height

      // center image if it is smaller than screen
      var hPadding = (viewWidth - scrollView.zoomScale * imageWidth) / 2
      if hPadding < 0 { hPadding = 0 }

      var vPadding = (viewHeight - scrollView.zoomScale * imageHeight) / 2
      if vPadding < 0 { vPadding = 0 }

      imageConstraintLeft.constant = hPadding
      imageConstraintRight.constant = hPadding

      imageConstraintTop.constant = vPadding
      imageConstraintBottom.constant = vPadding

      // Makes zoom out animation smooth and starting from the right point not from (0, 0)
      view.layoutIfNeeded()
    }
  }

  // Zoom to show as much image as possible unless image is smaller than screen
  private func updateZoom() {
    if let image = imageView.image {
      var minZoom = min(view.bounds.size.width / image.size.width,
        view.bounds.size.height / image.size.height)

      if minZoom > 1 { minZoom = 1 }

      scrollView.minimumZoomScale = minZoom

      // Force scrollViewDidZoom fire if zoom did not change
      if minZoom == lastZoomScale { minZoom += 0.000001 }

      scrollView.zoomScale = minZoom
      lastZoomScale = minZoom
    }
  }


  // UIScrollViewDelegate
  // -----------------------

  func scrollViewDidZoom(scrollView: UIScrollView) {
    updateConstraints()
  }

  func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
    return imageView
  }

}

确保您的故事板包含一个viewcontroller。在“查看”中放置“滚动视图”,然后在“滚动视图”中放置“图像视图”。

在“滚动视图”和“视图”之间建立0(或您喜欢的任何值)的上/下/前导/尾随约束。然后在图像和滚动视图之间建立相同的约束并将它们连接到@IBOutlets。

这应该可以正常工作,因为代码会在缩放时更改约束。

答案 2 :(得分:1)

我有相同的问题&#34; ..但没有自动布局。我提出了这个解决方案(使用插图使图像居中)。 必须将automatedAdjustsScrollViewInsets属性设置为false。

override func viewDidLoad() {
    super.viewDidLoad()
    //create scrollview
    self.automaticallyAdjustsScrollViewInsets = false
    myScrollview = MyScrollview(frame: self.view.frame)
    myScrollview.alwaysBounceHorizontal = true
    myScrollview.alwaysBounceVertical = true
    myScrollview.delegate = self
    //....
}
override func viewWillLayoutSubviews() {
    //setup frame portrait and landscape
    myScrollview.frame = self.view.frame
    myScrollview.zoomScale = self.view.frame.width / photo.size.width
    myScrollview.minimumZoomScale = self.view.bounds.width / photo.size.width

    // calculate inset to center vertically
    let shift = myScrollview.frame.height/2.0 - myScrollview.contentSize.height/2.0
    myScrollview.contentInset.top = shift
}

override func viewDidLayoutSubviews() {

}

func scrollViewDidZoom(scrollView: UIScrollView) {
    let shift = myScrollview.frame.height/2.0 - myScrollview.contentSize.height/2.0
    myScrollview.contentInset.top = shift
}

我使用了UIScrollView的子类,&#34; MyScrollview&#34;到&#34;看&#34;最新消息,我认为这对了解scrollview,边框和内容大小很有用:

//
//  MyScrollview.swift
//  CampingDeHooiberg  
//
//  Created by Andre Lam on 09-03-15.
//  Copyright (c) 2015 Andre Lam. All rights reserved.
//

import UIKit

class MyScrollview: UIScrollView {

    override var bounds: CGRect { willSet { println("bounds set: \(newValue) contentSize:\(self.contentSize) frame:\(self.frame)")}}
    override var contentSize: CGSize { willSet { println("bounds:\(self.bounds) set contentsize:\(newValue)  frame: \(self.frame)")}}
    override var frame: CGRect { willSet { println("bounds: \(self.bounds) contentSize:\(self.contentSize) frame set:\(newValue)")}}

override init(frame: CGRect) {
    super.init(frame: frame)
}

required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

}