5

I would like to implement a resizable and draggable UIView like the following picture shows:

enter image description here

This is the class I have implemented up to now using simple gestures recognizers:

class PincherView: UIView {

var pinchRec:UIPinchGestureRecognizer!
var rotateRec:UIRotationGestureRecognizer!
var panRec:UIPanGestureRecognizer!
var containerView:UIView!

init(size: CGRect, container:UIView) {
    super.init(frame: size)

    self.containerView = container

    self.pinchRec = UIPinchGestureRecognizer(target: self, action: "handlePinch:")
    self.addGestureRecognizer(self.pinchRec)

    self.rotateRec = UIRotationGestureRecognizer(target: self, action: "handleRotate:")
    self.addGestureRecognizer(self.rotateRec)

    self.panRec = UIPanGestureRecognizer(target: self, action: "handlePan:")
    self.addGestureRecognizer(self.panRec)

    self.backgroundColor = UIColor(red: 0.0, green: 0.6, blue: 1.0, alpha: 0.4)
    self.userInteractionEnabled = true
    self.multipleTouchEnabled = true
    self.hidden = false
}

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

func handlePinch(recognizer : UIPinchGestureRecognizer) {
    if let view = recognizer.view {
        view.transform = CGAffineTransformScale(view.transform, 1.0, recognizer.scale)
        //view.transform = CGAffineTransformScale(view.transform, recognizer.scale, recognizer.scale)
        recognizer.scale = 1
    }
}

func handleRotate(recognizer : UIRotationGestureRecognizer) {
    if let view = recognizer.view {
        view.transform = CGAffineTransformRotate(view.transform, recognizer.rotation)
        recognizer.rotation = 0
    }
}

func handlePan(recognizer:UIPanGestureRecognizer) {
    let translation = recognizer.translationInView(containerView)
    if let view = recognizer.view {
        view.center = CGPoint(x:view.center.x + translation.x,
            y:view.center.y + translation.y)
    }
    recognizer.setTranslation(CGPointZero, inView: containerView)
}

}

As you can imagine, with a simple UIPinchGestureRecognizer the uiview is scaled equally both in x and y directions but I want the users to have the chance to be as precise al possibile so that they can either scale even in one single direction or alter the form of the uiview, not necessarily to be a rectangle. Moreover, it's more important for me that user is as precise as possible in setting the heigth of the uiviewThat's why I need to have those 4 buttons at the corners. I just would like you to give me some hints from where to start from and how. Thank you

UPDATE This is what I have done up to know

enter image description here

In this way I have the following hierarchy:

-UIImageView embed in -UIView embed in - UIScrollView embed in - UIViewController

I had to add a further UIView to use as container, so that all sub uiviews it contains will be zoomed in/out together with the picture in order to have more precision in order to better overlap the azure uiview to photographed objects. Concerning the pin, the little white circle, this is the class I have tried to implement up to know:

class PinImageView: UIImageView {

var lastLocation:CGPoint!
var container:UIView!
var viewToScale:UIView!
var id:String!

init(imageIcon: UIImage?, location:CGPoint, container:UIView, viewToScale:UIView, id:String) {

    super.init(image: imageIcon)
    self.lastLocation = location

    self.frame = CGRect(x: location.x, y: location.y, width: 10.0, height: 10.0)
    self.center = location

    self.userInteractionEnabled = true

    self.container = container
    self.viewToScale = viewToScale
    self.id = id
    self.hidden = false
}

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

func getScaleParameters(arrivalPoint:CGPoint) -> (sx:CGFloat, sy:CGFloat) {

    //var result:(sx:CGFloat, sy:CGFloat) = (1.0, 1.0)
    var scaleX:CGFloat = 1.0
    var scaleY:CGFloat = 1.0

    switch (self.id) {
    case "up_left":
        /* up_left is moving towards right*/
        if (self.lastLocation.x < arrivalPoint.x) {
            scaleX = -0.99
        }
        /* up_left is moving towards left*/
        else {
            scaleX = 0.9
        }
        /* up_left is moving towards up*/
        if (self.lastLocation.y < arrivalPoint.y) {
            scaleY = -0.9
        }
        /* up_left is moving towards down*/
        else {
            scaleY = 0.9
        }
        break
    default:
        scaleX = 1.0
        scaleY = 1.0
    }

    return (scaleX, scaleY)

}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    if let touch: UITouch = touches.first {
        let scaleParameters:(sx:CGFloat, sy:CGFloat) = self.getScaleParameters(touch.locationInView(self.container))
        self.viewToScale.transform = CGAffineTransformMakeScale(scaleParameters.sx, scaleParameters.sy)
        //self.center = touch.locationInView(self.container)
        self.center = touch.locationInView(self.container)
        self.lastLocation = touch.locationInView(self.container)
    }
}

}

where viewToScale is the azure floating uiview called pincherViewRec. The center of the pin at the beginning is in pincherViewRec.frame.origin. It's useless to say that it does not work as expected. Do you have any idea? Any hint would be appreciated to help me getting the right way.

SagittariusA
  • 5,289
  • 15
  • 73
  • 127

0 Answers0