UIScrollView使用自动布局缩放UIImageView [英] UIScrollView with scaled UIImageView using autolayout

查看:101
本文介绍了UIScrollView使用自动布局缩放UIImageView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一个 UIScrollView 只有一个子视图。子视图是 UIImageView ,具有以下大小限制:

Consider a UIScrollView with a single subview. The subview is an UIImageView with the following size constraints:


  • 其高度必须为等于 UIScrollView 的高度。

  • 其宽度必须是与<$的高度成比例缩放的图像宽度c $ c> UIImageView 。

  • Its height must be equal to the height of the UIScrollView.
  • Its width must be the width of the image scaled proportionally to the height of the UIImageView.

预计的宽度UIImageView 将大于UIScrollView的宽度,因此需要滚动。

It is expected that the width of the UIImageView will be bigger than the width of the UIScrollView, hence the need for scrolling.

图像可能在 viewDidLoad (如果已缓存)或异步。

The image might be set during viewDidLoad (if cached) or asynchronously.

如何使用autolayout实现上述功能,尽可能多地使用Interface builder?

How do you implement the above using autolayout, making as much use as possible of Interface builder?

基于此回答我这样配置了我的笔尖:

Based on this answer I configured my nib like this:


  • UIScrollView 固定在其超级视图的边缘。

  • UIImageView 固定在 UIScrollView 的边缘。

  • UIImageView 具有占位符内在大小(以避免可滚动内容大小歧义错误)

  • The UIScrollView is pinned to the edges of its superview.
  • The UIImageView is pinned to the edges of the UIScrollView.
  • The UIImageView has a placeholder intrinsic size (to avoid the Scrollable Content Size Ambiguity error)

正如预期的那样,结果是 UIImageView 的大小调整为<​​code> UIImage 的大小,以及 UIScrollView 水平和垂直滚动(因为图像大于 UIScrollView )。

As expected, the result is that the UIImageView is sized to the size of the UIImage, and the UIScrollView scrolls horizontally and vertically (as the image is bigger than the UIScrollView).

然后我尝试了各种不起作用的东西:

Then I tried various things which didn't work:


  • 手动加载图像后设置<$ c $的框架c> UIImageView 。

  • 为UIImageView的宽度添加约束,并在加载图像后修改其值。这使图像更大(?!)。

  • 在加载图像后设置 zoomScale 。没有明显效果。

  • After loading the image manually set the frame of UIImageView.
  • Add a constraint for the width of the UIImageView and modify its value after the image has been loaded. This makes the image even bigger (?!).
  • Set zoomScale after the image is loaded. Has no visible effect.

以下代码完全正确我想要的,虽然没有autolayout或界面构建器。

The following code does exactly as I want, albeit without autolayout or interface builder.

- (void)viewDidLoad
{
    {
        UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
        scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [self.view addSubview:scrollView];
        self.scrollView = scrollView;
    }

    {
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.scrollView.frame.size.width, self.scrollView.frame.size.height)];
        imageView.contentMode = UIViewContentModeScaleAspectFit;
        imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [self.scrollView addSubview:imageView];
        self.scrollView.contentSize = imageView.frame.size;
        self.imageView = imageView;
    }
}

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    [self layoutStripImageView];
}

- (void)layoutStripImageView
{ // Also called when the image finishes loading
    UIImage *image = self.imageView.image;
    if (! image) return;

    const CGSize imageSize = image.size;
    const CGFloat vh = self.scrollView.frame.size.height;
    const CGFloat scale = vh / imageSize.height;
    const CGFloat vw = imageSize.width * scale;

    CGSize imageViewSize = CGSizeMake(vw, vh);
    self.imageView.frame = CGRectMake(0, 0, imageViewSize.width, imageViewSize.height);
    self.scrollView.contentSize = imageViewSize;
}

我正在努力转向自动布局,但这并不容易。

I'm trying really hard to move to autolayout but it's not being easy.

推荐答案

在autolayout制度下,理想情况下UIScrollView contentSize 完全由约束决定,而不是设置明确地在代码中。

Under the autolayout regime, ideally the UIScrollView contentSize is solely determined by the constraints and not set explicitly in code.

所以在你的情况下:


  • 创建约束以将子视图固定到 UIScrollView 约束必须确保子视图和滚动视图之间的边距为0.我看到你了我已经尝试过了。

  • Create constraints to pin the subview to the UIScrollView. The constraints have to ensure the margin between the subview and the scroll view are 0. I see that you have already tried this.

为子视图创建高度和宽度约束。否则,<$>的内在大小c $ c> UIImageView 确定其高度和宽度。在设计时,此大小只是一个占位符,以保持Interface Builder的快乐。在运行时,它将被设置为实际图像大小,但这不是您想要的。

Create a height and a width constraint for your subview. Otherwise, the intrinsic size of the UIImageView determines its height and width. At design time, this size is only a placeholder to keep Interface Builder happy. At run time, it will be set to the actual image size, but this is not what you want.

期间viewDidLayoutSubviews ,将约束更新为实际内容大小。您可以通过更改高度的常量属性直接执行此操作。宽度约束,或调用 setNeedsUpdateConstraints 和覆盖 updateConstraints 来这样做。

During viewDidLayoutSubviews, update the constraints to be actual content size. You can either do this directly by changing the constant property of the height and width constraint, or calling setNeedsUpdateConstraints and overriding updateConstraints to do the same.

这可确保系统只能从约束中派生 contentSize

This ensures that the system can derive contentSize solely from constraints.

我已经完成了上述操作,它在iOS 6和7上可靠地运行,带有 UIScrollView 和自定义子视图,所以它应该适用于 UIImageView 也是。特别是如果你没有将子视图固定到滚动视图,iOS 6中的缩放将是抖动。

I've done the above and it works reliably on iOS 6 and 7 with a UIScrollView and a custom subview, so it should work for UIImageView too. In particular if you don't pin the subview to the scroll view, zooming will be jittery in iOS 6.

您也可以尝试创建直接引用的高度和宽度约束滚动视图的高度和宽度的倍数,但我还没有尝试过这种方法。

You may also try creating height and width constraints that directly reference a multiple of the height and width of the scroll view, but I haven't tried this other approach.

这篇关于UIScrollView使用自动布局缩放UIImageView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆