UIScrollView缩放和contentInset

26

与iOS照片应用程序相似,用户通过手指捏合来放大和缩小图像:

UIView > UIScrollView > UIImageView > UIImage

最初,我在缩小比例低于1时遇到了图像偏离中心的问题。我通过以下方式解决了这个问题:

func scrollViewDidZoom(scrollView: UIScrollView) {
        let offsetX = max((scrollView.bounds.width - scrollView.contentSize.width) * 0.5, 0)
        let offsetY = max((scrollView.bounds.height - scrollView.contentSize.height) * 0.5, 0)
        scrollView.contentInset = UIEdgeInsetsMake(offsetY, offsetX, 0, 0)
}

缩小时效果很好。

UIImage的content mode是aspectFit。

问题

当我放大,即zoomScale大于1时,滚动视图的插图需要贴合包含在滚动视图中的UIImage周围。这会消除原来围绕UIImage的空白区域。例如相册应用程序通过捏或双击放大。

已尝试

    func scrollViewDidZoom(scrollView: UIScrollView) {
    if scrollView.zoomScale > 1 {
        let imageScale = (self.imageView.bounds.width/self.imageView.image!.size.width)
        let imageWidth = self.imageView.image!.size.width * imageScale
        let imageHeight = self.imageView.image!.size.height * imageScale
        scrollView.contentInset = UIEdgeInsetsMake(((scrollView.frame.height - imageHeight) * 0.5), (scrollView.frame.width - imageWidth) * 0.5 , 0, 0)
        print (scrollView.contentInset.top)
    }
    else {

        let offsetX = max((scrollView.bounds.width - scrollView.contentSize.width) * 0.5, 0)
        let offsetY = max((scrollView.bounds.height - scrollView.contentSize.height) * 0.5, 0)
        scrollView.contentInset = UIEdgeInsetsMake(offsetY, offsetX, 0, 0)
    }
}

以上增加似乎仍然会改变插入量。

更新(添加了图像)

第一张图片显示默认布局。其余的是放大后的效果.....

输入图像描述


2
所以,你想在出现死区之前停止吗? - Vasily Bodnarchuk
更新了问题并附上了图形说明。 - Gizmodo
第二张和第三张图片的唯一区别在于第三张图片中的滚动视图仅在x轴上缩放。但是这对图像有什么影响呢?第二张和第三张图片中图像的缩放是相同的。您是否只是想要像照片应用程序一样的效果? - Gurdeep
@Gurdeep:第三张图片已经修剪了 Scroll View Insets。 - Gizmodo
3个回答

45

你的方法看起来是正确的。你需要按照以下方式更新你的代码。

    func scrollViewDidZoom(scrollView: UIScrollView) {
    
    if scrollView.zoomScale > 1 {
        
        if let image = imageView.image {
            
            let ratioW = imageView.frame.width / image.size.width
            let ratioH = imageView.frame.height / image.size.height
            
            let ratio = ratioW < ratioH ? ratioW:ratioH
            
            let newWidth = image.size.width*ratio
            let newHeight = image.size.height*ratio
            
            let left = 0.5 * (newWidth * scrollView.zoomScale > imageView.frame.width ? (newWidth - imageView.frame.width) : (scrollView.frame.width - scrollView.contentSize.width))
            let top = 0.5 * (newHeight * scrollView.zoomScale > imageView.frame.height ? (newHeight - imageView.frame.height) : (scrollView.frame.height - scrollView.contentSize.height))
            
            scrollView.contentInset = UIEdgeInsetsMake(top, left, top, left)
        }
    } else {
        scrollView.contentInset = UIEdgeInsetsZero
    }
}

Swift 5

    func scrollViewDidZoom(scrollView: UIScrollView) {
    
    if scrollView.zoomScale > 1 {

        if let image = imageView.image {

            let ratioW = imageView.frame.width / image.size.width
            let ratioH = imageView.frame.height / image.size.height

            let ratio = ratioW < ratioH ? ratioW:ratioH

            let newWidth = image.size.width*ratio
            let newHeight = image.size.height*ratio

            let left = 0.5 * (newWidth * scrollView.zoomScale > imageView.frame.width ? (newWidth - imageView.frame.width) : (scrollView.frame.width - scrollView.contentSize.width))
            let top = 0.5 * (newHeight * scrollView.zoomScale > imageView.frame.height ? (newHeight - imageView.frame.height) : (scrollView.frame.height - scrollView.contentSize.height))

            scrollView.contentInset = UIEdgeInsets(top: top, left: left, bottom: top, right: left)
        }
    } else {
        scrollView.contentInset = .zero
    }
}

非常好用,非常感谢! - Vlad Pulichev

7

Swift 5

func scrollViewDidZoom(_ scrollView: UIScrollView) {
    if scrollView.zoomScale > 1 {
        if let image = imageView.image {

            let ratioW = imageView.frame.width / image.size.width
            let ratioH = imageView.frame.height / image.size.height

            let ratio = ratioW < ratioH ? ratioW : ratioH

            let newWidth = image.size.width * ratio
            let newHeight = image.size.height * ratio

            let left = 0.5 * (newWidth * scrollView.zoomScale > imageView.frame.width ? (newWidth - imageView.frame.width) : (scrollView.frame.width - scrollView.contentSize.width))
            let top = 0.5 * (newHeight * scrollView.zoomScale > imageView.frame.height ? (newHeight - imageView.frame.height) : (scrollView.frame.height - scrollView.contentSize.height))

            scrollView.contentInset = UIEdgeInsets(top: top, left: left, bottom: top, right: left)
        }
    } else {
        scrollView.contentInset = UIEdgeInsets.zero
    }
}

2

针对Swift 4

func scrollViewDidZoom(_ scrollView: UIScrollView) {

        if scrollView.zoomScale > 1 {

            if let image = self.imageViewZoom.image {

                let ratioW = self.imageViewZoom.frame.width / image.size.width
                let ratioH = self.imageViewZoom.frame.height / image.size.height

                let ratio = ratioW < ratioH ? ratioW:ratioH

                let newWidth = image.size.width*ratio
                let newHeight = image.size.height*ratio

                let left = 0.5 * (newWidth * scrollView.zoomScale > self.imageViewZoom.frame.width ? (newWidth - self.imageViewZoom.frame.width) : (scrollView.frame.width - scrollView.contentSize.width))
                let top = 0.5 * (newHeight * scrollView.zoomScale > self.imageViewZoom.frame.height ? (newHeight - self.imageViewZoom.frame.height) : (scrollView.frame.height - scrollView.contentSize.height))

                scrollView.contentInset = UIEdgeInsetsMake(top, left, top, left)
            }
        } else {
            scrollView.contentInset = UIEdgeInsets.zero
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接