Commit 10002a2c by Daniel Dahan

added Menu component

parent e57b5c3d
...@@ -58,9 +58,9 @@ ...@@ -58,9 +58,9 @@
</Group> </Group>
<Group <Group
location = "container:" location = "container:"
name = "MenuLayout"> name = "Menu">
<FileRef <FileRef
location = "group:Programmatic/MenuLayout/MenuLayout.xcodeproj"> location = "group:Programmatic/Menu/Menu.xcodeproj">
</FileRef> </FileRef>
</Group> </Group>
<Group <Group
......
...@@ -7,8 +7,6 @@ ...@@ -7,8 +7,6 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
960CB2381C64017500EE010C /* Material.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 960CB2371C64017500EE010C /* Material.framework */; };
960CB2391C64017500EE010C /* Material.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 960CB2371C64017500EE010C /* Material.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
965E8E721C14A4950035A270 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965E8E711C14A4950035A270 /* AppDelegate.swift */; }; 965E8E721C14A4950035A270 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965E8E711C14A4950035A270 /* AppDelegate.swift */; };
965E8E741C14A4950035A270 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965E8E731C14A4950035A270 /* ViewController.swift */; }; 965E8E741C14A4950035A270 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965E8E731C14A4950035A270 /* ViewController.swift */; };
965E8E791C14A4950035A270 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 965E8E781C14A4950035A270 /* Assets.xcassets */; }; 965E8E791C14A4950035A270 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 965E8E781C14A4950035A270 /* Assets.xcassets */; };
...@@ -22,7 +20,6 @@ ...@@ -22,7 +20,6 @@
dstPath = ""; dstPath = "";
dstSubfolderSpec = 10; dstSubfolderSpec = 10;
files = ( files = (
960CB2391C64017500EE010C /* Material.framework in Embed Frameworks */,
); );
name = "Embed Frameworks"; name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
...@@ -30,7 +27,6 @@ ...@@ -30,7 +27,6 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
960CB2371C64017500EE010C /* Material.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; name = Material.framework; path = "/Users/danieldahan/Library/Developer/Xcode/DerivedData/Material-hbpnflxhoouqxebjcyhbbhqyesjd/Build/Products/Debug-iphoneos/Material.framework"; sourceTree = "<absolute>"; };
965E8E6E1C14A4950035A270 /* MaterialButton.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MaterialButton.app; sourceTree = BUILT_PRODUCTS_DIR; }; 965E8E6E1C14A4950035A270 /* MaterialButton.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MaterialButton.app; sourceTree = BUILT_PRODUCTS_DIR; };
965E8E711C14A4950035A270 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 965E8E711C14A4950035A270 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
965E8E731C14A4950035A270 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; }; 965E8E731C14A4950035A270 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
...@@ -44,7 +40,6 @@ ...@@ -44,7 +40,6 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
960CB2381C64017500EE010C /* Material.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
...@@ -54,7 +49,6 @@ ...@@ -54,7 +49,6 @@
965E8E651C14A4950035A270 = { 965E8E651C14A4950035A270 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
960CB2371C64017500EE010C /* Material.framework */,
965E8E701C14A4950035A270 /* MaterialButton */, 965E8E701C14A4950035A270 /* MaterialButton */,
965E8E6F1C14A4950035A270 /* Products */, 965E8E6F1C14A4950035A270 /* Products */,
); );
......
...@@ -2,6 +2,6 @@ ...@@ -2,6 +2,6 @@
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "self:MenuLayout.xcodeproj"> location = "self:Menu.xcodeproj">
</FileRef> </FileRef>
</Workspace> </Workspace>
...@@ -36,12 +36,12 @@ import UIKit ...@@ -36,12 +36,12 @@ import UIKit
import Material import Material
class ViewController: UIViewController { class ViewController: UIViewController {
private var menuLayout: MenuLayout! private var menu: Menu!
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
prepareView() prepareView()
prepareMenuLayoutExample() prepareMenuExample()
} }
override func viewWillLayoutSubviews() { override func viewWillLayoutSubviews() {
...@@ -50,18 +50,18 @@ class ViewController: UIViewController { ...@@ -50,18 +50,18 @@ class ViewController: UIViewController {
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
menuLayout.width = size.width // menuLayout.origin.x = size.width
menuLayout.height = size.height // menuLayout.origin.y = size.height
menuLayout.reloadLayout() menu.reloadLayout()
} }
internal func handleOpenMenuLayout() { internal func handleOpenMenu() {
if menuLayout.opened { if menu.opened {
menuLayout.close() menu.close()
} else { } else {
// (menuLayout.items?.first?.button as? MaterialButton)?.animate(MaterialAnimation.rotate(1)) // (menuLayout.items?.first?.button as? MaterialButton)?.animate(MaterialAnimation.rotate(1))
menuLayout.open() { (item: MenuLayoutItem) in menu.open() { (button: UIButton) in
(item.button as? MaterialButton)?.pulse() (button as? MaterialButton)?.pulse()
} }
} }
} }
...@@ -71,18 +71,14 @@ class ViewController: UIViewController { ...@@ -71,18 +71,14 @@ class ViewController: UIViewController {
view.backgroundColor = MaterialColor.white view.backgroundColor = MaterialColor.white
} }
/// Prepares the MenuLayout example. /// Prepares the Menu example.
private func prepareMenuLayoutExample() { private func prepareMenuExample() {
// let btn: FlatButton = FlatButton(frame: CGRectMake(100, 100, 100, 100))
// btn.backgroundColor = MaterialColor.red.base
// view.addSubview(btn)
let image: UIImage? = UIImage(named: "ic_add_white") let image: UIImage? = UIImage(named: "ic_add_white")
let btn1: FabButton = FabButton() let btn1: FabButton = FabButton()
btn1.depth = .Depth1 btn1.depth = .Depth1
btn1.setImage(image, forState: .Normal) btn1.setImage(image, forState: .Normal)
btn1.setImage(image, forState: .Highlighted) btn1.setImage(image, forState: .Highlighted)
btn1.addTarget(self, action: "handleOpenMenuLayout", forControlEvents: .TouchUpInside) btn1.addTarget(self, action: "handleOpenMenu", forControlEvents: .TouchUpInside)
view.addSubview(btn1) view.addSubview(btn1)
let btn2: FabButton = FabButton() let btn2: FabButton = FabButton()
...@@ -106,16 +102,10 @@ class ViewController: UIViewController { ...@@ -106,16 +102,10 @@ class ViewController: UIViewController {
btn4.setImage(image, forState: .Highlighted) btn4.setImage(image, forState: .Highlighted)
view.addSubview(btn4) view.addSubview(btn4)
menuLayout = MenuLayout() menu = Menu(origin: CGPointMake(100, 100))
menuLayout.baseSize = CGSizeMake(56, 56) menu.direction = .Down
menuLayout.itemSize = CGSizeMake(48, 48) menu.baseSize = CGSizeMake(88, 88)
menu.buttons = [btn1, btn2, btn3, btn4]
menuLayout.items = [
MenuLayoutItem(button: btn1),
MenuLayoutItem(button: btn2),
MenuLayoutItem(button: btn3),
MenuLayoutItem(button: btn4)
]
} }
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
65FDC2EB1C66858A00103AC2 /* MenuLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65FDC2EA1C66858A00103AC2 /* MenuLayout.swift */; }; 65FDC2EB1C66858A00103AC2 /* Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65FDC2EA1C66858A00103AC2 /* Menu.swift */; };
960B23271C383E5500E96216 /* Material+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960B23261C383E5500E96216 /* Material+String.swift */; }; 960B23271C383E5500E96216 /* Material+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960B23261C383E5500E96216 /* Material+String.swift */; };
960B232E1C383EAA00E96216 /* Material+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960B23281C383EAA00E96216 /* Material+UIImage.swift */; }; 960B232E1C383EAA00E96216 /* Material+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960B23281C383EAA00E96216 /* Material+UIImage.swift */; };
960B232F1C383EAA00E96216 /* Material+UIImage+Crop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960B23291C383EAA00E96216 /* Material+UIImage+Crop.swift */; }; 960B232F1C383EAA00E96216 /* Material+UIImage+Crop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 960B23291C383EAA00E96216 /* Material+UIImage+Crop.swift */; };
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
96442ADB1C28EEFA00C3C574 /* TextField.swift in Headers */ = {isa = PBXBuildFile; fileRef = 966F57B71C226D75009185B7 /* TextField.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 96442ADB1C28EEFA00C3C574 /* TextField.swift in Headers */ = {isa = PBXBuildFile; fileRef = 966F57B71C226D75009185B7 /* TextField.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96442ADE1C28EF3700C3C574 /* MaterialTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96442ADD1C28EF3700C3C574 /* MaterialTableViewCell.swift */; }; 96442ADE1C28EF3700C3C574 /* MaterialTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96442ADD1C28EF3700C3C574 /* MaterialTableViewCell.swift */; };
96442ADF1C28EF3E00C3C574 /* MaterialTableViewCell.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96442ADD1C28EF3700C3C574 /* MaterialTableViewCell.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 96442ADF1C28EF3E00C3C574 /* MaterialTableViewCell.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96442ADD1C28EF3700C3C574 /* MaterialTableViewCell.swift */; settings = {ATTRIBUTES = (Public, ); }; };
965C588C1C698C0F00CFB4E1 /* MaterialDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 965C588B1C698C0F00CFB4E1 /* MaterialDirection.swift */; };
966F57B81C226D75009185B7 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 966F57B71C226D75009185B7 /* TextField.swift */; }; 966F57B81C226D75009185B7 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 966F57B71C226D75009185B7 /* TextField.swift */; };
96D88C1E1C1328D800B91418 /* CaptureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D88BF51C1328D800B91418 /* CaptureView.swift */; }; 96D88C1E1C1328D800B91418 /* CaptureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D88BF51C1328D800B91418 /* CaptureView.swift */; };
96D88C1F1C1328D800B91418 /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D88BF61C1328D800B91418 /* CardView.swift */; }; 96D88C1F1C1328D800B91418 /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D88BF61C1328D800B91418 /* CardView.swift */; };
...@@ -115,7 +116,7 @@ ...@@ -115,7 +116,7 @@
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
65FDC2EA1C66858A00103AC2 /* MenuLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuLayout.swift; sourceTree = "<group>"; }; 65FDC2EA1C66858A00103AC2 /* Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Menu.swift; sourceTree = "<group>"; };
960B23261C383E5500E96216 /* Material+String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+String.swift"; sourceTree = "<group>"; }; 960B23261C383E5500E96216 /* Material+String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+String.swift"; sourceTree = "<group>"; };
960B23281C383EAA00E96216 /* Material+UIImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIImage.swift"; sourceTree = "<group>"; }; 960B23281C383EAA00E96216 /* Material+UIImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIImage.swift"; sourceTree = "<group>"; };
960B23291C383EAA00E96216 /* Material+UIImage+Crop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIImage+Crop.swift"; sourceTree = "<group>"; }; 960B23291C383EAA00E96216 /* Material+UIImage+Crop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Material+UIImage+Crop.swift"; sourceTree = "<group>"; };
...@@ -130,6 +131,7 @@ ...@@ -130,6 +131,7 @@
963832411B88DFD80015F710 /* Material.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Material.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 963832411B88DFD80015F710 /* Material.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Material.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
963832591B88E31A0015F710 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 963832591B88E31A0015F710 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
96442ADD1C28EF3700C3C574 /* MaterialTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaterialTableViewCell.swift; sourceTree = "<group>"; }; 96442ADD1C28EF3700C3C574 /* MaterialTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaterialTableViewCell.swift; sourceTree = "<group>"; };
965C588B1C698C0F00CFB4E1 /* MaterialDirection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaterialDirection.swift; sourceTree = "<group>"; };
966F57B71C226D75009185B7 /* TextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; }; 966F57B71C226D75009185B7 /* TextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; };
96D88BF51C1328D800B91418 /* CaptureView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaptureView.swift; sourceTree = "<group>"; }; 96D88BF51C1328D800B91418 /* CaptureView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaptureView.swift; sourceTree = "<group>"; };
96D88BF61C1328D800B91418 /* CardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = "<group>"; }; 96D88BF61C1328D800B91418 /* CardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = "<group>"; };
...@@ -303,6 +305,7 @@ ...@@ -303,6 +305,7 @@
96D88C041C1328D800B91418 /* MaterialDepth.swift */, 96D88C041C1328D800B91418 /* MaterialDepth.swift */,
96D88C061C1328D800B91418 /* MaterialGravity.swift */, 96D88C061C1328D800B91418 /* MaterialGravity.swift */,
96D88C071C1328D800B91418 /* MaterialEdgeInsetPreset.swift */, 96D88C071C1328D800B91418 /* MaterialEdgeInsetPreset.swift */,
965C588B1C698C0F00CFB4E1 /* MaterialDirection.swift */,
); );
name = Type; name = Type;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -391,7 +394,7 @@ ...@@ -391,7 +394,7 @@
96D88C541C132A7700B91418 /* Navigation */ = { 96D88C541C132A7700B91418 /* Navigation */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
65FDC2EA1C66858A00103AC2 /* MenuLayout.swift */, 65FDC2EA1C66858A00103AC2 /* Menu.swift */,
96D88C151C1328D800B91418 /* NavigationBarView.swift */, 96D88C151C1328D800B91418 /* NavigationBarView.swift */,
96D88C1D1C1328D800B91418 /* SideNavigationViewController.swift */, 96D88C1D1C1328D800B91418 /* SideNavigationViewController.swift */,
); );
...@@ -585,7 +588,8 @@ ...@@ -585,7 +588,8 @@
96D88C3E1C1328D800B91418 /* NavigationBarView.swift in Sources */, 96D88C3E1C1328D800B91418 /* NavigationBarView.swift in Sources */,
96D88C221C1328D800B91418 /* FabButton.swift in Sources */, 96D88C221C1328D800B91418 /* FabButton.swift in Sources */,
96D88C3F1C1328D800B91418 /* RaisedButton.swift in Sources */, 96D88C3F1C1328D800B91418 /* RaisedButton.swift in Sources */,
65FDC2EB1C66858A00103AC2 /* MenuLayout.swift in Sources */, 65FDC2EB1C66858A00103AC2 /* Menu.swift in Sources */,
965C588C1C698C0F00CFB4E1 /* MaterialDirection.swift in Sources */,
960B23311C383EAA00E96216 /* Material+UIImage+PhotoLibrary.swift in Sources */, 960B23311C383EAA00E96216 /* Material+UIImage+PhotoLibrary.swift in Sources */,
960B23321C383EAA00E96216 /* Material+UIImage+Resize.swift in Sources */, 960B23321C383EAA00E96216 /* Material+UIImage+Resize.swift in Sources */,
96D88C3C1C1328D800B91418 /* MaterialTransitionAnimation.swift in Sources */, 96D88C3C1C1328D800B91418 /* MaterialTransitionAnimation.swift in Sources */,
......
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.io>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Material nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
public enum MaterialDirection {
case Up
case Down
case Left
case Right
}
/*
* Copyright (C) 2015 - 20spacing, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.io>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Material nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import UIKit
public class Menu {
/// The rectangular bounds that the menu animates.
public var origin: CGPoint
/// The space between buttons.
public var spacing: CGFloat
/// A Boolean that indicates if the menu is open or not.
public private(set) var opened: Bool = false
/// Animation duration.
public var duration: Double = 0.07
/// The direction in which the animation opens the menu.
public var direction: MaterialDirection = .Up
/// An Array of UIButtons.
public var buttons: Array<UIButton>? {
didSet {
reloadLayout()
}
}
/// Size of buttons, not including the first button.
public var buttonSize: CGSize = CGSizeMake(48, 48)
/// An Optional base button size.
public var baseSize: CGSize?
public init(origin: CGPoint, spacing: CGFloat = 16) {
self.origin = origin
self.spacing = spacing
}
public func reloadLayout() {
opened = false
layoutButtons()
}
public func open(completion: ((UIButton) -> Void)? = nil) {
switch direction {
case .Up:
openUpAnimation(completion)
case .Down:
openDownAnimation(completion)
case .Left:
openLeftAnimation(completion)
case .Right:
openRightAnimation(completion)
}
}
public func close(completion: ((UIButton) -> Void)? = nil) {
switch direction {
case .Up:
closeUpAnimation(completion)
case .Down:
closeDownAnimation(completion)
case .Left:
closeLeftAnimation(completion)
case .Right:
closeRightAnimation(completion)
}
}
private func openUpAnimation(completion: ((UIButton) -> Void)? = nil) {
if let v: Array<UIButton> = buttons {
var base: UIButton?
for var i: Int = 1, l: Int = v.count; i < l; ++i {
if nil == base {
base = v[0]
}
let button: UIButton = v[i]
button.hidden = false
UIView.animateWithDuration(Double(i) * duration,
animations: { [unowned self] in
button.alpha = 1
button.frame.origin.y = base!.frame.origin.y - CGFloat(i) * self.buttonSize.height - CGFloat(i) * self.spacing
},
completion: { _ in
completion?(button)
})
}
opened = true
}
}
public func closeUpAnimation(completion: ((UIButton) -> Void)? = nil) {
if let v: Array<UIButton> = buttons {
for var i: Int = 1, l: Int = v.count; i < l; ++i {
let button: UIButton = v[i]
UIView.animateWithDuration(Double(i) * duration,
animations: { [unowned self] in
button.alpha = 0
button.frame.origin.y = self.origin.y
},
completion: { _ in
button.hidden = true
completion?(button)
})
}
opened = false
}
}
private func openDownAnimation(completion: ((UIButton) -> Void)? = nil) {
if let v: Array<UIButton> = buttons {
var base: UIButton?
for var i: Int = 1, l: Int = v.count; i < l; ++i {
if nil == base {
base = v[0]
}
let button: UIButton = v[i]
button.hidden = false
let h: CGFloat = nil == baseSize ? buttonSize.height : baseSize!.height
UIView.animateWithDuration(Double(i) * duration,
animations: { [unowned self] in
button.alpha = 1
button.frame.origin.y = base!.frame.origin.y + h + CGFloat(i - 1) * self.buttonSize.height + CGFloat(i) * self.spacing
},
completion: { _ in
completion?(button)
})
}
opened = true
}
}
public func closeDownAnimation(completion: ((UIButton) -> Void)? = nil) {
if let v: Array<UIButton> = buttons {
for var i: Int = 1, l: Int = v.count; i < l; ++i {
let button: UIButton = v[i]
let h: CGFloat = nil == baseSize ? buttonSize.height : baseSize!.height
UIView.animateWithDuration(Double(i) * duration,
animations: {
button.alpha = 0
button.frame.origin.y = self.origin.y + h
},
completion: { _ in
button.hidden = true
completion?(button)
})
}
opened = false
}
}
private func openLeftAnimation(completion: ((UIButton) -> Void)? = nil) {
if let v: Array<UIButton> = buttons {
var base: UIButton?
for var i: Int = 1, l: Int = v.count; i < l; ++i {
if nil == base {
base = v[0]
}
let button: UIButton = v[i]
button.hidden = false
UIView.animateWithDuration(Double(i) * duration,
animations: { [unowned self] in
button.alpha = 1
button.frame.origin.x = base!.frame.origin.x - CGFloat(i) * self.buttonSize.width - CGFloat(i) * self.spacing
},
completion: { _ in
completion?(button)
})
}
opened = true
}
}
public func closeLeftAnimation(completion: ((UIButton) -> Void)? = nil) {
if let v: Array<UIButton> = buttons {
for var i: Int = 1, l: Int = v.count; i < l; ++i {
let button: UIButton = v[i]
UIView.animateWithDuration(Double(i) * duration,
animations: { [unowned self] in
button.alpha = 0
button.frame.origin.x = self.origin.x
},
completion: { _ in
button.hidden = true
completion?(button)
})
}
opened = false
}
}
private func openRightAnimation(completion: ((UIButton) -> Void)? = nil) {
if let v: Array<UIButton> = buttons {
var base: UIButton?
for var i: Int = 1, l: Int = v.count; i < l; ++i {
if nil == base {
base = v[0]
}
let button: UIButton = v[i]
button.hidden = false
let h: CGFloat = nil == baseSize ? buttonSize.height : baseSize!.height
UIView.animateWithDuration(Double(i) * duration,
animations: { [unowned self] in
button.alpha = 1
button.frame.origin.x = base!.frame.origin.x + h + CGFloat(i - 1) * self.buttonSize.width + CGFloat(i) * self.spacing
},
completion: { _ in
completion?(button)
})
}
opened = true
}
}
public func closeRightAnimation(completion: ((UIButton) -> Void)? = nil) {
if let v: Array<UIButton> = buttons {
for var i: Int = 1, l: Int = v.count; i < l; ++i {
let button: UIButton = v[i]
let w: CGFloat = nil == baseSize ? buttonSize.width : baseSize!.width
UIView.animateWithDuration(Double(i) * duration,
animations: {
button.alpha = 0
button.frame.origin.x = self.origin.x + w
},
completion: { _ in
button.hidden = true
completion?(button)
})
}
opened = false
}
}
private func layoutButtons() {
if let v: Array<UIButton> = buttons {
let size: CGSize = nil == baseSize ? buttonSize : baseSize!
for var i: Int = 0, l: Int = v.count; i < l; ++i {
let button: UIButton = v[i]
if 0 == i {
button.frame.size = size
button.frame.origin = origin
button.layer.zPosition = 10000
} else {
button.alpha = 0
button.hidden = true
button.frame.size = buttonSize
button.frame.origin.x = origin.x + (size.width - buttonSize.width) / 2
button.frame.origin.y = origin.y + (size.height - buttonSize.height) / 2
button.layer.zPosition = CGFloat(10000 - i)
}
}
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment