Swift: how to implement a scalable personalized uiview with four buttons at the top

I would like to implement a scalable and draggable UIView, as shown in the following figure:

enter image description here

This is the class that I have implemented so far with the help of simple gesture 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 uiview scales the same in both x and y directions, but I want users to be able to be as accurate as possible so that they can scale even in one direction or change the shape of the uiview , does not have to be a rectangle. Moreover, for me it is more important that the user is as accurate as possible when setting up the uiview vertex . So I need to have these 4 buttons in the corners. I just would like you to give me some tips on where to start and how. thank you

UPDATE This is what I did to know

enter image description here

So I have the following hierarchy:

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

I needed to add another UIView for use as a container, so that all its auxiliary files will be enlarged to / from the image in order to have more accuracy, in order to better combine azure uiview with photo objects. As for the pin, the little white circle, this is the class I tried to implement in order 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 an azure floating uiview called pincherViewRec . The pin center at the beginning is at pincherViewRec.frame.origin . It is useless to say that it does not work as expected. Do you have any ideas? Any hint would be appreciated to help me fit right.

+5
source share

Source: https://habr.com/ru/post/1238078/


All Articles