Commit 0bfdd805 by Daniel Dahan

development: added Menu container and working open and close handler

parent ee348867
......@@ -103,7 +103,6 @@
965E810C1DD4D5C800D61E4B /* DynamicFontType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9628645E1D540AF300690B69 /* DynamicFontType.swift */; };
965E810D1DD4D5C800D61E4B /* Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB78E1CB40DC500C806FE /* Menu.swift */; };
965E810E1DD4D5C800D61E4B /* FABMenuItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9697F7B61D8F22A4004741EC /* FABMenuItem.swift */; };
965E810F1DD4D5C800D61E4B /* MenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB78F1CB40DC500C806FE /* MenuController.swift */; };
965E81101DD4D5C800D61E4B /* NavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7901CB40DC500C806FE /* NavigationBar.swift */; };
965E81111DD4D5C800D61E4B /* NavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7911CB40DC500C806FE /* NavigationController.swift */; };
965E81121DD4D5C800D61E4B /* NavigationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BCB7921CB40DC500C806FE /* NavigationItem.swift */; };
......@@ -182,7 +181,6 @@
96BCB83C1CB4115200C806FE /* Bar.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7981CB40DC500C806FE /* Bar.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96BCB83D1CB4115200C806FE /* RootController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7991CB40DC500C806FE /* RootController.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96BCB83F1CB4115200C806FE /* Menu.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB78E1CB40DC500C806FE /* Menu.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96BCB8401CB4115200C806FE /* MenuController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB78F1CB40DC500C806FE /* MenuController.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96BCB8441CB4115200C806FE /* BottomNavigationController.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7581CB40DC500C806FE /* BottomNavigationController.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96BCB8451CB4115200C806FE /* BottomTabBar.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7591CB40DC500C806FE /* BottomTabBar.swift */; settings = {ATTRIBUTES = (Public, ); }; };
96BCB8461CB4115200C806FE /* NavigationBar.swift in Headers */ = {isa = PBXBuildFile; fileRef = 96BCB7901CB40DC500C806FE /* NavigationBar.swift */; settings = {ATTRIBUTES = (Public, ); }; };
......@@ -310,7 +308,6 @@
96BCB78B1CB40DC500C806FE /* TransitionMotion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransitionMotion.swift; sourceTree = "<group>"; };
96BCB78C1CB40DC500C806FE /* View.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = "<group>"; };
96BCB78E1CB40DC500C806FE /* Menu.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = Menu.swift; sourceTree = "<group>"; tabWidth = 4; };
96BCB78F1CB40DC500C806FE /* MenuController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MenuController.swift; sourceTree = "<group>"; };
96BCB7901CB40DC500C806FE /* NavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationBar.swift; sourceTree = "<group>"; };
96BCB7911CB40DC500C806FE /* NavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationController.swift; sourceTree = "<group>"; };
96BCB7921CB40DC500C806FE /* NavigationItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationItem.swift; sourceTree = "<group>"; };
......@@ -552,7 +549,6 @@
children = (
96BCB78E1CB40DC500C806FE /* Menu.swift */,
9617304B1E11931400A9A297 /* MenuItem.swift */,
96BCB78F1CB40DC500C806FE /* MenuController.swift */,
96A183621E0C6CE200083C30 /* FABMenu.swift */,
9697F7B61D8F22A4004741EC /* FABMenuItem.swift */,
96A183641E0C6DD400083C30 /* FABMenuController.swift */,
......@@ -904,7 +900,6 @@
96BCB83C1CB4115200C806FE /* Bar.swift in Headers */,
96BCB83D1CB4115200C806FE /* RootController.swift in Headers */,
96BCB83F1CB4115200C806FE /* Menu.swift in Headers */,
96BCB8401CB4115200C806FE /* MenuController.swift in Headers */,
96BCB8441CB4115200C806FE /* BottomNavigationController.swift in Headers */,
96BCB8451CB4115200C806FE /* BottomTabBar.swift in Headers */,
96BCB8461CB4115200C806FE /* NavigationBar.swift in Headers */,
......@@ -1176,7 +1171,6 @@
965E810C1DD4D5C800D61E4B /* DynamicFontType.swift in Sources */,
965E810D1DD4D5C800D61E4B /* Menu.swift in Sources */,
965E810E1DD4D5C800D61E4B /* FABMenuItem.swift in Sources */,
965E810F1DD4D5C800D61E4B /* MenuController.swift in Sources */,
96A183651E0C6DD400083C30 /* FABMenuController.swift in Sources */,
965E81101DD4D5C800D61E4B /* NavigationBar.swift in Sources */,
965E81111DD4D5C800D61E4B /* NavigationController.swift in Sources */,
......
......@@ -255,9 +255,11 @@ open class Card: PulseView {
self.contentView = contentView
self.bottomBar = bottomBar
}
}
extension Card {
/// Prepares the container.
private func prepareContainer() {
fileprivate func prepareContainer() {
container.clipsToBounds = true
addSubview(container)
}
......
......@@ -82,7 +82,7 @@ public protocol MenuDelegate {
@objc(Menu)
open class Menu: View {
open class Menu: Button {
/// The direction in which the animation opens the menu.
open var direction = MenuDirection.up {
didSet {
......@@ -90,12 +90,127 @@ open class Menu: View {
}
}
/// A reference to the base UIButton.
open var button: UIButton? {
/// A reference to the contentView.
open let contentView = UIView()
/// A reference to the contentView.
open let container = UIView()
/// A reference to the MenuItems.
open var items = [MenuItem]() {
didSet {
oldValue?.removeTarget(self, action: #selector(handleToggleMenu), for: .touchUpInside)
button?.addTarget(self, action: #selector(handleToggleMenu), for: .touchUpInside)
reload()
}
}
/// A boolean indicating if the menu is open or not.
open var isOpened = false
/// An optional delegation handler.
open weak var delegate: MenuDelegate?
open override func layoutSubviews() {
super.layoutSubviews()
contentView.frame = container.bounds
}
open override func prepare() {
super.prepare()
prepareContentView()
prepareContainer()
prepareHandler()
}
}
extension Menu {
fileprivate func reload() {
}
}
extension Menu {
/// Prepares the contentView.
fileprivate func prepareContentView() {
contentView.clipsToBounds = true
contentView.backgroundColor = .white
contentView.cornerRadiusPreset = .cornerRadius1
}
/// Prepares the container.
fileprivate func prepareContainer() {
container.depthPreset = .depth1
container.addSubview(contentView)
}
/// Prepares the button.
fileprivate func prepareHandler() {
addTarget(self, action: #selector(handleToggleMenu), for: .touchUpInside)
}
}
extension Menu {
/**
Handles the hit test for the Menu and views outside of the Menu bounds.
- Parameter _ point: A CGPoint.
- Parameter with event: An optional UIEvent.
- Returns: An optional UIView.
*/
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard isOpened, isEnabled else {
return super.hitTest(point, with: event)
}
for v in subviews {
let p = v.convert(point, from: self)
if v.bounds.contains(p) {
delegate?.menu?(menu: self, tappedAt: point, isOutside: false)
return v.hitTest(p, with: event)
}
}
delegate?.menu?(menu: self, tappedAt: point, isOutside: true)
close()
return self.hitTest(point, with: event)
}
}
extension Menu {
open func open() {
guard !isOpened, isEnabled else {
return
}
guard nil == container.superview else {
return
}
delegate?.menuWillOpen?(menu: self)
switch direction {
case .up, .down, .left, .right:
layout(container).bottom().width(100).height(200).centerHorizontally()
}
isOpened = true
delegate?.menuDidOpen?(menu: self)
}
open func close() {
guard isOpened, isEnabled else {
return
}
delegate?.menuWillClose?(menu: self)
container.removeFromSuperview()
isOpened = false
delegate?.menuDidClose?(menu: self)
}
}
......@@ -106,6 +221,11 @@ extension Menu {
*/
@objc
fileprivate func handleToggleMenu(button: UIButton) {
guard isOpened else {
open()
return
}
close()
}
}
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* 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 CosmicMind 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 enum MenuBacking {
case fade
case blur
}
extension UIViewController {
/**
A convenience property that provides access to the MenuController.
This is the recommended method of accessing the MenuController
through child UIViewControllers.
*/
public var menuController: MenuController? {
var viewController: UIViewController? = self
while nil != viewController {
if viewController is MenuController {
return viewController as? MenuController
}
viewController = viewController?.parent
}
return nil
}
}
open class MenuController: RootController {
/// Reference to the MenuView.
@IBInspectable
open let menu = Menu()
/// A MenuBacking value type.
open var menuBacking = MenuBacking.blur
/// The menuBacking UIBlurEffectStyle.
open var menuBackingBlurEffectStyle = UIBlurEffectStyle.light
/// A reference to the blurView.
open fileprivate(set) var blurView: UIView?
open override func layoutSubviews() {
super.layoutSubviews()
rootViewController.view.frame = view.bounds
}
/**
Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepare method
to initialize property values and other setup operations.
The super.prepare method should always be called immediately
when subclassing.
*/
open override func prepare() {
super.prepare()
prepareMenu()
}
}
extension MenuController {
/// Prepares the menu.
fileprivate func prepareMenu() {
menu.zPosition = 1000
view.addSubview(menu)
}
}
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