【问题标题】:Draggable UIView Swift 3可拖动的 UIView Swift 3
【发布时间】:2017-09-28 14:57:23
【问题描述】:

我希望能够拖动屏幕上的对象,但他们不会。我什么都试过了,还是不行。

这里是代码。

func panGesture(gesture: UIPanGestureRecognizer) {
    switch gesture.state {
    case .began:
        print("Began.")
        for i in 0..<forms.count {
            if forms[i].frame.contains(gesture.location(in: view)) {
                gravity.removeItem(forms[i])
            }
        }
    case .changed:
        let translation = gesture.translation(in: forms[1])

        gesture.view!.center = CGPoint(x: gesture.view!.center.x + translation.x, y: gesture.view!.center.y + translation.y)

        gesture.setTranslation(CGPoint.zero, in: self.view)

        print("\(gesture.view!.center.x)=\(gesture.view!.center.y)")
        print("t;: \(translation)")
    case .ended:
        for i in 0..<forms.count {
            if forms[i].frame.contains(gesture.location(in: view)) {
                gravity.addItem(forms[i])
            }
        }
        print("Ended.")
    case .cancelled:
        print("Cancelled")
    default:
        print("Default")
    }
}

它们也有重力。形状有正方形和圆形。

说明: 在 .began - 我禁用所选表单的重力。 在 .changed - 我尝试更改坐标。 在 .end - 我再次启用重力。

屏幕截图。

【问题讨论】:

    标签: ios swift xcode animation swift3


    【解决方案1】:

    第 1 步:获取一个要拖动到 storyBoard 中的 View。

    @IBOutlet weak var viewDrag: UIView!
    

    第 2 步:添加 PanGesture。

    var panGesture       = UIPanGestureRecognizer()
    

    第 3 步: 在 ViewDidLoad 中添加以下代码。

    override func viewDidLoad() {
        super.viewDidLoad()
    
        panGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.draggedView(_:)))
        viewDrag.isUserInteractionEnabled = true
        viewDrag.addGestureRecognizer(panGesture)
    
    }
    

    第 4 步:draggedView 的代码。

    func draggedView(_ sender:UIPanGestureRecognizer){
        self.view.bringSubview(toFront: viewDrag)
        let translation = sender.translation(in: self.view)
        viewDrag.center = CGPoint(x: viewDrag.center.x + translation.x, y: viewDrag.center.y + translation.y)
        sender.setTranslation(CGPoint.zero, in: self.view)
    }
    

    第 5 步: 输出。

    【讨论】:

    • 评论不用于扩展讨论;这个对话是moved to chat
    • 在 draggedView 中我使用了 sender.view,以便我可以将 draggedView 函数重用于其他可拖动视图。
    • 首先,非常感谢简单的解决方案。它在我的应用程序中工作得非常整洁,我将这个实现用于辅助摄像头视图(我自己在视频通话屏幕中的视频)。但是我面临的问题是计时器何时启动并且每秒钟刷新一次计时器标签。一旦计时器标签开始,视图就会回到原来的位置,然后如果我拖动视图,它就会回到原来的位置。
    • 我们需要为swift 4添加@obj到draggedView
    【解决方案2】:

    如果对视图进行子类化很容易:

    可拖动视图...

    class DraggableView: UIIView {
        
        var fromleft: NSLayoutConstraint!
        var fromtop: NSLayoutConstraint!
        
        override func didMoveToWindow() {
            super.didMoveToWindow()
            if window != nil {
                fromleft = constraint(id: "fromleft")!
                fromtop = constraint(id: "fromtop")!
            }
        }
        
        override func common() {
            super.common()
            let p = UIPanGestureRecognizer(
               target: self, action: #selector(drag))
            addGestureRecognizer(p)
        }
        
        @objc func drag(_ s:UIPanGestureRecognizer) {
            let t = s.translation(in: self.superview)
            fromleft.constant = fromleft.constant + t.x
            fromtop.constant = fromtop.constant + t.y
            s.setTranslation(CGPoint.zero, in: self.superview)
        }
    }
    
    1. 在你的场景中放置一个 UIView。

    2. 像往常一样,从左侧添加一个约束(即 x 位置)并从顶部添加一个约束(即 y 位置)。

    3. 在情节提要中,只需简单地命名约束“fromleft”和“fromtop”

    你已经完成了。

    现在完美运行 - 就是这样。

    方便的constraint( 电话是什么?

    请注意,视图只是通过名称找到自己的约束

    在 Xcode 中仍然没有办法使用像 IBOutlets 这样的约束。幸运的是,通过“标识符”很容易找到它们。 (事实上​​,这正是 .identifier 约束功能的目的。)

    extension UIView {
        
        func constraint(id: String) -> NSLayoutConstraint? {
            let cc = self.allConstraints()
            for c in cc { if c.identifier == id { return c } }
            //print("someone forgot to label constraint \(id)") //heh!
            return nil
        }
        
        func allConstraints() -> [NSLayoutConstraint] {
            var views = [self]
            var view = self
            while let superview = view.superview {
                views.append(superview)
                view = superview
            }
            return views.flatMap({ $0.constraints }).filter { c in
                return c.firstItem as? UIView == self ||
                    c.secondItem as? UIView == self
            }
        }
    

    尖端...边缘与中心!

    不要忘记对视图进行约束时(如上图所示):

    您可以将左边的设置为:

    • 到白框的左边缘,或者,
    • 到白盒子的中心

    根据您的情况选择正确的一种。这将使计算、设置滑块等变得更加容易。


    脚注 - 一个“正在初始化”的 UIView,UI“I”视图,

    // UI "I" View ... "I" for initializing
    // Simply saves you typing inits everywhere
    import UIKit
    class UIIView: UIView {
        override init(frame: CGRect) {
            super.init(frame: frame)
            common()
        }
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            common()
        }
        func common() { }
    }
    

    【讨论】:

    • 这个很完美,谢谢@Fattie,你太棒了
    • 谢谢@Mehul!这绝对是这些天唯一的出路。
    • 我同意你的看法。感谢您的贡献。你节省了我的时间和精力。
    • @Fattie,这很好。您是否有一种同样简洁的方法可以在此解决方案中加入对翻译的调整以消除 Apple 所说的 "distance for recognition as a pan"
    • @Paul ,有趣的是你应该问。这是 iOS 中的一个“著名问题”。这是几年前的著名答案:stackoverflow.com/a/19145354/294884(请注意在最近的一些代码中添加了某个英俊的列表成员:))请注意,每个“自定义触摸需求”都需要大量工作;很少有通用的解决方案。祝你好运!
    【解决方案3】:

    Use below code for Swift 5.0

    第 1 步:从 Storyboard 中取出一个 UIView,将其拖到您的 ViewController 文件中并创建 UIView 的 IBOutlet。

    @IBOutlet weak var viewDrag: UIView!
    var panGesture = UIPanGestureRecognizer()
    

    第 2 步:在 viewDidLoad() 中添加以下代码。

    override func viewDidLoad() {
    super.viewDidLoad()
      let panGesture = UIPanGestureRecognizer(target: self, action:(Selector(("draggedView:"))))
      viewDrag.isUserInteractionEnabled = true
      viewDrag.addGestureRecognizer(panGesture)
    }
    

    第 3 步:创建 func 并添加代码以移动 UIView,如下所示。

    func draggedView(sender:UIPanGestureRecognizer){
        self.view.bringSubviewToFront(viewDrag)
        let translation = sender.translation(in: self.view)
        viewDrag.center = CGPoint(x: viewDrag.center.x + translation.x, y: viewDrag.center.y + translation.y)
        sender.setTranslation(CGPoint.zero, in: self.view)
    }
    

    希望这会对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 2017-06-12
      • 1970-01-01
      • 1970-01-01
      • 2015-04-19
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      • 2013-01-18
      相关资源
      最近更新 更多