1

I'm using a UIPinchGestureRecognizer to resize the frames of views in my app. I'd like to resize height and width independently (the views are rectangles on a snap-to grid), and so I need to determine whether the pinch is intended to modify the height or the width.

Initially I tried using the slope between the two points, as many SO posts suggest. Something like this:

enum ScalingType {
    case widthOnly, heightOnly, widthAndHeight
}

private func determineScaling(loc1: CGPoint, loc2: CGPoint) -> ScalingType {
    let dx = abs(loc1.x - loc2.x)
    let dy = abs(loc1.y - loc2.y)

    if dx > dy {
        return .widthOnly
    } else {
        return .heightOnly
    }
}

While this works for most shapes, it does not work when the shape becomes very narrow in either dimension. For example, if I want to resize the height of a rectangle with short height and long width, the fingers will move vertically, but the fingers will probably have more horizontal distance than vertical.

Is there a best way to get (for example) the translation of points in a pinch gesture or some way to determine the direction the fingers have moved?

Thanks

c_booth
  • 2,185
  • 1
  • 13
  • 22

2 Answers2

1

I'm guessing that you are running into a scenario where the narrow width or height is less then 44 (44 is the suggested guideline by Apple as apparently that's how many pixels a finger touch covers). I would recommend to discard the UIPinchGesture altogether and use a UIPanGesture instead. Keep in mind that it will change the functionality. Instead of pinch to scale, you would be dragging individual sides to scale (something like what happens while you crop a picture in iPhone's photo library). By using this approach, if there is narrow width or height, you don't have to worry about two fingers being too close (for a pinch) and messing up the maths

Malik
  • 3,763
  • 1
  • 22
  • 35
  • Actually my minimum dimension is 70 - easily big enough for one touch, but not big enough for 2 with no horizontal (or vertical) space between them. But I'll experiment with your suggestion about the pan gesture - that might be a less clumsy way to do this. Tnx – c_booth Aug 22 '17 at 01:03
  • Glad to be of help – Malik Aug 22 '17 at 01:05
0

Here is Swift code to determine if a pinch is more horizontal or more vertical.

When it is more horizontal, a width factor is increased or decreased.

When it is more vertical, a height factor is increased or decreased.

Give the below func declaration

  @objc func handlePinch(pinch: UIPinchGestureRecognizer)

Then in the body of that function, check that 2 touch points for the pinch exist to avoid a crash.

Then check the magnitude of the delta in the X and Y directions.

It works really good when the fingers are far apart.

                        
      if pinch.numberOfTouches < 2 {
        print("don't crash")
        return
      }

      var touchPoint1 = pinch.location(ofTouch: 0, in: self.view)
      var touchPoint2 = pinch.location(ofTouch: 1, in: self.view)

      let deltaX = abs(touchPoint1.x - touchPoint2.x)
      let deltaY = abs(touchPoint1.y - touchPoint2.y)

      if deltaX > deltaY
      {
        dropRectangleCurrentWidth *= pinch.scale
      }
      else
      {
        dropRectangleCurrentHeight *= pinch.scale
      }

      pinch.scale = 1


user3408691
  • 93
  • 1
  • 1
  • 7