【问题标题】:UIScrollView Not Sizing Properly In AutolayoutUIScrollView 在自动布局中未正确调整大小
【发布时间】:2015-07-22 02:12:25
【问题描述】:

我正在尝试将Ray Wenderlich UIScrollView Tutorial 的第 1 部分转换为具有通用设备的自动布局。我目前在导航控制器中嵌入了一个UITableView,将ViewController 类的UIViewControllerUIScrollView(没有自定义类)连接起来。导航控制器有一个不透明的导航栏,没有工具栏。 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)
}

【问题讨论】:

    标签: ios swift uiscrollview autolayout


    【解决方案1】:

    解决了!感谢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()
    }
    

    所有其他功能都没有改变。

    【讨论】:

      猜你喜欢
      • 2012-11-18
      • 1970-01-01
      • 2017-03-06
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 2015-08-16
      • 2014-04-29
      • 1970-01-01
      相关资源
      最近更新 更多