如何将可拖动的UIView限制为特定边界

时间:2016-06-02 14:29:56

标签: ios swift uiimageview uigesturerecognizer

我有UIImageView我通过名为DraggableImageView2的自定义类创建了Draggable。然后,该类在带有图像的UIViewController中实例化,并且可以在UIView内拖动。问题是我想限制UIImageView在拖动时不要经过特定的边界。这是我目前的代码:

import UIKit

class DraggableImageView2: UIImageView, UIGestureRecognizerDelegate {

    var dragStartPositionRelativeToCenter : CGPoint?

    var dragGesture: UIGestureRecognizer!
    var zoomGesture: UIGestureRecognizer!

    var lastKnownCenterX: CGFloat = 0.0
    var lastKnownCenterY: CGFloat = 0.0

    required init?(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)

        self.initializeGestures()

    }


    override init(image: UIImage?) {

        super.init(image: image)

        self.initializeGestures()

    }

    override init(frame: CGRect) {

        super.init(frame: frame)

        self.initializeGestures()

    }

    func initializeGestures() {

        self.userInteractionEnabled = true
        self.multipleTouchEnabled = true

        dragGesture = UIPanGestureRecognizer(target: self, action: #selector(DraggableImageView.handlePan(_:)))

        self.addGestureRecognizer(dragGesture)

    }

    func handlePan(recognizer: UIPanGestureRecognizer!) {

        Scripts.log("PAN >>> MOVE ACTIVATED")

        if recognizer.state == UIGestureRecognizerState.Began {

            let locationInView = recognizer.locationInView(superview)
            dragStartPositionRelativeToCenter = CGPoint(x: locationInView.x - center.x, y: locationInView.y - center.y)

            return

        }

        if recognizer.state == UIGestureRecognizerState.Ended {

            dragStartPositionRelativeToCenter = nil

            return
        }

        let locationInView = recognizer.locationInView(superview)

        Scripts.log("PAN LOCATION >>> X = \(self.frame.origin.x) | Y = \(self.frame.origin.y) | LX = \(locationInView.x) | LY = \(locationInView.y) | DX = \(self.dragStartPositionRelativeToCenter!.x) | DY = \(self.dragStartPositionRelativeToCenter!.y)")

        let xDragMin: CGFloat = 1.0
        let yDragMin: CGFloat = 1.0
        let xDragMax: CGFloat = kDEVICE_WIDTH - self.frame.size.width - 1.0
        let yDragMax: CGFloat = kDEVICE_WIDTH - self.frame.size.height - 1.0

        var newCenterX: CGFloat = locationInView.x - self.dragStartPositionRelativeToCenter!.x
        var newCenterY: CGFloat = locationInView.y - self.dragStartPositionRelativeToCenter!.y

        if self.frame.origin.x < xDragMin {

            Scripts.log("PAN LOCATION >>> X MIN PAST BOUNDS")

            newCenterX =  lastKnownCenterX

        }

        if self.frame.origin.y < yDragMin {

            Scripts.log("PAN LOCATION >>> Y MIN PAST BOUNDS")

            newCenterY = lastKnownCenterY

        }

        if self.frame.origin.x > xDragMax {

            Scripts.log("PAN LOCATION >>> X MAX PAST BOUNDS")

        }

        if self.frame.origin.y > yDragMax {

            Scripts.log("PAN LOCATION >>> Y MAX PAST BOUNDS")

        }


        UIView.animateWithDuration(0.1) {
            self.center = CGPoint(x: newCenterX,
                                  y: newCenterY)
        }

        lastKnownCenterX = newCenterX
        lastKnownCenterY = newCenterY

    }


    func handlePinch(recognizer: UIPinchGestureRecognizer!) {

        Scripts.log("PINCH >>> ZOOM ACTIVATED")

        //self.bringSubviewToFront(recognizer.view!)

        recognizer.view?.transform = CGAffineTransformScale((recognizer.view?.transform)!, recognizer.scale, recognizer.scale)
        recognizer.scale = 1

    }

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {

        Scripts.log("shouldRecognizeSimultaneouslyWithGestureRecognizer WAS CALLED")

        return true

    }

}

我才开始处理xDragMinyDragMin部分。当它小于 xDragMin 时,一切都可以阻止它,但问题出现了一些奇怪的原因,当你试图拖出它时,它会在那个X点被冻结。对于 yDragMin 也是如此,如果达到最小值,它会停止,但不能拖出Y点。

1 个答案:

答案 0 :(得分:0)

所以经过一些更多的挖掘和游戏,我似乎已经能够解决我自己的问题,至少对于X Bounds Min而言。这是我做的:

(1)添加了这些新变量

var isWithinXBounds: Bool = true
var lastKnownLX: CGFloat = 0.0

(2)以“if self.frame.origin.x&lt; xDragMin”开头的逻辑需要微调。这个条件非常好,直到它达到X界限。一旦它发生,那么self.frame.origin.x将永远不会改变(DUH)cos现在它的位置被锁定。我需要另一个条件来检查一旦界限被击中,即锁定,检查用户是否正在向+ ve方向移动。如果是,则将BOOL值设置回TRUE,这将解锁x位置

  if self.frame.origin.x < xDragMin {

        Scripts.log("PAN LOCATION >>> X MIN PAST BOUNDS")

        self.isWithinXBounds = false

        //If TOUCH still moving in negative direction
        if locationInView.x - lastKnownLX  < 0 {

            newCenterX =  lastKnownCenterX

        }
        else {

            self.isWithinXBounds = true

        }

    }

(3)这是根据BOOL值解锁UIImageView的条件:

if isWithinXBounds {

        lastKnownCenterX = newCenterX
        lastKnownLX = locationInView.x

    }