2015年12月16日
Stanford CS193p第十一課 Unwind Segues, Alerts, Timers, View Animation. 第十二課 Dynamic Animation
Unwind
- Unwind Segue不會(huì)像其他Segue一樣創(chuàng)建一個(gè)新的MVC
Alerts/Action Sheets
- 如何添加Alerts/Action Sheets
1.創(chuàng)建button
2.調(diào)用UIAlertController
3.addAction
4.調(diào)用presentViewController顯示Alerts/Action Sheets
這次在之前CassiniDEMO中加入了Alerts和Action Sheets.
點(diǎn)進(jìn)Cassini后點(diǎn)擊"Redeploy"彈出Action Sheets.
在Action Sheets中"Orbit Saturn"欄中實(shí)現(xiàn)了點(diǎn)擊跳出Alerts的功能
具體代碼如下:
@IBOutlet weak var redeploy: UIBarButtonItem!
@IBAction func redeploy(sender: UIBarButtonItem) {
//創(chuàng)建actionSheet
let actionSheet = UIAlertController(title: "Redeploy", message: "Issue commands to Cassini'sguidance system.", preferredStyle: UIAlertControllerStyle.ActionSheet)
//添加Action
actionSheet.addAction(UIAlertAction(title: "Orbit Saturn", style: UIAlertActionStyle.Default, handler: { (action: UIAlertAction) -> Void in
//此處實(shí)現(xiàn)了,點(diǎn)擊Orbit Saturn后跳出Alert
let alert1 = UIAlertController(title: "Login Required", message: "Please enter your Cassini guidance system...", preferredStyle: UIAlertControllerStyle.Alert)//創(chuàng)建Alert
//添加Action
alert1.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
alert1.addAction(UIAlertAction(title: "Login", style: UIAlertActionStyle.Default, handler: nil))
//給Alert添加一個(gè)TextField
alert1.addTextFieldWithConfigurationHandler { (textField) in
textField.placeholder = "Guidance System Password"
}
//顯示TextField
self.presentViewController(alert1, animated: true, completion: nil)
}))
actionSheet.addAction(UIAlertAction(title: "Explore Titan", style: UIAlertActionStyle.Default, handler: nil))
actionSheet.addAction(UIAlertAction(title: "Closeup of Sun", style: UIAlertActionStyle.Destructive, handler: nil))
actionSheet.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
//以下三行代碼用于iPad已POPover的形式顯示ActionSheets.在iPhone上不需要
actionSheet.modalPresentationStyle = .Popover
let ppc = actionSheet.popoverPresentationController
ppc?.barButtonItem = redeploy
//顯示actionSheet
presentViewController(actionSheet, animated: true, completion: nil)
}
Animation
iOS中動(dòng)畫的分類
1.UIView Animation(視圖屬性的動(dòng)畫)
2.Animation of View Controller transitions(viewController轉(zhuǎn)場(chǎng)動(dòng)畫)
3.Core Animation
4.Dynamic Animation(基于物理引擎的動(dòng)畫)UIView Animation
在其中我們主要能夠使用三種屬性,分別為:frame(意味著可移動(dòng));transform(意味著可旋轉(zhuǎn));alpha(意味著可改變透明度)
-
使用:
class func animateWithDuration(durationL NSTimeInterval, delay: NSTimerInterval, options: UIViewAnimationOptions, animations: () -> Void, completion: ((finished: Bool) -> Void)?)
-
UIViewAnimationOptions
Dynamic Animation
如何使用Dynamic Animation
1.創(chuàng)建UIDynamicAnimator實(shí)例var animator = UIDynamicAnimator(referenceView: UIView)
2.添加UIDynamicBehaviors,如gravity,collisions等let gravity = UIGravityBehavior() animation.addBehavior(gravity)
3.添加UIDynamicItemlet item1: UIDynamicItem = ...// usually a UIView gravity.addItem(item1)
UIDynamicItem protocol
protocol UIDynamicItem {
var bounds: CGRect { get }
var center: CGRect { get set }
var transform: CGAffineTransform { get set } //用于旋轉(zhuǎn)
}
-
Behaviors
1.UIGravityBehavior有兩個(gè)重要屬性var angle: CGFloat //重力的角度 var magnitude: CGFloat //重力加速度
2.UIAttachmentBehavior
3.UICollisionBehavior碰撞效果
4.UISnapBehavior震蕩效果
5.UIPushBehavior把物體推向特定角度,速度恒定,可食一次性的效果,也可是持續(xù)效果
6.UIDynamicItemBehavior控制對(duì)象之間如何交互
DropitDEMO
import UIKit
class dropitViewController: UIViewController,UIDynamicAnimatorDelegate {
@IBOutlet weak var gameView: BezierPathsView!
//創(chuàng)建DynamicAnimator
lazy var animator: UIDynamicAnimator = {
let lazilyCreatedDynamicAnimator = UIDynamicAnimator(referenceView: self.gameView)
lazilyCreatedDynamicAnimator.delegate = self
return lazilyCreatedDynamicAnimator
}()
//創(chuàng)建集成了三個(gè)Behavior的DropBehavior的實(shí)例
var dropitBehavior = DropBehavior()
var attachment: UIAttachmentBehavior? {
willSet {
animator.removeBehavior(attachment!)
gameView.setPath(nil, named: PathNames.Attachment)
}
didSet {
if attachment != nil {
animator.addBehavior(attachment!)
attachment?.action = { [unowned self] in
if let attacheView = self.attachment?.items.first as? UIView {
let path = UIBezierPath()
path.moveToPoint(self.attachment!.anchorPoint)
path.addLineToPoint(attacheView.center)
self.gameView.setPath(path, named: PathNames.Attachment)
}
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
animator.addBehavior(dropitBehavior)
}
struct PathNames {
static let MiddleBarrier = "Middle Barrier"
static let Attachment = "Attachment"
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let barrierSize = dropSize
let barrierOrigin = CGPoint(x: gameView.bounds.midX - barrierSize.width / 2, y: gameView.bounds.midY - barrierSize.height / 2)
//設(shè)置圓圈的邊界
let path = UIBezierPath(ovalInRect: CGRect(origin: barrierOrigin, size: barrierSize))
dropitBehavior.addBarrier(path, named: PathNames.MiddleBarrier)
gameView.setPath(path, named: PathNames.MiddleBarrier)
}
//UIDynamicAnimatorDelegate中的方法,當(dāng)動(dòng)畫停止時(shí)
func dynamicAnimatorDidPause(animator: UIDynamicAnimator) {
removeCompletedRow()
}
var dropsPerRow = 10
//設(shè)置方塊的形狀
var dropSize: CGSize {
let size = gameView.bounds.width / CGFloat(dropsPerRow)
return CGSize(width: size, height: size)
}
//設(shè)置手勢(shì)
@IBAction func drop(sender: UITapGestureRecognizer) {
drop()
}
var lastDroppedView: UIView?
//掉落方法
func drop() {
//設(shè)置方塊的初始位置及大小
var frame = CGRect(origin: CGPointZero, size: dropSize)
frame.origin.x = CGFloat.random(dropsPerRow) * dropSize.width
//創(chuàng)建方塊視圖,并設(shè)置其顏色
let dropView = UIView(frame: frame)
dropView.backgroundColor = UIColor.random
lastDroppedView = dropView
dropitBehavior.addDrop(dropView)
}
@IBAction func grabDrop(sender: UIPanGestureRecognizer) {
let gesturePoint = sender.locationInView(gameView)
switch sender.state {
case .Began:
if let viewToAttachTo = lastDroppedView {
attachment = UIAttachmentBehavior(item: viewToAttachTo, attachedToAnchor: gesturePoint)
lastDroppedView = nil
}
case .Changed:
attachment?.anchorPoint = gesturePoint
case .Ended:
attachment = nil
default: break
}
}
//當(dāng)滿行后消除方塊
func removeCompletedRow() {
var dropsToRemove = [UIView]()
var dropFrame = CGRect(x: 0, y: gameView.frame.maxY, width: dropSize.width, height: dropSize.height)
repeat {
dropFrame.origin.y -= dropSize.height
dropFrame.origin.x = 0
var dropsFound = [UIView]()
var rowIsComplete = true
for _ in 0 ..< dropsPerRow {
if let hitView = gameView.hitTest(CGPoint(x: dropFrame.midX, y: dropFrame.midY), withEvent: nil) {
if hitView.superview == gameView {
dropsFound.append(hitView)
} else {
rowIsComplete = false
}
}
dropFrame.origin.x += dropSize.width }
if rowIsComplete {
dropsToRemove += dropsFound
}
} while dropsToRemove.count == 0 && dropFrame.origin.y > 0
for drop in dropsToRemove {
dropitBehavior.removeDrop(drop)
}
}
}
private extension CGFloat {
static func random(max:Int) -> CGFloat {
return CGFloat(arc4random() % UInt32(max))
}
}
private extension UIColor {
class var random:UIColor {
switch arc4random() % 5 {
case 0: return UIColor.greenColor()
case 1: return UIColor.blueColor()
case 2: return UIColor.orangeColor()
case 3: return UIColor.redColor()
case 4: return UIColor.purpleColor()
default: return UIColor.blackColor()
}
}
}
import UIKit
class dropitViewController: UIViewController,UIDynamicAnimatorDelegate {
@IBOutlet weak var gameView: BezierPathsView!
//創(chuàng)建DynamicAnimator
lazy var animator: UIDynamicAnimator = {
let lazilyCreatedDynamicAnimator = UIDynamicAnimator(referenceView: self.gameView)
lazilyCreatedDynamicAnimator.delegate = self
return lazilyCreatedDynamicAnimator
}()
//創(chuàng)建集成了三個(gè)Behavior的DropBehavior的實(shí)例
var dropitBehavior = DropBehavior()
var attachment: UIAttachmentBehavior? {
willSet {
animator.removeBehavior(attachment!)
gameView.setPath(nil, named: PathNames.Attachment)
}
didSet {
if attachment != nil {
animator.addBehavior(attachment!)
attachment?.action = { [unowned self] in
if let attacheView = self.attachment?.items.first as? UIView {
let path = UIBezierPath()
path.moveToPoint(self.attachment!.anchorPoint)
path.addLineToPoint(attacheView.center)
self.gameView.setPath(path, named: PathNames.Attachment)
}
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
animator.addBehavior(dropitBehavior)
}
struct PathNames {
static let MiddleBarrier = "Middle Barrier"
static let Attachment = "Attachment"
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let barrierSize = dropSize
let barrierOrigin = CGPoint(x: gameView.bounds.midX - barrierSize.width / 2, y: gameView.bounds.midY - barrierSize.height / 2)
//設(shè)置圓圈的邊界
let path = UIBezierPath(ovalInRect: CGRect(origin: barrierOrigin, size: barrierSize))
dropitBehavior.addBarrier(path, named: PathNames.MiddleBarrier)
gameView.setPath(path, named: PathNames.MiddleBarrier)
}
//UIDynamicAnimatorDelegate中的方法,當(dāng)動(dòng)畫停止時(shí)
func dynamicAnimatorDidPause(animator: UIDynamicAnimator) {
removeCompletedRow()
}
var dropsPerRow = 10
//設(shè)置方塊的形狀
var dropSize: CGSize {
let size = gameView.bounds.width / CGFloat(dropsPerRow)
return CGSize(width: size, height: size)
}
//設(shè)置手勢(shì)
@IBAction func drop(sender: UITapGestureRecognizer) {
drop()
}
var lastDroppedView: UIView?
//掉落方法
func drop() {
//設(shè)置方塊的初始位置及大小
var frame = CGRect(origin: CGPointZero, size: dropSize)
frame.origin.x = CGFloat.random(dropsPerRow) * dropSize.width
//創(chuàng)建方塊視圖,并設(shè)置其顏色
let dropView = UIView(frame: frame)
dropView.backgroundColor = UIColor.random
lastDroppedView = dropView
dropitBehavior.addDrop(dropView)
}
@IBAction func grabDrop(sender: UIPanGestureRecognizer) {
let gesturePoint = sender.locationInView(gameView)
switch sender.state {
case .Began:
if let viewToAttachTo = lastDroppedView {
attachment = UIAttachmentBehavior(item: viewToAttachTo, attachedToAnchor: gesturePoint)
lastDroppedView = nil
}
case .Changed:
attachment?.anchorPoint = gesturePoint
case .Ended:
attachment = nil
default: break
}
}
//當(dāng)滿行后消除方塊
func removeCompletedRow() {
var dropsToRemove = [UIView]()
var dropFrame = CGRect(x: 0, y: gameView.frame.maxY, width: dropSize.width, height: dropSize.height)
repeat {
dropFrame.origin.y -= dropSize.height
dropFrame.origin.x = 0
var dropsFound = [UIView]()
var rowIsComplete = true
for _ in 0 ..< dropsPerRow {
if let hitView = gameView.hitTest(CGPoint(x: dropFrame.midX, y: dropFrame.midY), withEvent: nil) {
if hitView.superview == gameView {
dropsFound.append(hitView)
} else {
rowIsComplete = false
}
}
dropFrame.origin.x += dropSize.width }
if rowIsComplete {
dropsToRemove += dropsFound
}
} while dropsToRemove.count == 0 && dropFrame.origin.y > 0
for drop in dropsToRemove {
dropitBehavior.removeDrop(drop)
}
}
}
private extension CGFloat {
static func random(max:Int) -> CGFloat {
return CGFloat(arc4random() % UInt32(max))
}
}
private extension UIColor {
class var random:UIColor {
switch arc4random() % 5 {
case 0: return UIColor.greenColor()
case 1: return UIColor.blueColor()
case 2: return UIColor.orangeColor()
case 3: return UIColor.redColor()
case 4: return UIColor.purpleColor()
default: return UIColor.blackColor()
}
}
}
import UIKit
class BezierPathsView: UIView {
private var bezierPath = [String: UIBezierPath]()
func setPath(path: UIBezierPath?, named name: String) {
bezierPath[name] = path
setNeedsDisplay()
}
override func drawRect(rect: CGRect) {
for (_,path) in bezierPath {
path.stroke()
}
}
}