UIView 转换后拖动行为错误

Drag behaviour wrong after UIView transformation

我有一个自定义 DraggableView 子类 UIImageView。我用相机拍照,将生成的 UIImage 添加到 DraggableView,然后我可以愉快地将它拖到屏幕上,如预期的那样。

现在,如果原始照片是横向拍摄的,我会使用以下方法旋转它:

if (image?.size.width > image?.size.height)
{
   self.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
}

当我应用此转换时,拖动行为仍然有效,但方向全错了 - 如果我向左拖动,图像会向上移动,而不是向左移动。如果我向上拖动,图像会向右移动,而不是向上移动。

我该如何解决这个问题?我想这与 UIPanGestureRecognizer 绑定到非转换视图有关?

编辑: 当前 UIPanGestureRecognizer 处理程序:

func onPhotoDrag(recognizer: UIPanGestureRecognizer?)
{
    let translation = recognizer!.translationInView(recognizer?.view)
    recognizer!.view!.center = CGPointMake(recognizer!.view!.center.x 
            + translation.x, recognizer!.view!.center.y + translation.y);
    recognizer?.setTranslation(CGPointZero, inView: recognizer?.view)

    if (recognizer!.state == UIGestureRecognizerState.Ended)
    {
        let velocity = recognizer!.velocityInView(recognizer?.view)
        let magnitude = sqrt((velocity.x * velocity.x) 
                + (velocity.y * velocity.y))
        let slideMult = magnitude / 300;
        let slideFactor = 0.1 * slideMult;
        let finalPoint = CGPointMake(recognizer!.view!.center.x 
                + (velocity.x * slideFactor), 
                recognizer!.view!.center.y + (velocity.y * slideFactor));

        // Animate the drag, and allow the drag delegate to do its work
        DraggableView.animateWithDuration(Double(slideFactor), 
                delay: 0, options: UIViewAnimationOptions.CurveEaseOut,
                animations: { recognizer?.view?.center = finalPoint },
                completion: {(_) -> Void in self.dragDelegate?.onDragEnd(self)})
    } // if: gesture ended
}

更新:

感谢您发布代码。我将您的代码粘贴到我的 DraggableImageView 中并重现了您的问题。虽然我的版本处理的是旋转视图(没有动画),但你的版本是横向的。

不同之处在于我的代码要求在可拖动视图的 superview 中输入 translationInView。您需要在可拖动视图的 superview 中请求 translationInViewvelocityInView

更改此行:

let translation = recognizer!.translationInView(recognizer?.view)

至:

let translation = recognizer!.translationInView(recognizer?.view?.superview)

并更改此:

let velocity = recognizer!.velocityInView(recognizer?.view)

至:

let velocity = recognizer!.velocityInView(recognizer?.view?.superview)

一切都会幸福。


上一个答案:

试试这个版本:

class DraggableImageView: UIImageView {
    
    override var image: UIImage? {
        didSet {
            if (image?.size.width > image?.size.height)
            {
                self.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
            }
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        self.setup()
    }
    
    func setup() {
        self.userInteractionEnabled = true
        
        let panGestureRecognizer = UIPanGestureRecognizer()
        panGestureRecognizer.addTarget(self, action: #selector(draggedView(_:)))
        self.addGestureRecognizer(panGestureRecognizer)
    }
    
    func moveByDeltaX(deltaX: CGFloat, deltaY: CGFloat) {
        self.center.x += deltaX
        self.center.y += deltaY
    }
    
    func draggedView(sender:UIPanGestureRecognizer) {
        if let dragView = sender.view as? DraggableImageView, superview = dragView.superview {
            superview.bringSubviewToFront(dragView)
            let translation = sender.translationInView(superview)
            sender.setTranslation(CGPointZero, inView: superview)
            dragView.moveByDeltaX(translation.x, deltaY: translation.y)
        }
    }
}

使用示例:

override func viewDidLoad() {
    super.viewDidLoad()
    
    let dragView = DraggableImageView(frame: CGRect(x: 50, y: 50, width: 96, height: 128))
    
    dragView.image = UIImage(named: "landscapeImage.png")
    
    self.view.addSubview(dragView)
}