【问题标题】:Use a scrollview to zoom an image in Xcode 11 avoiding the "Ambiguous Content Size" AutoLayout error使用滚动视图在 Xcode 11 中缩放图像,避免“不明确的内容大小”自动布局错误
【发布时间】:2019-12-28 11:00:25
【问题描述】:

我的问题是关于滚动视图的自动布局问题。

我只是想在故事板上添加一个滚动视图,它对超级视图有自己的约束,但里面没有任何子视图,一旦应用程序运行,就在其中添加一个 imageView。但是由于情节提要上的“内容大小不明确”错误,即使我们取消选中“检查歧义”选项,自动布局也无法在滚动视图上工作。如果我应用将 contentView 添加到 scrollView 的解决方案,并使用所有这些额外的约束固定它,我仍然可以在 scrollView 内捏和缩放图像,但失去了平移的能力,无论 viewForZoom 是 contentView 还是添加了图像视图。如果 ContentView 是 imageView 我有同样的问题。可以缩放,不能平移。

另外,任何人都可以向我解释为什么当 ScrollView 没有内容时,在这个 Xcode 版本中会触发这种荒谬的“模棱两可的责骂内容错误”?为什么我们需要将一个带有两个冗余约束的 contentView 固定到 scrollView 的 superview 上?

【问题讨论】:

    标签: swift image autolayout scrollview zooming


    【解决方案1】:

    Interface Builder / Storyboard 无法知道您将在运行时添加子视图和约束。

    因此,它告诉您当前布局的内容大小不明确。

    如果滚动视图没有内容,不显示消息会更好吗?也许...但即使它显示设计错误,也不意味着您必须修复它。

    如果你真的想摆脱警告/错误,有几个选择:

    1) 在 Storyboard 中添加您的 imageView(带有适当的约束),并在运行时设置 .image 属性。

    2) 在 Storyboard 中添加一个子视图(具有适当的约束),并在添加 imageView 之前在 viewdidLoad() 中删除该视图。


    编辑

    这是一个简单的例子:https://github.com/DonMag/ZoomTest

    在 IB / Storyboard 中,我添加了 UIScrollView 并仅设置宽度、高度、centerX 和 centerY 约束,因此 Storyboard 告诉我Ambiguous Content Size

    viewDidLoad 中,我添加了UIImageView,设置适当的约束,设置滚动视图委托和最小/最大缩放比例。


    编辑 2

    使用256 x 256 图像的结果,并约束滚动视图以填充父视图(滚动视图背景为青色)...

    加载时 - zoomScale == 1:

    加载时 - zoomScale == 1 - 旋转:

    zoomScale = 大约 1.5(刚好足够宽):

    zoomScale = 大约 1.5 - 旋转后:

    zoomScale == 5 - 平移到左上角:

    zoomScale == 5 - 平移到左上角 - 旋转后:

    zoomScale == 5 - 平移到右下方:

    zoomScale == 5 - 平移到右下方 - 旋转后:

    【讨论】:

    • 你真的做到了吗?因为一旦你得到那个“错误”,AutoLayout 就不再处理那个scrollView,并且旋转功能失调。如果你实现了,你会好心分享这个项目吗?
    • @Hikarus - 检查我编辑的答案。我在 GitHub 上添加了一个示例项目。
    • 我已经修改了约束,使滚动视图与超级视图一样大(这是我的目标)但自动布局在旋转后失败,并且图像视图不再占用整个滚动视图旋转到水平后的内容。我只需要一个简单的示例,其中 Autolayout 在具有可缩放图像的全屏尺寸滚动视图上工作。
    • @Hikarus - 首先...您是说当您在 Storyboard 的滚动视图中添加 UIImageView 时 - 设置适当的约束以消除 Ambiguous 警告- 一切都按照你想要的方式进行?如果是这样,您使用什么约束?如果不是,那么也许您需要更好地解释没有按您期望的方式工作的原因是什么?我添加了屏幕截图以显示我的结果。
    • 你愿意分享这个例子吗,全屏滚动视图?我对通过代码使用自动布局不是很熟悉。
    【解决方案2】:

    所以,简而言之,解决方案似乎是在情节提要上添加 ScrollView 约束,忽略无意义的错误,然后在 viewController 上使用 UIImage 初始化 UIImageView 属性,并在 viewDidLoad() 上将 imageView 添加到scrollView,并使用 NSLayoutConstraint 的 activate() 方法设置 imageView 相对于 scrollView 的 contentLayoutGuide 的约束,将其固定在顶部、底部、左侧和右侧。

    实现的例子在这里: https://github.com/HikarusGF/ScrollView-ImageView-Zoom

    PS:我喜欢在 storyboard 上设置 scrollView 委托,所以你不会在代码中看到它。

    【讨论】:

    • 我在发布故事板解决方案之前发布了此解决方案,但由于某种原因,它最后显示。
    【解决方案3】:

    我终于想出了如何在情节提要上实现这一点,并让它变得更简单。直到几个 XCode 版本以前的方式:

    我们仍然可以在 storyboard 上添加一个 ScrollView,它们具有典型的约束,使其垂直和水平居中到它的 superView,并且宽度和高度相同,因此可以全屏看到 scrollView。

    到目前为止一切顺利,现在是棘手的部分:在情节提要上添加一个 ImageView,作为 Scroll View 的子视图。在这里,我们需要的约束是四个将 IMAGEVIEW 固定在 SCROLLVIEW 内,但从不限制大小。如果我们在 ImageView 上使用与 ScrollView 相同的中心/等大小约束,那么当涉及到平移,尤其是旋转屏幕时,ScrollView 将表现出完全不稳定和荒谬的行为。

    我们仍然会收到荒谬的故事板警告/错误,告诉我们我们的滚动视图具有“模糊的内容大小”,并且“更新帧”按钮也会有一个不稳定的行为,但我们可以完全忽略所有这些,并手动调整ScrollView 和其中的 ImageView 的大小,使其看起来与运行时完全相同。根本不需要额外的冗余约束,尤其是触及 ImageView 大小的任何约束。

    然后,我们需要添加到 viewDidLoad() 中的唯一代码是委托方法 viewForZooming(),以通知 ScrollView 使用哪个子视图作为“可缩放”,在这种情况下,我们的 @IBOutlet UIImageView。必要的最小和最大缩放比例参数也可以在故事板上设置。

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

    最后,如果我们希望摆脱滚动视图中的初始边距,因为我们只是显示全屏图像,我们需要设置这个我在 IB 上找不到的选项:

    scrollView.contentInsetAdjustmentBehavior = .never
    

    这是 GitHub 上的植入项目:https://github.com/HikarusGF/ScrollView-ImageView-Zoom

    代码和情节提要解决方案都在项目中实现。要从一个切换到另一个,只需更改情节提要上的初始 viewController。我已将故事板解决方案设置为默认值。

    【讨论】:

      猜你喜欢
      • 2018-02-17
      • 2013-12-25
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多