0

我想要有幾個可以拖放的對象。如何實現多個PanGestures(可拖拽視圖)?

這裏是我的移動一個對象(與@vacawama很大的幫助)代碼:

import UIKit 

class ViewController: UIViewController { 

@IBOutlet weak var panView: UIView! 

@IBOutlet weak var panViewCenterX: NSLayoutConstraint! 
@IBOutlet weak var panViewCenterY: NSLayoutConstraint! 

let panRec = UIPanGestureRecognizer() 

override func viewDidLoad() { 
    super.viewDidLoad() 

    panRec.addTarget(self, action: "draggedView:") 
    panView.addGestureRecognizer(panRec) 

// Do any additional setup after loading the view, typically from a nib. 
} 

func draggedView(sender:UIPanGestureRecognizer){ 

    self.view.bringSubviewToFront(sender.view!) 
    var translation = sender.translationInView(self.view) 

    panViewCenterY.constant += translation.y 
    panViewCenterX.constant += translation.x 

    sender.setTranslation(CGPointZero, inView: self.view) 
} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Dispose of any resources that can be recreated. 
} 

} 

我想在我的項目更多的對象:

@IBOutlet weak var panView2: UIView! 
@IBOutlet weak var panView3: UIView! 
@IBOutlet weak var panView4: UIView! 
... 

那麼,什麼是最簡單的方法來實現這種方式,我可以有多個panView,我可以獨立移動(當時一個)?

+0

只要做到這一點。有什麼問題? – matt 2014-11-25 02:40:04

+0

我的問題是我不完全明白我在做什麼(這就是爲什麼我在這裏發佈)。這是我的「理解」:我用'panRec'檢測PanGesture,並將該手勢傳遞給'func draggedView',並在那裏設置新的位置。但是「panView.addGestureRecognizer(panRec)」究竟是什麼。或者是周圍的其他方式?我希望有一種方法,我可以有一個'panRec'並用switch語句來測試它是'panView1'還是'panView2'或'panView3'等等,然後相應地設置位置。 – Kjetil 2014-11-25 06:44:26

+0

我已經經歷了很多例子,並且我很快就放棄了...用「-1」衝刺我並沒有真正的幫助;-) – Kjetil 2014-11-25 06:45:51

回答

3

如果您使用自動佈局,您不應該通過改變其中心來移動視圖。任何導致自動佈局運行的事件都會將您的視圖移回原始位置。

下面是一個名爲DraggableView的新類的實現,它與自動佈局一起使用,以提供可以拖動的視圖。它在代碼中爲視圖的寬度,高度,X位置和Y位置創建約束。它使用自己的UIPanGestureRecognizer來允許拖動視圖。

DraggableView.swift可以被拖放到任何需要可拖動視圖的項目中。看看下面的ViewController.swift,看看它是多麼容易使用。

DraggableView。迅速

import UIKit 

class DraggableView: UIView { 
    let superView: UIView! 
    let xPosConstraint: NSLayoutConstraint! 
    let yPosConstraint: NSLayoutConstraint! 
    var constraints: [NSLayoutConstraint] { 
     get { 
      return [xPosConstraint, yPosConstraint] 
     } 
    } 

    init(width: CGFloat, height: CGFloat, x: CGFloat, y: CGFloat, color: UIColor, superView: UIView) { 
     super.init() 

     self.superView = superView 

     self.backgroundColor = color 

     self.setTranslatesAutoresizingMaskIntoConstraints(false) 

     let panGestureRecognizer = UIPanGestureRecognizer() 
     panGestureRecognizer.addTarget(self, action: "draggedView:") 
     self.addGestureRecognizer(panGestureRecognizer) 

     let widthConstraint = NSLayoutConstraint(item: self, attribute: .Width, relatedBy: .Equal, 
      toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: width) 
     self.addConstraint(widthConstraint) 

     let heightConstraint = NSLayoutConstraint(item: self, attribute: .Height, relatedBy: .Equal, 
      toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: height) 
     self.addConstraint(heightConstraint) 

     xPosConstraint = NSLayoutConstraint(item: self, attribute: .CenterX, relatedBy: .Equal, 
      toItem: superView, attribute: .Leading, multiplier: 1.0, constant: x) 

     yPosConstraint = NSLayoutConstraint(item: self, attribute: .CenterY, relatedBy: .Equal, 
      toItem: superView, attribute: .Top, multiplier: 1.0, constant: y) 
    } 

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

    required init(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

    func moveByDeltaX(deltaX: CGFloat, deltaY: CGFloat) { 
     xPosConstraint.constant += deltaX 
     yPosConstraint.constant += deltaY 
    } 

    func draggedView(sender:UIPanGestureRecognizer){ 
     if let dragView = sender.view as? DraggableView { 
      superView.bringSubviewToFront(dragView) 
      var translation = sender.translationInView(superView) 
      sender.setTranslation(CGPointZero, inView: superView) 
      dragView.moveByDeltaX(translation.x, deltaY: translation.y) 
     } 
    } 
} 

ViewController.swift

import UIKit 

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let dragView1 = DraggableView(width: 75, height: 75, x: 50, y: 50, 
      color: UIColor.redColor(), superView: self.view) 
     self.view.addSubview(dragView1) 
     self.view.addConstraints(dragView1.constraints) 

     let dragView2 = DraggableView(width: 100, height: 100, x: 150, y: 50, 
      color: UIColor.blueColor(), superView: self.view) 
     self.view.addSubview(dragView2) 
     self.view.addConstraints(dragView2.constraints) 

     let dragView3 = DraggableView(width: 125, height: 125, x: 100, y: 175, 
      color: UIColor.greenColor(), superView: self.view) 
     self.view.addSubview(dragView3) 
     self.view.addConstraints(dragView3.constraints) 
    } 
} 

UPDATE:

這裏是DraggableView.swift支持圖像作爲一個子視圖的一個版本。

import UIKit 

class DraggableView: UIView { 
    let superView: UIView! 
    let xPosConstraint: NSLayoutConstraint! 
    let yPosConstraint: NSLayoutConstraint! 
    var constraints: [NSLayoutConstraint] { 
     get { 
      return [xPosConstraint, yPosConstraint] 
     } 
    } 

    init(width: CGFloat, height: CGFloat, x: CGFloat, y: CGFloat, color: UIColor, superView: UIView, imageToUse: String? = nil, contentMode: UIViewContentMode = .ScaleAspectFill) { 
     super.init() 

     self.superView = superView 

     self.backgroundColor = color 

     self.setTranslatesAutoresizingMaskIntoConstraints(false) 

     let panGestureRecognizer = UIPanGestureRecognizer() 
     panGestureRecognizer.addTarget(self, action: "draggedView:") 
     self.addGestureRecognizer(panGestureRecognizer) 

     let widthConstraint = NSLayoutConstraint(item: self, attribute: .Width, relatedBy: .Equal, 
      toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: width) 
     self.addConstraint(widthConstraint) 

     let heightConstraint = NSLayoutConstraint(item: self, attribute: .Height, relatedBy: .Equal, 
      toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: height) 
     self.addConstraint(heightConstraint) 

     xPosConstraint = NSLayoutConstraint(item: self, attribute: .CenterX, relatedBy: .Equal, 
      toItem: superView, attribute: .Leading, multiplier: 1.0, constant: x) 

     yPosConstraint = NSLayoutConstraint(item: self, attribute: .CenterY, relatedBy: .Equal, 
      toItem: superView, attribute: .Top, multiplier: 1.0, constant: y) 

     if imageToUse != nil { 
      if let image = UIImage(named: imageToUse!) { 
       let imageView = UIImageView(image: image) 
       imageView.contentMode = contentMode 
       imageView.clipsToBounds = true 
       imageView.setTranslatesAutoresizingMaskIntoConstraints(false) 
       self.addSubview(imageView) 
       self.addConstraint(NSLayoutConstraint(item: imageView, attribute: .Left, relatedBy: .Equal, toItem: self, attribute: .Left, multiplier: 1.0, constant: 0)) 
       self.addConstraint(NSLayoutConstraint(item: imageView, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1.0, constant: 0)) 
       self.addConstraint(NSLayoutConstraint(item: imageView, attribute: .Right, relatedBy: .Equal, toItem: self, attribute: .Right, multiplier: 1.0, constant: 0)) 
       self.addConstraint(NSLayoutConstraint(item: imageView, attribute: .Bottom, relatedBy: .Equal, toItem: self, attribute: .Bottom, multiplier: 1.0, constant: 0)) 
      } 
     } 
    } 

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

    required init(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

    func moveByDeltaX(deltaX: CGFloat, deltaY: CGFloat) { 
     xPosConstraint.constant += deltaX 
     yPosConstraint.constant += deltaY 
    } 

    func draggedView(sender:UIPanGestureRecognizer){ 
     if let dragView = sender.view as? DraggableView { 
      superView.bringSubviewToFront(dragView) 
      var translation = sender.translationInView(superView) 
      sender.setTranslation(CGPointZero, inView: superView) 
      dragView.moveByDeltaX(translation.x, deltaY: translation.y) 
     } 
    } 
} 
+0

這很聰明,但沒有必要。如果視圖可拖動,則不適合通過自動佈局進行定位。所以只需將它從自動佈局中取出即可。對於一個或兩個特殊視圖來說,在使用自動佈局的界面中不會自動佈局是完全合理的/合法的。 – matt 2014-11-26 16:16:41

+0

你如何「自動佈局」? – vacawama 2014-11-26 16:43:56

+0

@matt,這是對OP之前詢問的一個後續問題。在那一個,他正在更新一個'UILabel',他的拖動視圖因爲自動佈局而停止工作。他說他想要自動佈局,所以這就是我走向這條道路的原因。我不知道如何爲單個視圖禁用自動佈局,僅適用於Storyboard或XIB。 – vacawama 2014-11-26 17:13:44

0

手勢識別器的工作方式是將其附加到視圖。因此,如果您有多個視圖,並且您希望它們可以以相同方式拖動,請爲每個視圖附加一個不同的平移手勢識別器。

現在讓我們假設你希望它們都具有相同的動作處理器。沒問題。在動作處理程序中,您將接收當前手勢識別器作爲參數。它有一個view財產;這就是它所附的觀點!所以現在你知道這就是你正在移動的視圖。

+0

但是總的來說,你不認爲在你使用手勢識別器之前最好先學習_learn_,這樣你纔不會在四處亂打併說「我不完全明白我在做什麼」?例如,我在這裏向您解釋它們:http://www.apeth.com/iOSBook/ch18.html#_gesture_recognizers – matt 2014-11-25 15:17:49

+0

是的,總的來說,我同意!我瞭解手勢的概念,這是我正在努力的實現部分..我會繼續閱讀,thanx的鏈接。 – Kjetil 2014-11-25 21:10:44

0

最後:

發現這個例子中一個簡單的方法來解釋它: http://www.raywenderlich.com/76020/using-uigesturerecognizer-with-swift-tutorial

所以,現在多潘氏正在..

下面的代碼:

import UIKit 

class ViewController: UIViewController { 


@IBOutlet weak var boxToMove1: UIView! 
@IBOutlet weak var boxToMove2: UIView! 


override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view, typically from a nib. 
} 

@IBAction func handlePan(objectToMove:UIPanGestureRecognizer) { 

    let translation = objectToMove.translationInView(self.view) 
    objectToMove.view!.center = CGPoint(x: objectToMove.view!.center.x + translation.x, y: objectToMove.view!.center.y + translation.y) 
    objectToMove.setTranslation(CGPointZero, inView: self.view) 

    println("\(objectToMove.view!.tag)") //Verify correct object received 
} 
override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Dispose of any resources that can be recreated. 
} 
} 

我將「Pan Gesture Recognizer」從「對象庫」鏈接到每個boxToMove。然後我將「Pan Gesture Recognizer」(兩者)連接到我的@IBAction func handlePan ...

這現在正在工作! 最後,我明白了這個手勢識別器的工作方式!

我仍然試圖弄清楚的是如何以編程方式完成所有這些鏈接。任何想法?