Commit 62f29b52 by Daniel Dahan

development: updated FABMenuController handler for FABButton user interactions

parent 3724bbd3
......@@ -37,7 +37,7 @@ public enum CaptureMode: Int {
case video
}
private var CaptureAdjustingExposureContext: UInt8 = 0
fileprivate var CaptureAdjustingExposureContext: UInt8 = 0
@objc(CapturePreset)
public enum CapturePreset: Int {
......
......@@ -135,7 +135,7 @@ public struct Divider {
}
/// A memory reference to the Divider instance.
private var DividerKey: UInt8 = 0
fileprivate var DividerKey: UInt8 = 0
extension UIView {
/// TabBarItem reference.
......
......@@ -214,10 +214,13 @@ open class FABMenu: View {
}
addSubview(v)
v.addTarget(self, action: #selector(handleToggleMenu(button:)), for: .touchUpInside)
v.addTarget(self, action: #selector(handleFABButton(button:)), for: .touchUpInside)
}
}
/// An internal handler for the FABButton.
internal var handleFABButtonCallback: ((UIButton) -> Void)?
/// Size of FABMenuItems.
open var fabMenuItemSize: CGSize {
get {
......@@ -314,16 +317,34 @@ extension FABMenu {
- Parameter completion: A completion block to execute on each view's animation.
*/
open func open(duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIViewAnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {
delegate?.fabMenuWillOpen?(fabMenu: self)
open(isTriggeredByUserInteraction: false, duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
}
/**
Open the Menu component with animation options.
- Parameter isTriggeredByUserInteraction: A boolean indicating whether the
state was changed by a user interaction, true if yes, false otherwise.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
internal func open(isTriggeredByUserInteraction: Bool, duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIViewAnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {
if isTriggeredByUserInteraction {
delegate?.fabMenuWillOpen?(fabMenu: self)
}
spring.expand(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations) { [weak self, completion = completion] (view) in
spring.expand(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations) { [weak self, isTriggeredByUserInteraction = isTriggeredByUserInteraction, completion = completion] (view) in
guard let s = self else {
return
}
(view as? FABMenuItem)?.showTitleLabel()
if view == s.fabMenuItems.last {
if isTriggeredByUserInteraction && view == s.fabMenuItems.last {
s.delegate?.fabMenuDidOpen?(fabMenu: s)
}
......@@ -342,16 +363,34 @@ extension FABMenu {
- Parameter completion: A completion block to execute on each view's animation.
*/
open func close(duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIViewAnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {
delegate?.fabMenuWillClose?(fabMenu: self)
close(isTriggeredByUserInteraction: false, duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations, completion: completion)
}
/**
Close the Menu component with animation options.
- Parameter isTriggeredByUserInteraction: A boolean indicating whether the
state was changed by a user interaction, true if yes, false otherwise.
- Parameter duration: The time for each view's animation.
- Parameter delay: A delay time for each view's animation.
- Parameter usingSpringWithDamping: A damping ratio for the animation.
- Parameter initialSpringVelocity: The initial velocity for the animation.
- Parameter options: Options to pass to the animation.
- Parameter animations: An animation block to execute on each view's animation.
- Parameter completion: A completion block to execute on each view's animation.
*/
internal func close(isTriggeredByUserInteraction: Bool, duration: TimeInterval = 0.15, delay: TimeInterval = 0, usingSpringWithDamping: CGFloat = 0.5, initialSpringVelocity: CGFloat = 0, options: UIViewAnimationOptions = [], animations: ((UIView) -> Void)? = nil, completion: ((UIView) -> Void)? = nil) {
if isTriggeredByUserInteraction {
delegate?.fabMenuWillClose?(fabMenu: self)
}
spring.contract(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations) { [weak self, completion = completion] (view) in
spring.contract(duration: duration, delay: delay, usingSpringWithDamping: usingSpringWithDamping, initialSpringVelocity: initialSpringVelocity, options: options, animations: animations) { [weak self, isTriggeredByUserInteraction = isTriggeredByUserInteraction, completion = completion] (view) in
guard let s = self else {
return
}
(view as? FABMenuItem)?.hideTitleLabel()
if view == s.fabMenuItems.last {
if isTriggeredByUserInteraction && view == s.fabMenuItems.last {
s.delegate?.fabMenuDidClose?(fabMenu: s)
}
......@@ -382,9 +421,9 @@ extension FABMenu {
delegate?.fabMenu?(fabMenu: self, tappedAt: point, isOutside: true)
close()
close(isTriggeredByUserInteraction: true)
return self.hitTest(point, with: event)
return super.hitTest(point, with: event)
}
}
......@@ -394,12 +433,17 @@ extension FABMenu {
- Parameter button: A UIButton.
*/
@objc
fileprivate func handleToggleMenu(button: UIButton) {
fileprivate func handleFABButton(button: UIButton) {
guard nil == handleFABButtonCallback else {
handleFABButtonCallback?(button)
return
}
guard isOpened else {
open()
open(isTriggeredByUserInteraction: true)
return
}
close()
close(isTriggeredByUserInteraction: true)
}
}
......@@ -86,11 +86,14 @@ open class FABMenuController: RootController {
}
}
extension FABMenuController: FABMenuDelegate {}
extension FABMenuController {
/// Prepares the fabMenu.
fileprivate func prepareFABMenu() {
fabMenu.delegate = self
fabMenu.zPosition = 1000
fabMenu.handleFABButtonCallback = handleFABButton
view.addSubview(fabMenu)
}
}
......@@ -174,33 +177,32 @@ extension FABMenuController {
}
}
extension FABMenuController: FABMenuDelegate {
@objc
open func fabMenuWillOpen(fabMenu: FABMenu) {
isUserInteractionEnabled = false
showFabMenuBacking()
}
@objc
open func fabMenuDidOpen(fabMenu: FABMenu) {
isUserInteractionEnabled = true
}
extension FABMenuController {
/**
Handler to toggle the FABMenu opened or closed.
- Parameter button: A UIButton.
*/
@objc
open func fabMenuWillClose(fabMenu: FABMenu) {
fileprivate func handleFABButton(button: UIButton) {
guard fabMenu.isOpened else {
isUserInteractionEnabled = false
showFabMenuBacking()
fabMenu.open(isTriggeredByUserInteraction: true, completion: handleCompletion)
return
}
isUserInteractionEnabled = false
hideFabMenuBacking()
fabMenu.close(isTriggeredByUserInteraction: true, completion: handleCompletion)
}
@objc
open func fabMenuDidClose(fabMenu: FABMenu) {
isUserInteractionEnabled = true
}
@objc
open func fabMenu(fabMenu: FABMenu, tappedAt point: CGPoint, isOutside: Bool) {
guard isOutside else {
return
/**
Completion handler for FABMenu open and close calls.
- Parameter view: A UIView.
*/
fileprivate func handleCompletion(view: UIView) {
if view == fabMenu.fabMenuItems.last {
isUserInteractionEnabled = true
}
}
}
......@@ -266,7 +266,7 @@ public struct Grid {
}
/// A memory reference to the Grid instance for UIView extensions.
private var GridKey: UInt8 = 0
fileprivate var GridKey: UInt8 = 0
/// Grid extension for UIView.
extension UIView {
......
......@@ -961,7 +961,7 @@ extension Layout {
}
/// A memory reference to the LayoutKey instance for UIView extensions.
private var LayoutKey: UInt8 = 0
fileprivate var LayoutKey: UInt8 = 0
/// Layout extension for UIView.
extension UIView {
......
......@@ -31,8 +31,8 @@
import UIKit
/// A memory reference to the NavigationItem instance.
private var NavigationItemKey: UInt8 = 0
private var NavigationItemContext: UInt8 = 0
fileprivate var NavigationItemKey: UInt8 = 0
fileprivate var NavigationItemContext: UInt8 = 0
public class NavigationItem: NSObject {
/// Should center the contentView.
......
......@@ -31,7 +31,7 @@
import UIKit
/// A memory reference to the PageTabBarItem instance for UIViewController extensions.
private var PageTabBarItemKey: UInt8 = 0
fileprivate var PageTabBarItemKey: UInt8 = 0
open class PageTabBarItem: FlatButton {
open override func prepare() {
......
......@@ -388,7 +388,7 @@ extension Switch {
internalSwitchState = state
if animated {
animateToState(state: state) { [weak self] _ in
animateToState(state: state) { [weak self, isTriggeredByUserInteraction = isTriggeredByUserInteraction] _ in
guard isTriggeredByUserInteraction else {
return
}
......@@ -467,23 +467,23 @@ extension Switch {
fileprivate func animateToState(state: SwitchState, completion: ((Switch) -> Void)? = nil) {
isUserInteractionEnabled = false
UIView.animate(withDuration: 0.15,
delay: 0.05,
options: [.curveEaseIn, .curveEaseOut],
animations: { [weak self] in
guard let s = self else {
return
}
s.button.x = .on == state ? s.onPosition + s.bounceOffset : s.offPosition - s.bounceOffset
s.styleForState(state: state)
delay: 0.05,
options: [.curveEaseIn, .curveEaseOut],
animations: { [weak self] in
guard let s = self else {
return
}
s.button.x = .on == state ? s.onPosition + s.bounceOffset : s.offPosition - s.bounceOffset
s.styleForState(state: state)
}) { [weak self] _ in
UIView.animate(withDuration: 0.15,
animations: { [weak self] in
guard let s = self else {
return
}
s.button.x = .on == state ? s.onPosition : s.offPosition
animations: { [weak self] in
guard let s = self else {
return
}
s.button.x = .on == state ? s.onPosition : s.offPosition
}) { [weak self] _ in
guard let s = self else {
return
......
......@@ -254,7 +254,7 @@ extension TabBar {
s.line.center.x = button.center.x
s.line.width = button.width
}) { [weak self, button = button, completion = completion] _ in
}) { [weak self, isTriggeredByUserInteraction = isTriggeredByUserInteraction, button = button, completion = completion] _ in
guard let s = self else {
return
}
......
......@@ -30,7 +30,7 @@
import UIKit
private var ToolbarContext: UInt8 = 0
fileprivate var ToolbarContext: UInt8 = 0
open class Toolbar: Bar {
/// A convenience property to set the titleLabel.text.
......
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