簡體   English   中英

在平移手勢上設置邊界

[英]Setting boundaries on pan gestures

我創建了5個UIView,每個UIView都有UIPanGestureRecognizers,然后將它們添加到另一個UIView中。 所有這些工作正常,我可以將它們拖到各處,但我不希望它們被拖到其父UIView的邊界之外。 我已經讀過我可以使用gestureRecognizerShouldBegin函數實現UIGestureRecognizerDelegate來實現此目的,但是我找不到足夠的文檔來確切地了解如何實現所需的功能。 和往常一樣,蘋果公司對此的文件含糊不清。 我的代碼是:

    let foreheadTopViewWidth = foreheadTopView.frame.width
            let foreheadTopViewHeight = foreheadTopView.frame.height
            let touchPointOffset = touchPointSize / 2
            let touchPointYPos = (foreheadTopViewHeight / 2) - touchPointOffset

            let touchPointForehead1 = TouchPoint(touchPointSize: touchPointSize, xPosition: 0, yPosition: touchPointYPos, treatmentArea: .upperForehead)
            let touchPointForehead2 = TouchPoint(touchPointSize: touchPointSize, xPosition: ((foreheadTopViewWidth * 0.50) - touchPointOffset) / 2, yPosition: touchPointYPos, treatmentArea: .upperForehead)
            let touchPointForehead3 = TouchPoint(touchPointSize: touchPointSize, xPosition: (foreheadTopViewWidth * 0.50) - touchPointOffset, yPosition: touchPointYPos, treatmentArea: .upperForehead)
            let touchPointForehead4 = TouchPoint(touchPointSize: touchPointSize, xPosition: (foreheadTopViewWidth * 0.75) - (touchPointOffset / 0.75), yPosition: touchPointYPos, treatmentArea: .upperForehead)
            let touchPointForehead5 = TouchPoint(touchPointSize: touchPointSize, xPosition: foreheadTopViewWidth - touchPointSize, yPosition: touchPointYPos, treatmentArea: .upperForehead)

            foreheadTopView.addSubview(touchPointForehead1)
            foreheadTopView.addSubview(touchPointForehead2)
            foreheadTopView.addSubview(touchPointForehead3)
            foreheadTopView.addSubview(touchPointForehead4)
            foreheadTopView.addSubview(touchPointForehead5)

            let foreheadGesture1 = UIPanGestureRecognizer(target: self, action: #selector(didPan(gesture:)))
            let foreheadGesture2 = UIPanGestureRecognizer(target: self, action: #selector(didPan(gesture:)))
            let foreheadGesture3 = UIPanGestureRecognizer(target: self, action: #selector(didPan(gesture:)))
            let foreheadGesture4 = UIPanGestureRecognizer(target: self, action: #selector(didPan(gesture:)))
            let foreheadGesture5 = UIPanGestureRecognizer(target: self, action: #selector(didPan(gesture:)))
            foreheadGesture1.delegate = self
            foreheadGesture2.delegate = self
            foreheadGesture3.delegate = self
            foreheadGesture4.delegate = self
            foreheadGesture5.delegate = self

            touchPointForehead1.addGestureRecognizer(foreheadGesture1)
            touchPointForehead2.addGestureRecognizer(foreheadGesture2)
            touchPointForehead3.addGestureRecognizer(foreheadGesture3)
            touchPointForehead4.addGestureRecognizer(foreheadGesture4)
            touchPointForehead5.addGestureRecognizer(foreheadGesture5)

            foreheadTopView.layer.addSublayer(touchPointForehead1.lineTo(touchpoint: touchPointForehead2))
            foreheadTopView.layer.addSublayer(touchPointForehead2.lineTo(touchpoint: touchPointForehead3))
            foreheadTopView.layer.addSublayer(touchPointForehead3.lineTo(touchpoint: touchPointForehead4))
            foreheadTopView.layer.addSublayer(touchPointForehead4.lineTo(touchpoint: touchPointForehead5))

@objc func didPan(gesture: UIPanGestureRecognizer) {

        guard let touchpoint = gesture.view as? TouchPoint else {
            return
        }
        if (gesture.state == .began) {
            touchpoint.center = gesture.location(in: foreheadTopView)
        }

        let newCenter: CGPoint = gesture.location(in: foreheadTopView)
        let dX = newCenter.x - touchpoint.center.x
        let dY = newCenter.y - touchpoint.center.y
        touchpoint.center = CGPoint(x: touchpoint.center.x + dX, y: touchpoint.center.y + dY)

        if let outGoingTouchPoint = touchpoint.outGoingTouchPoint, let line = touchpoint.outGoingLine, let path = touchpoint.outGoingLine?.path {
            let newPath = UIBezierPath(cgPath: path)
            newPath.removeAllPoints()
            newPath.move(to: touchpoint.center)
            newPath.addLine(to: outGoingTouchPoint.center)
            line.path = newPath.cgPath
        }

        if let inComingTouchPoint = touchpoint.inComingTouchPoint, let line = touchpoint.inComingLine, let path = touchpoint.inComingLine?.path {
            let newPath = UIBezierPath(cgPath: path)
            newPath.removeAllPoints()
            newPath.move(to: inComingTouchPoint.center)
            newPath.addLine(to: touchpoint.center)
            line.path = newPath.cgPath
        }
    }

上面的代碼在平移/拖動方面需要我做的很好。 我還擴展了ViewController以使其符合UIGestureRecognizerDelegate

extension ViewController: UIGestureRecognizerDelegate {
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {

    }
}

但是我不確定如何將可拖動視圖限制在其父視圖的范圍之內,從何而來。 有人可以幫忙嗎?

您必須進行一些計算,希望這段代碼對您有所幫助。

@objc func handlepan(_ gesture:UIPanGestureRecognizer)
{
    let translation = gesture.translation(in: self.imagelayer)
    if let view1 = gesture.view {

        if (view1.frame.origin.x + translation.x >= 0) && (view1.frame.origin.y + translation.y >= 0) && (view1.frame.origin.x + translation.x <= view1.frame.width ) && (view1.frame.origin.y + translation.y <= view1.frame.height)
        {
        view1.center = CGPoint(x:view1.center.x + translation.x,
                              y:view1.center.y + translation.y)
        }
    }
    gesture.setTranslation(CGPoint.zero, in: self.imagelayer)
}

不,委托不適合這個事情。 我相信您想保持手勢,只是將視圖的位置限制在其父視圖之內。 為此,您需要限制平移手勢更改事件。

最簡單的方法是檢查兩個相對的點是否在父矩形內:

let topLeft = CGPoint(x: touchpoint.frame.minX + dX, y: touchpoint.frame.minY + dY)
let bottomRight = CGPoint(x: touchpoint.frame.maxX + dX, y: touchpoint.frame.maxY + dY)
if let containerView = touchpoint.superview, containerView.bounds.contains(topLeft), containerView.bounds.contains(bottomRight) {
    touchpoint.center = CGPoint(x: touchpoint.center.x + dX, y: touchpoint.center.y + dY)
}

因此,基本上,我們正在計算新的左上和右下點。 並且如果這些在其超級視圖范圍之內,則視圖可能會移至該點。

這是相當不錯的,但事實是,一旦發生這種情況,您的視線可能就不會完全在邊界處。 例如,如果用戶將它真正快速地向左拖動,則在某個點topLeft可能是(15, 0) topLeft (15, 0) ,在下一個事件中(-10, 0) topLeft (-10, 0)意味着這將忽略第二個,並保持在(15, 0) topLeft (15, 0)

因此,您需要將limi實現為運動並將其限制為運動...

var targetFrame = CGRect(x: touchpoint.frame.origin.x + dX, y: touchpoint.frame.origin.y + dY, width: touchpoint.frame.width, height: touchpoint.frame.height)

if let containerView = touchpoint.superview {
    targetFrame.origin.x = max(0.0, targetFrame.origin.x)
    targetFrame.origin.y = max(0.0, targetFrame.origin.y)
    targetFrame.size.width = min(targetFrame.size.width, containerView.bounds.width-(targetFrame.origin.x+targetFrame.width))
    targetFrame.size.height = min(targetFrame.size.height, containerView.bounds.height-(targetFrame.origin.y+targetFrame.height))
}

touchpoint.frame = targetFrame

所以這應該使您的視圖停留在超級視圖內...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM