在具有较大 contentSize 的 UIScrollView 中居中 UIImageView

Posted

技术标签:

【中文标题】在具有较大 contentSize 的 UIScrollView 中居中 UIImageView【英文标题】:Center UIImageView within a UIScrollView with a larger contentSize 【发布时间】:2018-04-18 15:04:37 【问题描述】:

我有一个全屏scrollView,我在其中添加了一个imageView 作为子视图。我希望imageView 在开始时居中并缩放填充scrollView 的大小(即屏幕大小),但随后允许用户以相等的方式在两个方向(垂直和水平)滚动图像左、右、上、下偏移。

我的意思是:我已将滚动视图的 contentSize 设置为 CGSize(width: screenWidth + 200, height: screenHeight + 200),如果我运行该应用程序,我发现我只能将这 200 点的偏移量滚动到右侧和底部的图像。我希望图像以内容大小为中心,并且能够以每侧偏移 100 pts 的方式将其水平滚动到左侧和右侧(垂直滚动时与顶部和底部类似)。

我怎样才能做到这一点?

注意:我在代码中设置了所有 UI,我没有使用故事板,也没有使用 xib 文件

【问题讨论】:

【参考方案1】:

您可能会发现使用约束和自动布局比使用screenWidthscreenHeight 更容易/更直观:

//
//  CenteredScrollViewController.swift
//  SW4Temp
//
//  Created by Don Mag on 4/18/18.
//

import UIKit

class CenteredScrollViewController: UIViewController 

    let theScrollView: UIScrollView = 
        let v = UIScrollView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = UIColor.green
        return v
    ()

    let theImageView: UIImageView = 
        let v = UIImageView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = UIColor.blue
        return v
    ()

    override func viewDidLoad() 
        super.viewDidLoad()

        // add the scrollView to the main view
        view.addSubview(theScrollView)

        // add the imageView to the scrollView
        theScrollView.addSubview(theImageView)

        // pin the scrollView to all four sides
        theScrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0.0).isActive = true
        theScrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0.0).isActive = true
        theScrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0).isActive = true
        theScrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0.0).isActive = true

        // constrain the imageView's width and height to the scrollView's width and height
        theImageView.widthAnchor.constraint(equalTo: theScrollView.widthAnchor, multiplier: 1.0).isActive = true
        theImageView.heightAnchor.constraint(equalTo: theScrollView.heightAnchor, multiplier: 1.0).isActive = true

        // set the imageView's top / bottom / leading / trailing anchors
        // this *also* determines the scrollView's contentSize (scrollable area)
        // with 100-pt padding on each side
        theImageView.topAnchor.constraint(equalTo: theScrollView.topAnchor, constant: 100.0).isActive = true
        theImageView.bottomAnchor.constraint(equalTo: theScrollView.bottomAnchor, constant: -100.0).isActive = true
        theImageView.leadingAnchor.constraint(equalTo: theScrollView.leadingAnchor, constant: 100.0).isActive = true
        theImageView.trailingAnchor.constraint(equalTo: theScrollView.trailingAnchor, constant: -100.0).isActive = true

    

    override func viewDidAppear(_ animated: Bool) 
        super.viewDidAppear(animated)
        // set the scrollView's contentOffset (to center the imageView)
        theScrollView.contentOffset = CGPoint(x: 100, y: 100)
    


【讨论】:

这对我有用,核心是在四面八方设置锚点以及宽度和高度锚点【参考方案2】:

您只能向下和向右移动,因为您当前的内容偏移量是 0,0,所以左上角 - 因此您可以向下移动 200 和向右移动 200。

你想要的是滚动 1/2 的垂直填充和 1/2 的水平填充,所以在你的情况下你会做 scrollView.contentOffset = CGPoint(x: 100, y: 100)

为了让一切正常工作,UIImageView 的大小必须与scrollView 的 contentSize 大小相同,比屏幕大小大。

鉴于 cmets 我认为您想要的是填充屏幕的图像,然后用户可以滚动到图像的边界之外,那么您只需将 UIImageView 的大小设置为屏幕的大小 x 和y 坐标与scrollViewcontentOffset 相同,因此 (100, 100)。

以下是执行此操作的示例应用的视频: https://dzwonsemrish7.cloudfront.net/items/2v361r2p0O2j1D3x3W10/Screen%20Recording%202018-04-19%20at%2002.32%20PM.mov

【讨论】:

谢谢,但实际上我想要的是在图像周围有“空白”偏移,我不希望图像填充滚动视图的内容大小。另一方面,contentOffset 似乎从一开始就显示出这样的偏移量。我还想在开始时显示填充屏幕大小的图像,然后能够使用这些偏移量滚动它。 这是需要的还是我遗漏了什么? dzwonsemrish7.cloudfront.net/items/2v361r2p0O2j1D3x3W10/… @AppsDev 这就是你想要的吗?【参考方案3】:

试试这个 斯威夫特 4.* 或 5.*

let maxScale = self.imageScrollView.maximumZoomScale
let minScale = self.imageScrollView.minimumZoomScale

if let imageSize = imageView.image?.size
    let topOffset: CGFloat = (boundsSize.height - minScale * imageSize.height ) / 2
    let leftOffset: CGFloat = (boundsSize.width - minScale * imageSize.width ) / 2
    self.imageScrollView.contentInset = UIEdgeInsets(top: topOffset, left: leftOffset, bottom: 0, right: 0)

【讨论】:

以上是关于在具有较大 contentSize 的 UIScrollView 中居中 UIImageView的主要内容,如果未能解决你的问题,请参考以下文章

具有可变 contentSize 的 UIScrollView

在 addSubview 中调用具有动态 ScrollView ContentSize Autolayout 的 CustomView

UICollectionView 具有自调整大小的单元格未正确计算 contentSize

iOS:在 Interface Builder 中使用动态 contentSize 创建 UIScrollView

UIScrollView的contentSize、contentOffset和contentInset的理解

iOS7 UITextView contentsize.height替代方案