UIView 转换后拖动行为错误

Posted

技术标签:

【中文标题】UIView 转换后拖动行为错误【英文标题】:Drag behaviour wrong after UIView transformation 【发布时间】:2016-11-12 04:41:36 【问题描述】:

我有一个自定义的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

【问题讨论】:

你能发布你的可拖动视图的 panGestureHandler 代码吗? 而不是 DraggableView 继承 UIImageView,使其成为 UIView 的子类,然后将旋转后的 UIImageView 添加为子类。 已编辑以添加处理程序。我在DraggableViewinit 中进行旋转,但尝试答案中的方法没有任何区别。 【参考方案1】:

更新:

感谢您发布代码。我将您的代码粘贴到我的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)

【讨论】:

我试过这个,我看到它想做什么,但它没有用。根据@vacawama 的要求,我添加了当前的 pan 处理程序。 这如描述的那样工作,我明白为什么。谢谢! 我还应该说,这会阻止我从顶部的照片后面拖动(就像我以前可以做的那样),因为用于拖动的框架现在要大得多,但我可以解决这个问题稍后。 嗯。我不明白你最近的评论。这种变化仅仅是坐标到正确视图坐标的数学变换。这对您可以选择的内容有何影响? DraggableView 框架刚刚超出了显示的边界,然后我调整了图像,这以前是绑定到拖动行为的。我认为我需要更聪明地调整框架的大小。

以上是关于UIView 转换后拖动行为错误的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCell 中自定义 UIView 的 drawRect 行为错误

UIView锚点->拖动->旋转变换导致闪烁

拖动 touchesBegan 后创建的 UIView

在 tableview 滚动和再次拖动 tableview 上动画 UIView 位置

在两个 UiViewControllers 和 UIViews 之间实现拖动和滑动转换? [关闭]

可拖动的 UIView 在添加到 UIScrollView 后停止发布 touchesBegan