Commit 07222ba0 by Daniel Dahan

development: BottomSheetController now adjusts opening position based on FABButton

parent 56da8682
...@@ -39,14 +39,18 @@ public enum BottomSheetFABButtonPosition: Int { ...@@ -39,14 +39,18 @@ public enum BottomSheetFABButtonPosition: Int {
@objc(BottomSheetLayoutStyle) @objc(BottomSheetLayoutStyle)
public enum BottomSheetLayoutStyle: Int { public enum BottomSheetLayoutStyle: Int {
case persistent
case modal case modal
case persistent
} }
open class BottomSheet: View { open class BottomSheet: View {
/// Handler for when the fabButton is set.
fileprivate var fabButtonWasSet: ((FABButton?) -> Void)?
/// A reference to a FABButton. /// A reference to a FABButton.
open var fabButton: FABButton? { open var fabButton: FABButton? {
didSet { didSet {
fabButtonWasSet?(fabButton)
layoutSubviews() layoutSubviews()
} }
} }
...@@ -240,15 +244,15 @@ open class BottomSheetController: RootController { ...@@ -240,15 +244,15 @@ open class BottomSheetController: RootController {
open var bottomThreshold: CGFloat = 64 open var bottomThreshold: CGFloat = 64
fileprivate var bottomSheetThreshold: CGFloat = 0 fileprivate var bottomSheetThreshold: CGFloat = 0
/// A preset for bottomSheetClosedHeight. /// A preset for bottomSheetClosedThreshold.
open var bottomSheetClosedHeightPreset = HeightPreset.none { open var bottomSheetClosedThresholdPreset = HeightPreset.none {
didSet { didSet {
bottomSheetClosedHeight = CGFloat(bottomSheetClosedHeightPreset.rawValue) bottomSheetClosedThreshold = CGFloat(bottomSheetClosedThresholdPreset.rawValue)
} }
} }
/// The height the BottomSheet should leave open when a FABButton exists. /// The height the BottomSheet should leave open when a FABButton exists.
open var bottomSheetClosedHeight: CGFloat = 0 { open var bottomSheetClosedThreshold: CGFloat = 0 {
didSet { didSet {
layoutSubviews() layoutSubviews()
} }
...@@ -351,7 +355,7 @@ open class BottomSheetController: RootController { ...@@ -351,7 +355,7 @@ open class BottomSheetController: RootController {
opens up to. opens up to.
*/ */
@IBInspectable @IBInspectable
open fileprivate(set) var bottomSheetHeight: CGFloat! open fileprivate(set) var bottomSheetHeight: CGFloat = 0
/// Determines the layout style for the bottomSheet. /// Determines the layout style for the bottomSheet.
open var bottomSheetStyle = BottomSheetLayoutStyle.modal { open var bottomSheetStyle = BottomSheetLayoutStyle.modal {
...@@ -427,7 +431,8 @@ open class BottomSheetController: RootController { ...@@ -427,7 +431,8 @@ open class BottomSheetController: RootController {
open override func prepare() { open override func prepare() {
super.prepare() super.prepare()
prepareBottomSheet() prepareBottomSheet()
bottomSheetClosedHeightPreset = .normal bottomSheetClosedThresholdPreset = .large
bottomSheet.fabButtonWasSet = handleFABButtonWasSet
} }
/** /**
...@@ -539,7 +544,7 @@ open class BottomSheetController: RootController { ...@@ -539,7 +544,7 @@ open class BottomSheetController: RootController {
return return
} }
v.position.y = s.view.bounds.height - v.bounds.height / 2 v.position.y = s.view.bounds.height - s.bottomSheetHeight / 2
if .modal == s.bottomSheetStyle { if .modal == s.bottomSheetStyle {
s.rootViewController.view.alpha = 0.5 s.rootViewController.view.alpha = 0.5
...@@ -574,19 +579,7 @@ open class BottomSheetController: RootController { ...@@ -574,19 +579,7 @@ open class BottomSheetController: RootController {
return return
} }
let h = s.view.bounds.height v.position.y = s.view.bounds.height + s.bottomSheetHeight / 2 - (nil == s.bottomSheet.fabButton ? 0 : s.bottomSheetClosedThreshold)
let p = s.bottomSheetHeight / 2
v.position.y = h + p
// if nil == s.bottomSheet.fabButton {
// v.position.y = h + p
// } else {
// let y = v.position.y
// let q = s.bottomSheetClosedHeight / 2
// print(h, p, y, q)
// v.position.y = y > q ? q : h + p
// }
if .modal == s.bottomSheetStyle { if .modal == s.bottomSheetStyle {
s.rootViewController.view.alpha = 1 s.rootViewController.view.alpha = 1
...@@ -596,7 +589,9 @@ open class BottomSheetController: RootController { ...@@ -596,7 +589,9 @@ open class BottomSheetController: RootController {
return return
} }
if nil == s.bottomSheet.fabButton {
s.hideView(container: v) s.hideView(container: v)
}
s.delegate?.bottomViewControllerDidClose?(bottomViewController: s) s.delegate?.bottomViewControllerDidClose?(bottomViewController: s)
} }
...@@ -666,8 +661,8 @@ open class BottomSheetController: RootController { ...@@ -666,8 +661,8 @@ open class BottomSheetController: RootController {
- Parameter container: A container view. - Parameter container: A container view.
*/ */
fileprivate func showView(container: UIView) { fileprivate func showView(container: UIView) {
container.depthPreset = depthPreset
container.isHidden = false container.isHidden = false
container.depthPreset = depthPreset
} }
/** /**
...@@ -675,8 +670,8 @@ open class BottomSheetController: RootController { ...@@ -675,8 +670,8 @@ open class BottomSheetController: RootController {
- Parameter container: A container view. - Parameter container: A container view.
*/ */
fileprivate func hideView(container: UIView) { fileprivate func hideView(container: UIView) {
container.depthPreset = .none
container.isHidden = true container.isHidden = true
container.depthPreset = .none
} }
} }
...@@ -689,13 +684,13 @@ extension BottomSheetController { ...@@ -689,13 +684,13 @@ extension BottomSheetController {
/// A method that prepares the bottomSheet. /// A method that prepares the bottomSheet.
fileprivate func prepareBottomSheet() { fileprivate func prepareBottomSheet() {
bottomSheetHeight = .phone == Device.userInterfaceIdiom ? 280 : 320 bottomSheetHeight = .phone == Device.userInterfaceIdiom ? 280 : 320
view.addSubview(bottomSheet)
bottomSheet.isHidden = true bottomSheet.isHidden = true
bottomSheet.width = view.bounds.width bottomSheet.width = view.bounds.width
bottomSheet.height = bottomSheetHeight bottomSheet.height = bottomSheetHeight
bottomSheet.position.y = view.bounds.height + bottomSheetHeight / 2 bottomSheet.position.y = view.bounds.height + bottomSheetHeight / 2
bottomSheet.zPosition = 2000 bottomSheet.zPosition = 2000
view.addSubview(bottomSheet)
guard nil != bottomViewController else { guard nil != bottomViewController else {
return return
...@@ -761,35 +756,36 @@ extension BottomSheetController: UIGestureRecognizerDelegate { ...@@ -761,35 +756,36 @@ extension BottomSheetController: UIGestureRecognizerDelegate {
return return
} }
let point = recognizer.location(in: view)
// Animate the panel. // Animate the panel.
switch recognizer.state { switch recognizer.state {
case .began: case .began:
originalY = bottomSheet.position.y originalY = bottomSheet.position.y
showView(container: bottomSheet) showView(container: bottomSheet)
delegate?.bottomViewController?(bottomViewController: self, didBeginPanAt: point) delegate?.bottomViewController?(bottomViewController: self, didBeginPanAt: recognizer.location(in: view))
case .changed: case .changed:
let h = bottomSheet.bounds.height let y = originalY + recognizer.translation(in: bottomSheet).y
let translationY = recognizer.translation(in: bottomSheet).y let h = view.bounds.height
let b = bottomSheetHeight / 2
let p = h - b
let q = h + b - bottomSheetClosedThreshold
bottomSheet.position.y = originalY + translationY < view.bounds.height - (h / 2) ? view.bounds.height - (h / 2) : originalY + translationY bottomSheet.position.y = y < p ? p : y > q && nil != bottomSheet.fabButton ? q : y
let a = 1 - (view.bounds.height - bottomSheet.position.y) / bottomSheet.bounds.height let a = 1 - (h - y) / bottomSheetHeight
rootViewController.view.alpha = 0.5 < a && bottomSheet.position.y >= bottomSheet.bounds.height / 2 ? a : 0.5 rootViewController.view.alpha = 0.5 < a && y >= b ? a : 0.5
delegate?.bottomViewController?(bottomViewController: self, didChangePanAt: point) delegate?.bottomViewController?(bottomViewController: self, didChangePanAt: recognizer.location(in: view))
case .ended, .cancelled, .failed: case .ended, .cancelled, .failed:
let p = recognizer.velocity(in: recognizer.view) let p = recognizer.velocity(in: recognizer.view)
let y = p.y >= 1000 || p.y <= -1000 ? p.y : 0 let v = p.y >= 500 || p.y <= -500 ? p.y : 0
delegate?.bottomViewController?(bottomViewController: self, didEndPanAt: point) delegate?.bottomViewController?(bottomViewController: self, didEndPanAt: recognizer.location(in: view))
if bottomSheet.y >= bottomSheetThreshold || y > 1000 { if bottomSheet.y >= bottomSheetThreshold || v > 500 {
closeBottomSheet(velocity: y) closeBottomSheet(velocity: v)
} else { } else {
openBottomSheet(velocity: y) openBottomSheet(velocity: v)
} }
case .possible:break case .possible:break
} }
...@@ -816,3 +812,24 @@ extension BottomSheetController: UIGestureRecognizerDelegate { ...@@ -816,3 +812,24 @@ extension BottomSheetController: UIGestureRecognizerDelegate {
closeBottomSheet() closeBottomSheet()
} }
} }
extension BottomSheetController {
/**
A handler that is executed when the bottomSheet.fabButton
has been set.
- Parameter fabButton: An optional FABButton.
*/
fileprivate func handleFABButtonWasSet(fabButton: FABButton?) {
guard nil == fabButton else {
if !isOpened {
showView(container: bottomSheet)
closeBottomSheet()
}
return
}
if !isOpened {
closeBottomSheet()
}
}
}
...@@ -374,14 +374,14 @@ open class NavigationDrawerController: RootController { ...@@ -374,14 +374,14 @@ open class NavigationDrawerController: RootController {
opens up to. opens up to.
*/ */
@IBInspectable @IBInspectable
open fileprivate(set) var leftViewWidth: CGFloat! open fileprivate(set) var leftViewWidth: CGFloat = 0
/** /**
A CGFloat property to access the width that the rightView A CGFloat property to access the width that the rightView
opens up to. opens up to.
*/ */
@IBInspectable @IBInspectable
open fileprivate(set) var rightViewWidth: CGFloat! open fileprivate(set) var rightViewWidth: CGFloat = 0
/** /**
An initializer that initializes the object with a NSCoder object. An initializer that initializes the object with a NSCoder object.
...@@ -1167,11 +1167,11 @@ extension NavigationDrawerController: UIGestureRecognizerDelegate { ...@@ -1167,11 +1167,11 @@ extension NavigationDrawerController: UIGestureRecognizerDelegate {
delegate?.navigationDrawerController?(navigationDrawerController: self, didChangePanAt: point, position: .left) delegate?.navigationDrawerController?(navigationDrawerController: self, didChangePanAt: point, position: .left)
case .ended, .cancelled, .failed: case .ended, .cancelled, .failed:
let p = recognizer.velocity(in: recognizer.view) let p = recognizer.velocity(in: recognizer.view)
let x = p.x >= 1000 || p.x <= -1000 ? p.x : 0 let x = p.x >= 500 || p.x <= -500 ? p.x : 0
delegate?.navigationDrawerController?(navigationDrawerController: self, didEndPanAt: point, position: .left) delegate?.navigationDrawerController?(navigationDrawerController: self, didEndPanAt: point, position: .left)
if v.x <= -leftViewWidth + leftViewThreshold || x < -1000 { if v.x <= -leftViewWidth + leftViewThreshold || x < -500 {
closeLeftView(velocity: x) closeLeftView(velocity: x)
} else { } else {
openLeftView(velocity: x) openLeftView(velocity: x)
......
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