Skip to content
This repository has been archived by the owner on Nov 21, 2017. It is now read-only.

Commit

Permalink
Added example showing some CoreAnimation properties animating
Browse files Browse the repository at this point in the history
Summary: Uses the runtime and the CoreAnimation family in a simple demo that bundles several CA animations into one transaction.

Reviewers: O4 Material Motion Apple platform reviewers, O2 Material Motion, featherless

Reviewed By: O4 Material Motion Apple platform reviewers, O2 Material Motion, featherless

Subscribers: featherless

Tags: #material_motion

Differential Revision: http://codereview.cc/D1406
  • Loading branch information
maxluzuriaga committed Aug 10, 2016
1 parent 5a035fa commit a6d9d82
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 1 deletion.
4 changes: 4 additions & 0 deletions examples/apps/Catalog/Catalog.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
66E620301D47D2340021B138 /* SchedulerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E6202F1D47D2340021B138 /* SchedulerDelegate.swift */; };
66FB71CE1FA2B5DC89A7883C /* Pods_MaterialMotionCoreAnimationFamily_UnitTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 443B77A9B48B8E8395819E7E /* Pods_MaterialMotionCoreAnimationFamily_UnitTests.framework */; };
C0BC54AF6152BCDAA9566B30 /* Pods_MaterialMotionCoreAnimationFamily_Catalog.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0B8148CD2D7965DD1699653 /* Pods_MaterialMotionCoreAnimationFamily_Catalog.framework */; };
D05136411D5122C800438C0F /* PopupMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05136401D5122C800438C0F /* PopupMenuViewController.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -41,6 +42,7 @@
66E6202F1D47D2340021B138 /* SchedulerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchedulerDelegate.swift; sourceTree = "<group>"; };
B2AEAB79F993F15CB0185C24 /* Pods-MaterialMotionCoreAnimationFamily-UnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MaterialMotionCoreAnimationFamily-UnitTests.debug.xcconfig"; path = "../../../Pods/Target Support Files/Pods-MaterialMotionCoreAnimationFamily-UnitTests/Pods-MaterialMotionCoreAnimationFamily-UnitTests.debug.xcconfig"; sourceTree = "<group>"; };
CCEEB5C473CA229BD2A79788 /* Pods-MaterialMotionCoreAnimationFamily-Catalog.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MaterialMotionCoreAnimationFamily-Catalog.release.xcconfig"; path = "../../../Pods/Target Support Files/Pods-MaterialMotionCoreAnimationFamily-Catalog/Pods-MaterialMotionCoreAnimationFamily-Catalog.release.xcconfig"; sourceTree = "<group>"; };
D05136401D5122C800438C0F /* PopupMenuViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PopupMenuViewController.swift; path = Catalog/PopupMenuViewController.swift; sourceTree = "<group>"; };
D0B8148CD2D7965DD1699653 /* Pods_MaterialMotionCoreAnimationFamily_Catalog.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MaterialMotionCoreAnimationFamily_Catalog.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F2DA13259D089A0F11B2ECB8 /* Pods-MaterialMotionCoreAnimationFamily-Catalog.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MaterialMotionCoreAnimationFamily-Catalog.debug.xcconfig"; path = "../../../Pods/Target Support Files/Pods-MaterialMotionCoreAnimationFamily-Catalog/Pods-MaterialMotionCoreAnimationFamily-Catalog.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -149,6 +151,7 @@
isa = PBXGroup;
children = (
666FAA831D384A6B000363DA /* AppDelegate.swift */,
D05136401D5122C800438C0F /* PopupMenuViewController.swift */,
);
name = catalog;
sourceTree = "<group>";
Expand Down Expand Up @@ -363,6 +366,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D05136411D5122C800438C0F /* PopupMenuViewController.swift in Sources */,
666FAA841D384A6B000363DA /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
2 changes: 1 addition & 1 deletion examples/apps/Catalog/Catalog/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let window = UIWindow(frame: UIScreen.main.bounds)
self.window = window
window.rootViewController = UINavigationController(rootViewController: UIViewController())
window.rootViewController = UINavigationController(rootViewController: PopupMenuViewController())
window.makeKeyAndVisible()
return true
}
Expand Down
174 changes: 174 additions & 0 deletions examples/apps/Catalog/Catalog/PopupMenuViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*
Copyright 2016-present The Material Motion Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import UIKit
import MaterialMotionRuntime
import MaterialMotionCoreAnimationFamily

let animDuration = 0.2
let distFromMainButton: CGFloat = 100.0
let angle1: Float = Float(M_PI) / 3.0
let angle2: Float = 0
let angle3: Float = -angle1

class PopupMenuViewController: UIViewController {

var mainBtn: UIView?
var additionalBtn1: CALayer?
var additionalBtn2: CALayer?
var additionalBtn3: CALayer?

var buttonsShowing: Bool = false

let scheduler = Scheduler()

override func viewDidLoad() {
super.viewDidLoad()

self.view.backgroundColor = UIColor.white()

let width = self.view.frame.width
let height = self.view.frame.height
mainBtn = UIView(frame: CGRect(x: width / 2 - 20, y: height - 70, width: 40, height: 40))
mainBtn?.backgroundColor = .orange()
mainBtn?.layer.cornerRadius = 20
mainBtn?.layer.shadowColor = UIColor.black().cgColor
mainBtn?.layer.shadowOffset = CGSize(width: 0, height: 2)
mainBtn?.layer.shadowOpacity = 0.3
mainBtn?.layer.shadowRadius = 5
self.view.addSubview(mainBtn!)

mainBtn?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap(gestureRecognizer:))))

additionalBtn1 = CALayer()
additionalBtn1?.bounds = mainBtn!.frame
additionalBtn1?.position = mainBtn!.layer.position
additionalBtn1?.cornerRadius = 20
additionalBtn1?.backgroundColor = UIColor.blue().cgColor
additionalBtn1?.opacity = 0
self.view.layer.insertSublayer(additionalBtn1!, below: mainBtn!.layer)

additionalBtn2 = CALayer()
additionalBtn2?.bounds = mainBtn!.frame
additionalBtn2?.position = mainBtn!.layer.position
additionalBtn2?.cornerRadius = 20
additionalBtn2?.backgroundColor = UIColor.blue().cgColor
additionalBtn2?.opacity = 0
self.view.layer.insertSublayer(additionalBtn2!, below: mainBtn!.layer)

additionalBtn3 = CALayer()
additionalBtn3?.bounds = mainBtn!.frame
additionalBtn3?.position = mainBtn!.layer.position
additionalBtn3?.cornerRadius = 20
additionalBtn3?.backgroundColor = UIColor.blue().cgColor
additionalBtn3?.opacity = 0
self.view.layer.insertSublayer(additionalBtn3!, below: mainBtn!.layer)
}

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

func handleTap(gestureRecognizer: UIGestureRecognizer) {
let bounceTimingFunction = CAMediaTimingFunction(controlPoints: 0.5, 1.6, 1, 1)

// Make main button smaller
let smallerBtn = CABasicAnimation(keyPath: "transform")

let initialTransform = CATransform3DIdentity
let endTransform = CATransform3DMakeScale(0.6, 0.6, 1.0)

smallerBtn.fromValue = NSValue(caTransform3D: buttonsShowing ? endTransform : initialTransform)
smallerBtn.toValue = NSValue(caTransform3D: buttonsShowing ? initialTransform : endTransform)
smallerBtn.duration = animDuration
smallerBtn.timingFunction = bounceTimingFunction

// Main button shadow smaller
let smallerShadow = CABasicAnimation(keyPath: "shadowRadius")

let initialRadius = 5
let endRadius = 2

smallerShadow.fromValue = NSNumber(value: buttonsShowing ? endRadius : initialRadius)
smallerShadow.toValue = NSNumber(value: buttonsShowing ? initialRadius : endRadius)
smallerShadow.duration = animDuration
smallerShadow.timingFunction = bounceTimingFunction

// Main button grey
let greyButton = CABasicAnimation(keyPath: "backgroundColor")

let initialColor: AnyObject = UIColor.orange().cgColor
let endColor: AnyObject = UIColor.lightGray().cgColor

greyButton.fromValue = buttonsShowing ? endColor : initialColor
greyButton.toValue = buttonsShowing ? initialColor : endColor
greyButton.duration = animDuration

// Move and fade buttons
let btn1Move = generateBtnMove(btn: additionalBtn1!, distance: distFromMainButton, angle: angle1, timing: bounceTimingFunction)
let btn1Fade = generateBtnFade(btn: additionalBtn1!)

let btn2Move = generateBtnMove(btn: additionalBtn2!, distance: distFromMainButton, angle: angle2, timing: bounceTimingFunction)
let btn2Fade = generateBtnFade(btn: additionalBtn2!)

let btn3Move = generateBtnMove(btn: additionalBtn3!, distance: distFromMainButton, angle: angle3, timing: bounceTimingFunction)
let btn3Fade = generateBtnFade(btn: additionalBtn3!)

let transaction = Transaction()
transaction.add(plan: smallerBtn, to: mainBtn!)
transaction.add(plan: greyButton, to: mainBtn!)
transaction.add(plan: smallerShadow, to: mainBtn!)
transaction.add(plan: btn1Move, to: additionalBtn1!)
transaction.add(plan: btn1Fade, to: additionalBtn1!)
transaction.add(plan: btn2Move, to: additionalBtn2!)
transaction.add(plan: btn2Fade, to: additionalBtn2!)
transaction.add(plan: btn3Move, to: additionalBtn3!)
transaction.add(plan: btn3Fade, to: additionalBtn3!)

scheduler.commit(transaction)
buttonsShowing = !buttonsShowing
}

func generateBtnMove(btn: CALayer, distance: CGFloat, angle: Float, timing: CAMediaTimingFunction) -> CABasicAnimation {
let move = CABasicAnimation(keyPath: "position")
let initialPos = mainBtn!.layer.position

let x = initialPos.x - CGFloat(sinf(angle)) * distance
let y = initialPos.y - CGFloat(cosf(angle)) * distance
let endPos = CGPoint(x: x, y: y)

move.fromValue = NSValue(cgPoint: buttonsShowing ? endPos : initialPos)
move.toValue = NSValue(cgPoint: buttonsShowing ? initialPos : endPos)
move.duration = animDuration
move.timingFunction = timing

return move
}

func generateBtnFade(btn: CALayer) -> CABasicAnimation {
let fade = CABasicAnimation(keyPath: "opacity")

let initialOpacity = NSNumber.init(value: 0.0)
let endOpacity = NSNumber.init(value: 1.0)

fade.fromValue = buttonsShowing ? endOpacity : initialOpacity
fade.toValue = buttonsShowing ? initialOpacity : endOpacity

return fade
}

}

0 comments on commit a6d9d82

Please sign in to comment.