如何限制将捏缩放图像移动到图像边框?

Posted

技术标签:

【中文标题】如何限制将捏缩放图像移动到图像边框?【英文标题】:How to restrict shifting of a pinch zoomed image to the image borders? 【发布时间】:2015-11-17 14:35:10 【问题描述】:

我在情节提要中设置了一个scrollView,其中包含一个imageView,使用自动布局,如图所示here。 此外,我为此imageView 启用了捏缩放,如docs 中所述。

imageViewscollView 的两侧有 4 个 0 约束,并且它与主视图具有相等的宽度和高度,主视图具有 scrollView 作为子视图。

imageView 具有aspectFit 缩放模式,因此在未缩放状态下,图像将完全从左到右或从上到下(或两者)延伸。 在下面的示例中,它从上到下延伸,使一些背景左右可见:

我可以捏缩放图像,使其比屏幕大:

我可以向上或向下移动缩放的图像,但在顶部或底部的背景变得可见之前移动停止。这是我想要的。

但是,我可以将缩放后的图像向左或向右移动,以便可以看到背景:

我怎样才能避免将图像移动这么远(这里,向右)。与顶部或底部一样,它应该在边界处停止移动,这样就看不到背景了。

【问题讨论】:

【参考方案1】:

不是理想的解决方案,但我希望它会有所帮助:

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale 
    [self adjustScrollViewInsets];


- (void)adjustScrollViewInsets 
    CGFloat imageWidth = self.imageView.image.size.width;
    CGFloat imageHeight = self.imageView.image.size.height;
    CGFloat aspect = imageWidth / imageHeight;
    CGSize imageViewSize = self.imageView.frame.size;
    if (imageViewSize.width / aspect <= imageViewSize.height) 
        [self adjustVerticalInsetsWithImageHeight:(imageViewSize.width / aspect)];
     else 
        [self adjustHorizontalInsetsWithImageWidth:(imageViewSize.height * aspect)];
    


- (void)adjustHorizontalInsetsWithImageWidth:(CGFloat)width 
    CGFloat horizontalInset = (self.scrollView.contentSize.width - width) / 2;
    if (width < self.scrollView.frame.size.width) 
        horizontalInset = horizontalInset - (self.scrollView.frame.size.width - width) / 2;
    
    [self.scrollView setContentInset:UIEdgeInsetsMake(0, -horizontalInset, 0, -horizontalInset)];


- (void)adjustVerticalInsetsWithImageHeight:(CGFloat)height 
    CGFloat verticalInset = (self.scrollView.contentSize.height - height) / 2;
    if (height < self.scrollView.frame.size.height) 
        verticalInset = verticalInset - (self.scrollView.frame.size.height - height) / 2;
    
    [self.scrollView setContentInset:UIEdgeInsetsMake(-verticalInset, 0, -verticalInset, 0)];

如果您遇到问题,请查看this repo。

【讨论】:

嗨弗拉基米尔,我测试了你的代码。它正确计算插入。奇怪的是,使用正确的参数应用 setContentInset: 后,1)显示没有改变,即图像的大小没有改变并且周围的背景(如果有的话)仍然可见,2)它不再可以在应用插入的方向滚动(如果原始图像是横向的,即高度 您好弗拉基米尔,我发现了问题:您的代码没有考虑缩放比例因子。如果,例如垂直插入被设置,它们被设置为可见区域,并且即使缩放的图像允许垂直滚动也不可能。为了纠正这个问题,必须将 adjustVerticalInsetsWithImageHeight: 的参数与 scrollView.zoomScale 相乘(水平类似)。如果您同意,请编辑您的答案,我会接受。 我无法重现您的滚动问题(使用模拟器测试,9.1)。您是从我的存储库还是您自己的实现中测试了一个项目?无需考虑缩放比例因子,因为内容的大小和图像视图的大小已经针对当前比例进行了计算。您能否提供有关滚动问题的更多信息?视频或示例项目会很有帮助。 我用自己的实现进行了尝试。我会尽快提供更多信息。 我在代码中发现了问题:在您的代码中,scrollView 将 imageView 作为子视图。当 scrollView 被缩放时,imageView 也被缩放,并且不需要像您的代码中那样额外的缩放因子。在我的代码中,scrollView 有一个intermediateView 作为子视图,intermediateView 有一个imageView 作为子视图。当 scrollView 被缩放时,intermediateView 也被缩放,而 imageView 没有被缩放。因此,adjustVerticalInsetsWithImageHeight:(imageViewSize.width / aspect)*zoomscale 和 adjustVerticalInsetsWithImageHeight:(intermediateViewSize.width / aspect) 都有效。再次感谢您的回答!【参考方案2】:

我遇到了同样的问题,并在 Swift 4.0 中实现,如下所示,它对我有用。

Swift 4.0:

    func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) 
    adjustScrollViewInsets()


func adjustScrollViewInsets() 
    let imageWidth = self.imageView.image?.size.width
    let imageHeight = self.imageView.image?.size.height
    let aspect = imageWidth! / imageHeight!
    let imageViewSize = self.imageView.frame.size
    if imageViewSize.width / aspect <= imageViewSize.height 
        adjustVerticalInsetsWithImageHeight(height: imageViewSize.width / 2)
     else 
        adjustHorizontalInsetsWithImageWidth(width: imageViewSize.height / 2)
    


func adjustHorizontalInsetsWithImageWidth(width: CGFloat) 
    var horizontalInset = (self.scrollView.contentSize.width - width) / 2
    if width < self.scrollView.contentSize.width 
       horizontalInset = horizontalInset  - (self.scrollView.frame.size.width - width) / 2
    
    self.scrollView.contentInset = UIEdgeInsetsMake(0, -horizontalInset, 0, -horizontalInset)


func adjustVerticalInsetsWithImageHeight(height: CGFloat) 
    var verticalInset = (self.scrollView.contentSize.height - height) / 2
    if height < self.scrollView.frame.size.height 
        verticalInset = verticalInset - (self.scrollView.frame.size.height - height) / 2
    
    self.scrollView.contentInset = UIEdgeInsetsMake(-verticalInset, 0, -verticalInset, 0)

【讨论】:

虽然此答案可能是正确且有用的,但如果您 include some explanation along with it 解释它如何帮助解决问题,则最好。如果有更改(可能不相关)导致它停止工作并且用户需要了解它曾经是如何工作的,这在未来变得特别有用。

以上是关于如何限制将捏缩放图像移动到图像边框?的主要内容,如果未能解决你的问题,请参考以下文章

如何缩放视图并将自定义边框保持在原始大小\缩放?

如何移动和缩放图像[关闭]

无论浏览器缩放级别如何,如何使图像连续排列?

在不移动叠加视图的情况下裁剪和缩放图像,而是在 ImageView 中移动图像

图像未放大时如何停止移动图像?

当我的 UIScrollView 缩放图像时,如何使框架正确居中?