3

I'm struggling with problem in rotating image in a UIScrollView, my view hierarchy is described by:
I've an UIScrollView with an UIView as subview. The UIView has an UIImageView as subview.

I would be able to rotate the imageView inside it and then recalculate the contentSize of the scrollView in order to be able to pan over all of it.

I'm using this code:

//
//  TestView.swift
//

import UIKit

class TestView: UIView {

    // MARK: - properties
    private var imageView: UIImageView?
    private var zoomingView: UIView?
    private var scrollView: UIScrollView?
    private let kDecayRotation = "kDecayRotation"
    var image: UIImage? {
        didSet {
            setupImageView(image)
        }
    }


    // MARK: - init
    convenience init(frame: CGRect, image: UIImage) {
        self.init(frame: frame)
        setupImageView(image)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = UIColor.blueColor()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    // MARK: - methods
    private func setupImageView(image: UIImage?) {
        guard let image = image else { return }

        imageView = UIImageView(image: image)

        zoomingView = UIView(frame: imageView!.frame)
        zoomingView?.addSubview(imageView!)

        scrollView = UIScrollView(frame: frame)
        scrollView?.backgroundColor = UIColor.redColor()
        scrollView?.contentSize = zoomingView!.frame.size
        scrollView?.addSubview(zoomingView!)
        addSubview(scrollView!)

        let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotation(_:)))
        rotationGesture.delegate = self
        scrollView?.addGestureRecognizer(rotationGesture)
    }

    @objc private func handleRotation(gestureRecognizer: UIRotationGestureRecognizer) {
        adjustAnchorPointForGestureRecognizer(gestureRecognizer)

        guard let targetView = zoomingView else { return }

        if gestureRecognizer.state == .Began {  }
        else if gestureRecognizer.state == .Changed {

            targetView.transform = CGAffineTransformRotate(targetView.transform, gestureRecognizer.rotation)
            gestureRecognizer.rotation = 0

            scrollView?.contentSize = targetView.frame.size
            var targetFrame = targetView.frame
            let targetBounds = targetView.bounds
            targetFrame.origin.x = 0
            targetFrame.origin.y = 0
            targetView.frame = targetFrame
            targetView.bounds = targetBounds

            scrollView?.setNeedsDisplay()

        } else if gestureRecognizer.state == .Cancelled || gestureRecognizer.state == .Ended {  }
    }

    // MARK: - gesture helper
    private func adjustAnchorPointForGestureRecognizer(gestureRecognizer: UIGestureRecognizer) {
        guard let zoomingView = zoomingView else { return }
        if gestureRecognizer.state == .Began {
            let locationInView = gestureRecognizer.locationInView(zoomingView)
            let locationInSuperview = gestureRecognizer.locationInView(zoomingView.superview)

            zoomingView.layer.anchorPoint = CGPointMake(locationInView.x / zoomingView.bounds.size.width, locationInView.y / zoomingView.bounds.size.height)
            zoomingView.center = locationInSuperview
        }
    }
}

extension TestView: UIGestureRecognizerDelegate {
    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

The problem are:

  • The View doesn't rotate around the location of the finger (although I implemented the method to calculate the new anchorPoint)
  • The contentSize if recalculated correctly (only if I comment adjustAnchorPointForGestureRecognizer(gestureRecognizer) in handleRotation(_:)), but the image move across the scrollview in an horrible way. How can I get the effect of the image remain fixed (and rotate) and the contentSize being recalculated under of that in a 'silence' manner?

Edit 1

Here's the test image: test image

The code to use the TestView is:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        setupView()
    }

    private func setupView() {
        let sampleImage = UIImage(named: "testImage")
        let testView = TestView(frame: view.frame, image: sampleImage!)
        view.addSubview(testView)
    }
}
Taglia_90
  • 117
  • 1
  • 9

0 Answers0