Commit a0a9ac09 by Daniel Dahan

development: updated Snackbar animations to allow for cancel block

parent 51a7d750
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
import UIKit import UIKit
public typealias AnimationFillModeType = String
@objc(AnimationFillMode) @objc(AnimationFillMode)
public enum AnimationFillMode: Int { public enum AnimationFillMode: Int {
case forwards case forwards
...@@ -41,9 +39,10 @@ public enum AnimationFillMode: Int { ...@@ -41,9 +39,10 @@ public enum AnimationFillMode: Int {
} }
/** /**
:name: AnimationFillModeToValue Converts the AnimationFillMode enum value to a corresponding String.
*/ - Parameter mode: An AnimationFillMode enum value.
public func AnimationFillModeToValue(mode: AnimationFillMode) -> AnimationFillModeType { */
public func AnimationFillModeToValue(mode: AnimationFillMode) -> String {
switch mode { switch mode {
case .forwards: case .forwards:
return kCAFillModeForwards return kCAFillModeForwards
...@@ -60,15 +59,15 @@ public typealias AnimationDelayCancelBlock = (Bool) -> Void ...@@ -60,15 +59,15 @@ public typealias AnimationDelayCancelBlock = (Bool) -> Void
public struct Animation { public struct Animation {
/// Delay helper method. /// Delay helper method.
public static func delay(time: TimeInterval, completion: @escaping ()-> Void) -> AnimationDelayCancelBlock? { public static func delay(time: TimeInterval, completion: @escaping () -> Void) -> AnimationDelayCancelBlock {
func dispatch_later(completion: @escaping ()-> Void) { func asyncAfter(completion: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time, execute: completion) DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time, execute: completion)
} }
var cancelable: AnimationDelayCancelBlock? var cancelable: AnimationDelayCancelBlock?
let delayed: AnimationDelayCancelBlock = { (cancel: Bool) in let delayed: AnimationDelayCancelBlock = { (cancel) in
if !cancel { if !cancel {
DispatchQueue.main.async(execute: completion) DispatchQueue.main.async(execute: completion)
} }
...@@ -77,18 +76,18 @@ public struct Animation { ...@@ -77,18 +76,18 @@ public struct Animation {
cancelable = delayed cancelable = delayed
dispatch_later { asyncAfter {
cancelable?(false) cancelable?(false)
} }
return cancelable; return delayed;
} }
/** /**
:name: delayCancel :name: delayCancel
*/ */
public static func delayCancel(completion: AnimationDelayCancelBlock?) { public static func delayCancel(completion: AnimationDelayCancelBlock) {
completion?(true) completion(true)
} }
...@@ -128,8 +127,8 @@ public struct Animation { ...@@ -128,8 +127,8 @@ public struct Animation {
:name: animateWithDelay :name: animateWithDelay
*/ */
public static func animateWithDelay(delay d: CFTimeInterval, duration: CFTimeInterval, animations: (() -> Void), completion: (() -> Void)? = nil) { public static func animateWithDelay(delay d: CFTimeInterval, duration: CFTimeInterval, animations: (() -> Void), completion: (() -> Void)? = nil) {
_ = delay(time: d) { _ = delay(time: d) {
animateWithDuration(duration: duration, animations: animations, completion: completion) animateWithDuration(duration: duration, animations: animations, completion: completion)
} }
} }
} }
...@@ -56,72 +56,72 @@ public struct Icon { ...@@ -56,72 +56,72 @@ public struct Icon {
} }
/// Google icons. /// Google icons.
public static let add: UIImage? = Icon.icon("ic_add_white") public static let add = Icon.icon("ic_add_white")
public static let addCircle: UIImage? = Icon.icon("ic_add_circle_white") public static let addCircle = Icon.icon("ic_add_circle_white")
public static let addCircleOutline: UIImage? = Icon.icon("ic_add_circle_outline_white") public static let addCircleOutline = Icon.icon("ic_add_circle_outline_white")
public static let arrowBack: UIImage? = Icon.icon("ic_arrow_back_white") public static let arrowBack = Icon.icon("ic_arrow_back_white")
public static let arrowDownward: UIImage? = Icon.icon("ic_arrow_downward_white") public static let arrowDownward = Icon.icon("ic_arrow_downward_white")
public static let audio: UIImage? = Icon.icon("ic_audiotrack_white") public static let audio = Icon.icon("ic_audiotrack_white")
public static let bell: UIImage? = Icon.icon("cm_bell_white") public static let bell = Icon.icon("cm_bell_white")
public static let check: UIImage? = Icon.icon("ic_check_white") public static let check = Icon.icon("ic_check_white")
public static let clear: UIImage? = Icon.icon("ic_close_white") public static let clear = Icon.icon("ic_close_white")
public static let close: UIImage? = Icon.icon("ic_close_white") public static let close = Icon.icon("ic_close_white")
public static let edit: UIImage? = Icon.icon("ic_edit_white") public static let edit = Icon.icon("ic_edit_white")
public static let favorite: UIImage? = Icon.icon("ic_favorite_white") public static let favorite = Icon.icon("ic_favorite_white")
public static let favoriteBorder: UIImage? = Icon.icon("ic_favorite_border_white") public static let favoriteBorder = Icon.icon("ic_favorite_border_white")
public static let history: UIImage? = Icon.icon("ic_history_white") public static let history = Icon.icon("ic_history_white")
public static let home: UIImage? = Icon.icon("ic_home_white") public static let home = Icon.icon("ic_home_white")
public static let image: UIImage? = Icon.icon("ic_image_white") public static let image = Icon.icon("ic_image_white")
public static let menu: UIImage? = Icon.icon("ic_menu_white") public static let menu = Icon.icon("ic_menu_white")
public static let moreHorizontal: UIImage? = Icon.icon("ic_more_horiz_white") public static let moreHorizontal = Icon.icon("ic_more_horiz_white")
public static let moreVertical: UIImage? = Icon.icon("ic_more_vert_white") public static let moreVertical = Icon.icon("ic_more_vert_white")
public static let movie: UIImage? = Icon.icon("ic_movie_white") public static let movie = Icon.icon("ic_movie_white")
public static let pen: UIImage? = Icon.icon("ic_edit_white") public static let pen = Icon.icon("ic_edit_white")
public static let place: UIImage? = Icon.icon("ic_place_white") public static let place = Icon.icon("ic_place_white")
public static let photoCamera: UIImage? = Icon.icon("ic_photo_camera_white") public static let photoCamera = Icon.icon("ic_photo_camera_white")
public static let photoLibrary: UIImage? = Icon.icon("ic_photo_library_white") public static let photoLibrary = Icon.icon("ic_photo_library_white")
public static let search: UIImage? = Icon.icon("ic_search_white") public static let search = Icon.icon("ic_search_white")
public static let settings: UIImage? = Icon.icon("ic_settings_white") public static let settings = Icon.icon("ic_settings_white")
public static let share: UIImage? = Icon.icon("ic_share_white") public static let share = Icon.icon("ic_share_white")
public static let star: UIImage? = Icon.icon("ic_star_white") public static let star = Icon.icon("ic_star_white")
public static let starBorder: UIImage? = Icon.icon("ic_star_border_white") public static let starBorder = Icon.icon("ic_star_border_white")
public static let starHalf: UIImage? = Icon.icon("ic_star_half_white") public static let starHalf = Icon.icon("ic_star_half_white")
public static let videocam: UIImage? = Icon.icon("ic_videocam_white") public static let videocam = Icon.icon("ic_videocam_white")
public static let visibility: UIImage? = Icon.icon("ic_visibility_white") public static let visibility = Icon.icon("ic_visibility_white")
/// CosmicMind icons. /// CosmicMind icons.
public struct cm { public struct cm {
public static let add: UIImage? = Icon.icon("cm_add_white") public static let add = Icon.icon("cm_add_white")
public static let arrowBack: UIImage? = Icon.icon("cm_arrow_back_white") public static let arrowBack = Icon.icon("cm_arrow_back_white")
public static let arrowDownward: UIImage? = Icon.icon("cm_arrow_downward_white") public static let arrowDownward = Icon.icon("cm_arrow_downward_white")
public static let audio: UIImage? = Icon.icon("cm_audio_white") public static let audio = Icon.icon("cm_audio_white")
public static let audioLibrary: UIImage? = Icon.icon("cm_audio_library_white") public static let audioLibrary = Icon.icon("cm_audio_library_white")
public static let bell: UIImage? = Icon.icon("cm_bell_white") public static let bell = Icon.icon("cm_bell_white")
public static let check: UIImage? = Icon.icon("cm_check_white") public static let check = Icon.icon("cm_check_white")
public static let clear: UIImage? = Icon.icon("cm_close_white") public static let clear = Icon.icon("cm_close_white")
public static let close: UIImage? = Icon.icon("cm_close_white") public static let close = Icon.icon("cm_close_white")
public static let edit: UIImage? = Icon.icon("cm_pen_white") public static let edit = Icon.icon("cm_pen_white")
public static let image: UIImage? = Icon.icon("cm_image_white") public static let image = Icon.icon("cm_image_white")
public static let menu: UIImage? = Icon.icon("cm_menu_white") public static let menu = Icon.icon("cm_menu_white")
public static let microphone: UIImage? = Icon.icon("cm_microphone_white") public static let microphone = Icon.icon("cm_microphone_white")
public static let moreHorizontal: UIImage? = Icon.icon("cm_more_horiz_white") public static let moreHorizontal = Icon.icon("cm_more_horiz_white")
public static let moreVertical: UIImage? = Icon.icon("cm_more_vert_white") public static let moreVertical = Icon.icon("cm_more_vert_white")
public static let movie: UIImage? = Icon.icon("cm_movie_white") public static let movie = Icon.icon("cm_movie_white")
public static let pause: UIImage? = Icon.icon("cm_pause_white") public static let pause = Icon.icon("cm_pause_white")
public static let pen: UIImage? = Icon.icon("cm_pen_white") public static let pen = Icon.icon("cm_pen_white")
public static let photoCamera: UIImage? = Icon.icon("cm_photo_camera_white") public static let photoCamera = Icon.icon("cm_photo_camera_white")
public static let photoLibrary: UIImage? = Icon.icon("cm_photo_library_white") public static let photoLibrary = Icon.icon("cm_photo_library_white")
public static let play: UIImage? = Icon.icon("cm_play_white") public static let play = Icon.icon("cm_play_white")
public static let search: UIImage? = Icon.icon("cm_search_white") public static let search = Icon.icon("cm_search_white")
public static let settings: UIImage? = Icon.icon("cm_settings_white") public static let settings = Icon.icon("cm_settings_white")
public static let share: UIImage? = Icon.icon("cm_share_white") public static let share = Icon.icon("cm_share_white")
public static let shuffle: UIImage? = Icon.icon("cm_shuffle_white") public static let shuffle = Icon.icon("cm_shuffle_white")
public static let skipBackward: UIImage? = Icon.icon("cm_skip_backward_white") public static let skipBackward = Icon.icon("cm_skip_backward_white")
public static let skipForward: UIImage? = Icon.icon("cm_skip_forward_white") public static let skipForward = Icon.icon("cm_skip_forward_white")
public static let star: UIImage? = Icon.icon("cm_star_white") public static let star = Icon.icon("cm_star_white")
public static let videocam: UIImage? = Icon.icon("cm_videocam_white") public static let videocam = Icon.icon("cm_videocam_white")
public static let volumeHigh: UIImage? = Icon.icon("cm_volume_high_white") public static let volumeHigh = Icon.icon("cm_volume_high_white")
public static let volumeMedium: UIImage? = Icon.icon("cm_volume_medium_white") public static let volumeMedium = Icon.icon("cm_volume_medium_white")
public static let volumeOff: UIImage? = Icon.icon("cm_volume_off_white") public static let volumeOff = Icon.icon("cm_volume_off_white")
} }
} }
...@@ -37,14 +37,14 @@ public protocol MenuViewDelegate { ...@@ -37,14 +37,14 @@ public protocol MenuViewDelegate {
optional func menuViewDidTapOutside(menuView: MenuView) optional func menuViewDidTapOutside(menuView: MenuView)
} }
public class MenuView : PulseView { open class MenuView : PulseView {
/// References the Menu instance. /// References the Menu instance.
public private(set) lazy var menu: Menu = Menu() open internal(set) lazy var menu: Menu = Menu()
/// A delegation reference. /// A delegation reference.
open weak var delegate: MenuViewDelegate? open weak var delegate: MenuViewDelegate?
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
/** /**
Since the subviews will be outside the bounds of this view, Since the subviews will be outside the bounds of this view,
we need to look at the subviews to see if we have a hit. we need to look at the subviews to see if we have a hit.
...@@ -68,13 +68,13 @@ public class MenuView : PulseView { ...@@ -68,13 +68,13 @@ public class MenuView : PulseView {
} }
/** /**
Prepares the view instance when intialized. When subclassing, Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepareView method it is recommended to override the prepareView method
to initialize property values and other setup operations. to initialize property values and other setup operations.
The super.prepareView method should always be called immediately The super.prepareView method should always be called immediately
when subclassing. when subclassing.
*/ */
public override func prepareView() { open override func prepareView() {
super.prepareView() super.prepareView()
pulseAnimation = .none pulseAnimation = .none
clipsToBounds = false clipsToBounds = false
...@@ -82,11 +82,11 @@ public class MenuView : PulseView { ...@@ -82,11 +82,11 @@ public class MenuView : PulseView {
} }
/** /**
Opens the menu with a callback. Opens the menu with a callback.
- Parameter completion: An Optional callback that is executed when - Parameter completion: An Optional callback that is executed when
all menu items have been opened. all menu items have been opened.
*/ */
public func open(completion: (() -> Void)? = nil) { open func open(completion: (() -> Void)? = nil) {
if true == menu.views?.first?.isUserInteractionEnabled { if true == menu.views?.first?.isUserInteractionEnabled {
menu.views?.first?.isUserInteractionEnabled = false menu.views?.first?.isUserInteractionEnabled = false
menu.open { [weak self] (v: UIView) in menu.open { [weak self] (v: UIView) in
...@@ -99,11 +99,11 @@ public class MenuView : PulseView { ...@@ -99,11 +99,11 @@ public class MenuView : PulseView {
} }
/** /**
Closes the menu with a callback. Closes the menu with a callback.
- Parameter completion: An Optional callback that is executed when - Parameter completion: An Optional callback that is executed when
all menu items have been closed. all menu items have been closed.
*/ */
public func close(completion: (() -> Void)? = nil) { open func close(completion: (() -> Void)? = nil) {
if true == menu.views?.first?.isUserInteractionEnabled { if true == menu.views?.first?.isUserInteractionEnabled {
menu.views?.first?.isUserInteractionEnabled = false menu.views?.first?.isUserInteractionEnabled = false
menu.close { [weak self] (v: UIView) in menu.close { [weak self] (v: UIView) in
......
...@@ -58,6 +58,25 @@ open class Snackbar: BarView { ...@@ -58,6 +58,25 @@ open class Snackbar: BarView {
/// The status of the snackbar. /// The status of the snackbar.
open internal(set) var status = SnackbarStatus.notVisible open internal(set) var status = SnackbarStatus.notVisible
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
/**
Since the subviews will be outside the bounds of this view,
we need to look at the subviews to see if we have a hit.
*/
guard !isHidden else {
return nil
}
for v in subviews {
let p = v.convert(point, from: self)
if v.bounds.contains(p) {
return v.hitTest(p, with: event)
}
}
return super.hitTest(point, with: event)
}
/** /**
Prepares the view instance when intialized. When subclassing, Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepareView method it is recommended to override the prepareView method
...@@ -67,10 +86,12 @@ open class Snackbar: BarView { ...@@ -67,10 +86,12 @@ open class Snackbar: BarView {
*/ */
open override func prepareView() { open override func prepareView() {
super.prepareView() super.prepareView()
interimSpace = 24 depthPreset = .none
interimSpacePreset = .interimSpace8
contentEdgeInsets.left = interimSpace contentEdgeInsets.left = interimSpace
contentEdgeInsets.right = interimSpace contentEdgeInsets.right = interimSpace
backgroundColor = Color.grey.darken3 backgroundColor = Color.grey.darken3
clipsToBounds = false
prepareTextLabel() prepareTextLabel()
} }
......
...@@ -90,25 +90,34 @@ open class SnackbarController: RootController { ...@@ -90,25 +90,34 @@ open class SnackbarController: RootController {
Animates to a SnackbarStatus. Animates to a SnackbarStatus.
- Parameter status: A SnackbarStatus enum value. - Parameter status: A SnackbarStatus enum value.
*/ */
open func animate(snackbar status: SnackbarStatus, animations: (@escaping (Snackbar) -> Void)? = nil, completion: (@escaping (Snackbar) -> Void)? = nil) { open func animate(snackbar status: SnackbarStatus, delay: TimeInterval = 0, animations: (@escaping (Snackbar) -> Void)? = nil, completion: (@escaping (Snackbar) -> Void)? = nil) -> AnimationDelayCancelBlock {
isAnimating = true return Animation.delay(time: delay) { [weak self, status = status, animations = animations, completion = completion] in
isUserInteractionEnabled = false
UIView.animate(withDuration: 0.25, animations: { [weak self, status = status, animations = animations] in
guard let s = self else { guard let s = self else {
return return
} }
s.layoutSnackbar(status: status) s.isAnimating = true
animations?(s.snackbar) s.isUserInteractionEnabled = false
}) { [weak self, status = status, completion = completion] _ in
guard let s = self else {
return
}
s.isAnimating = false UIView.animate(withDuration: 0.25, animations: { [weak self, status = status, animations = animations] in
s.isUserInteractionEnabled = true guard let s = self else {
s.snackbar.status = status return
completion?(s.snackbar) }
s.layoutSnackbar(status: status)
animations?(s.snackbar)
}) { [weak self, status = status, completion = completion] _ in
guard let s = self else {
return
}
s.isAnimating = false
s.isUserInteractionEnabled = true
s.snackbar.status = status
completion?(s.snackbar)
}
} }
} }
...@@ -124,6 +133,7 @@ open class SnackbarController: RootController { ...@@ -124,6 +133,7 @@ open class SnackbarController: RootController {
} }
layoutSnackbar(status: snackbar.status) layoutSnackbar(status: snackbar.status)
layoutRootViewController(status: snackbar.status)
} }
/** /**
...@@ -149,33 +159,25 @@ open class SnackbarController: RootController { ...@@ -149,33 +159,25 @@ open class SnackbarController: RootController {
- Parameter status: A SnackbarStatus enum value. - Parameter status: A SnackbarStatus enum value.
*/ */
private func layoutSnackbar(status: SnackbarStatus) { private func layoutSnackbar(status: SnackbarStatus) {
let p = snackbar.intrinsicContentSize.height + snackbar.grid.layoutEdgeInsets.top + snackbar.grid.layoutEdgeInsets.bottom
snackbar.width = view.width
snackbar.height = p
snackbar.y = .visible == status ? view.height - p : view.height
snackbar.divider.reload()
}
/**
Lays out the rootViewController.
- Parameter status: A SnackbarStatus enum value.
*/
private func layoutRootViewController(status: SnackbarStatus) {
guard let vc = rootViewController else { guard let vc = rootViewController else {
return return
} }
let w = view.width
let h = view.height
let p = snackbar.intrinsicContentSize.height + snackbar.grid.layoutEdgeInsets.top + snackbar.grid.layoutEdgeInsets.bottom
snackbar.width = w
snackbar.height = p
vc.view.x = 0 vc.view.x = 0
vc.view.y = 0 vc.view.y = 0
vc.view.width = w vc.view.width = view.width
vc.view.height = .visible == status ? view.height - snackbar.height : view.height
switch status {
case .visible:
let y = h - p
snackbar.y = y
snackbar.isHidden = false
vc.view.height = y
case .notVisible:
snackbar.y = h
snackbar.isHidden = true
vc.view.height = h
}
snackbar.divider.reload()
} }
} }
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