Creating a Linear Gravity Field on Your UI - UI Dynamics - iOS 9 Swift Programming Cookbook (2015)

iOS 9 Swift Programming Cookbook (2015)

Chapter 13. UI Dynamics

13.2 Creating a Linear Gravity Field on Your UI

Problem

You want to create gravity that follows a vector on your UI.

Solution

Use the linearGravityFieldWithVector(_:) class method of UIFieldBehavior to create your gravity. The parameter to this method is of type CGVector. You can provide your own x and y values for this vector when you construct it. This is now your gravity field and you can add it to an animator of type UIDynamicAnimator.

NOTE

I am basing this recipe on Recipe 13.1. There are some things, such as the bridging header to enable debugging, that I mentioned in Recipe 13.1 and won’t mention again in this recipe. I might skim over them but won’t go into details.

Discussion

Whereas the Recipe 13.1 has a center and a radius, a linear gravity has a direction only (up, down, right, left, etc.). In this example, we are going to have the exact same UI that we created in Recipe 13.1. So create the little orange view on your storyboard and link it to an orangeView outlet on your code. Add a pan gesture recognizer to it as well and add it to a method called panning(_:).

Right now, your view controller’s code should look like this:

import UIKit

import SharedCode

class ViewController: UIViewController {

@IBOutlet var orangeView: UIView!

lazy var animator: UIDynamicAnimator = {

let animator = UIDynamicAnimator(referenceView: self.view)

animator.debugEnabled = true

return animator

}()

lazy var collision: UICollisionBehavior = {

let collision = UICollisionBehavior(items: [self.orangeView])

collision.translatesReferenceBoundsIntoBoundary = true

return collision

}()

...

The next step is to create your linear gravity:

lazy var gravity: UIFieldBehavior = {

let vector = CGVector(dx: 0.4, dy: 1.0)

let gravity =

UIFieldBehavior.linearGravityFieldWithVector(vector)

gravity.addItem(self.orangeView)

return gravity

}()

Last but not least, handle the panning and add the effects to the animator (see Recipe 13.1):

override func viewDidLoad() {

super.viewDidLoad()

animator.addBehavior(collision)

animator.addBehavior(gravity)

}

@IBAction func panning(sender: UIPanGestureRecognizer) {

switch sender.state{

case .Began:

collision.removeItem(orangeView)

gravity.removeItem(orangeView)

case .Changed:

orangeView.center = sender.locationInView(view)

case .Ended, .Cancelled:

collision.addItem(orangeView)

gravity.addItem(orangeView)

default: ()

}

}

If you run your app now you should see an interface similar to Figure 13-4. Our linear gravity pulls all objects down and to the right. This is because in our vector earlier I specified a positive y-delta that pulls everything down and a positive x-delta that pulls everything to the right. I suggest that you play around with the delta values of type CGVector to get a feeling of how they affect gravity.

Figure 13-4. Linear gravity acting on an object

You can also go ahead and change some aspects of your gravity field. For instance, set the strength proprety of the gravity to 20 and see how much more gravity is applied to your objects. Similarly, play with the animationSpeed property of your gravity to set the animation speed.

See Also