【问题标题】:Rotating UIImageView in a UIScrollView在 UIScrollView 中旋转 UIImageView
【发布时间】:2016-03-19 09:58:39
【问题描述】:

我在UIScrollView 中有一个UIImageView。最终目标是在UIScrollView 的范围内旋转、平移和缩放图像。平移和缩放效果很好。旋转最初是有效的,但是在旋转完成后,然后是捏缩放,图像旋转被重置为 0,并且图像被移出UIScrollView

对我可能遗漏的任何建议

@IBOutlet weak var innerScrollView: UIScrollView!
        private weak var innerImageView: UIImageView?
        var beforeImage: UIImage?


        // MARK: -
        // MARK: UIViewController       

        override func viewDidLoad() {
            super.viewDidLoad()

            innerScrollView.delegate = self
            configureScrollView(innerScrollView, image: beforeImage)

            let recognizer = UIRotationGestureRecognizer(target: self, action: "rotateRecognizer:")
            if let imageView = innerImageView {
                imageView.addGestureRecognizer(recognizer)
            }
        }

        override func viewWillAppear(animated: Bool) {
            super.viewWillAppear(animated)

            resetScrollView(innerScrollView)
        }



        // MARK: -
        // MARK: Private Helpers

        private func resetScrollView(scrollView: UIScrollView) {

            let scaleWidth = scrollView.frame.size.width / scrollView.contentSize.width
            let scaleHeight = scrollView.frame.size.height / scrollView.contentSize.height

            let minScale = min(scaleHeight, scaleWidth)

            scrollView.minimumZoomScale = minScale
            scrollView.maximumZoomScale = 1.0
            scrollView.zoomScale = minScale
            centerScrollViewContents()

        }

        private func configureScrollView(scrollView: UIScrollView, image: UIImage?) {

            guard let img = image else {
                return
            }
            let imageView = UIImageView(image: image)
            imageView.userInteractionEnabled = true
            imageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: img.size)
            scrollView.addSubview(imageView)
            scrollView.contentSize = img.size

            innerImageView = imageView
        }

        private func centerScrollViewContents() {
            let boundsSize = innerScrollView.bounds.size
            var contentsFrame = innerImageView!.frame

            if contentsFrame.size.width < boundsSize.width {
                contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0
            } else {
                contentsFrame.origin.x = 0.0
            }

            if contentsFrame.size.height < boundsSize.height {
                contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0
            } else {
                contentsFrame.origin.y = 0.0
            }

            innerImageView!.frame = contentsFrame
        }

        func rotateRecognizer(recognizer: UIRotationGestureRecognizer) {

            print("The content Offset is \(innerScrollView.contentOffset)")
            guard let recView = recognizer.view else {
                return
            }

            recView.transform = CGAffineTransformRotate(recView.transform, recognizer.rotation);
            recognizer.rotation = 0;
        }



        // MARK: -
        // MARK: UIGestureRecognizer Delegate Protocol

        func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {

            if let imageView = scrollView.subviews.first as? UIImageView {
                return imageView
            }
            return nil
        }

【问题讨论】:

  • 所以发布您的平移手势识别器代码。这很可能是问题所在。我敢打赌,您是从身份转换开始,而不是从图像视图的当前转换开始。 (您的旋转方法正在做正确的事情并从当前变换开始。)
  • @DuncanC 好吧,我没有平移或捏合手势识别器。我正在使用 UIScrollView。你认为这是问题所在吗?
  • 你不应该旋转innerImageView,而不是“recView”吗?
  • 如果您正在操作滚动视图的转换,那么是的,这很可能是问题所在。您可能应该将旋转应用于图像视图,而不是滚动视图。 (虽然让旋转中心正常工作可能是一个挑战。)

标签: ios uiscrollview uiimageview uigesturerecognizer


【解决方案1】:

我成功了。还有另一个建议的解决方案here,但我的不同。

使用滚动视图可以轻松进行缩放和平移,但是在添加旋转时,它会立即重置,您可以像您说的那样制作另一个平移(这也发生在我身上)。我所做的是完全放弃 scrollView 的手势,而不是依赖它的代表。我为平移、缩放和旋转添加了自己的手势识别器。然后,您可以随意组合它们:让它们中的两个同时感知变化,甚至三个。在我的解决方案中,我希望单独感测平移,同时感测缩放和旋转。您在方法中执行此操作:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool 

请参阅下面的其余代码。当然,在我的示例中,我有一个 UIView,而不是图像视图,但从变换的角度来看,这并不重要。

private struct Constants {
    private init() {}

    static let minZoom = CGFloat(0.3)
    static let maxZoom = CGFloat(6)
}

private var activeView: UIView
private var savedTransform: CGAffineTransform

// Represents rotation performed since the last transform save
private var editedRotation = TransformConstants.defaultRotation
// Represents scaling performed since the last transform save
private var editedScale = TransformConstants.defaultScale

override func didPan(recognizer: UIPanGestureRecognizer) {
    let translation = recognizer.translation(in: activeView)
    activeView.transform = savedTransform.translatedBy(x: translation.x, y: translation.y)

    if shouldSaveGestures(recognizer: recognizer) {
      saveChanges(operation: .pan)
      return
    }
}

override func didPinch(recognizer: UIPinchGestureRecognizer) {
    if shouldSaveGestures(recognizer: recognizer) {
      saveChanges(operation: .zoom)
      return
    }

    var scale = recognizer.scale

    if Constants.minZoom > scale * savedTransform.getScale().x {
      scale = Constants.minZoom / savedTransform.getScale().x
    } else if scale * savedTransform.getScale().x > Constants.maxZoom {
      scale = Constants.maxZoom / savedTransform.getScale().x
    }

    activeView.transform = savedTransform.scaledBy(x: scale, y: scale).rotated(by: editedRotation)
    editedScale = CGPoint(x: scale, y: scale)
}

override func didRotate(recognizer: UIRotationGestureRecognizer) {
    if shouldSaveGestures(recognizer: recognizer) {
      saveChanges(operation: .rotate)
      return
    }

    activeView.transform = savedTransform.scaledBy(x: editedScale.x, y: editedScale.y).rotated(by: recognizer.rotation)
    editedRotation = recognizer.rotation
}

private func shouldSaveGestures(recognizer: UIGestureRecognizer) -> Bool {
    return recognizer.state == .ended || recognizer.state == .failed
}

private func saveChanges(operation: OperationType) {
    savedTransform = activeView.transform
    editedScale = TransformConstants.defaultScale
    editedRotation = TransformConstants.defaultRotation
}

【讨论】:

    猜你喜欢
    • 2018-10-01
    • 2012-08-06
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多