Dragging Views with Gestures Tutorial

The strength of iOS lies in the interaction using touches and gestures. In this tutorial we'll display some custom views, which we can drag using the pan gesture recognizer. This tutorial is made with Xcode 8 and built for iOS 10.

Open Xcode and create a new Single View Application

Choose Next. For product name, use IOS10DraggingViewsTutorial and then fill out the Organization Name and Organization Identifier with your customary values. Enter Swift as Language and make sure only iPhone is selected in Devices.

First, let's create the views which we will place randomly on the screen. Add a new class file to the project with File->New -> File -> iOS -> Cocoa Touch Class. Name the class MyView with a Subclass of UIView.

Go to the MyView.swift file and add a the following property.

var lastLocation = CGPoint(x: 0, y: 0)

This variable will keep track of the last position of a user's touch. Next, implement the init method

override init(frame: CGRect) {
    super.init(frame: frame)
        
    // Initialization code
    let panRecognizer = UIPanGestureRecognizer(target:self, action:#selector(MyView.detectPan(_:)))
    self.gestureRecognizers = [panRecognizer]
        
    //randomize view color
    let blueValue = CGFloat(Int(arc4random() % 255)) / 255.0
    let greenValue = CGFloat(Int(arc4random() % 255)) / 255.0
    let redValue = CGFloat(Int(arc4random() % 255)) / 255.0
        
    self.backgroundColor = UIColor(red:redValue, green: greenValue, blue: blueValue, alpha: 1.0)
}

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

First we attach a pan gesture recognizer to the view. Using this recognizer we can click and drag a view to a new position. Next, we create a random color, which we assign to the background color property of our view. implement the detectPan method, which will be called when a pan gesture is recognized.

func detectPan(_ recognizer:UIPanGestureRecognizer) {
    let translation  = recognizer.translation(in: self.superview)
    self.center = CGPoint(x: lastLocation.x + translation.x, y: lastLocation.y + translation.y)
}

The translation variable detects the new coordinates of the view when panning. The center of the view will be adjusted according to the changed coordinates. When the user clicks on a view the touchesBegan:event method is called. Let's implement this method.

override func touchesBegan(_ touches: (Set<UITouch>!), with event: UIEvent!) {
    // Promote the touched view
    self.superview?.bringSubview(toFront: self)
      
    // Remember original location
    lastLocation = self.center
}

When the view is clicked, the current view will be displayed in front of the other views and the center of the view will be assigned to the lastlocation variable. Now, our custom view is ready, let's move over to our view controller. Implement the viewDidLoad function in ViewController.swift

override func viewDidLoad() {
    super.viewDidLoad()
        
    let halfSizeOfView = 25.0
    let maxViews = 25
    let insetSize = self.view.bounds.insetBy(dx: CGFloat(Int(2 * halfSizeOfView)), dy: CGFloat(Int(2 * halfSizeOfView))).size
        
    // Add the Views
    for _ in 0..<maxViews {
        let pointX = CGFloat(UInt(arc4random() % UInt32(UInt(insetSize.width))))
        let pointY = CGFloat(UInt(arc4random() % UInt32(UInt(insetSize.height))))
            
        let newView = MyView(frame: CGRect(x: pointX, y: pointY, width: 50, height: 50))
        self.view.addSubview(newView)
    }
}

There will be 25 custom views of size 50 by 50 and added to the main view. The custom view will be placed randomly on the main view. Build and Run the project. Click and drag a view and you will see the views will always be in front of the other views.

You can download the source code of the IOS10DraggingViewsTutorial at the ioscreator repository on github.