Compare commits

...

15 Commits

Author SHA1 Message Date
jonkykong 70715d6fa0 Updated podspec 2019-07-29 00:57:22 -07:00
jonkykong 411bd59493 Refactor 2019-07-29 00:56:05 -07:00
jonkykong 5e295d36eb Fix for gesture cancelation causing menu unresponsiveness 2019-07-29 00:53:21 -07:00
jonkykong 6aa68df4ce Update podspec 2019-07-28 23:05:46 -07:00
jonkykong 5c292125a6 Fix for tap gesture not working in landscape mode 2019-07-28 23:04:34 -07:00
jonkykong 48eb4a2e3a Fix for delegate not always being called 2019-07-28 23:04:18 -07:00
jonkykong 9503c814d6 README update 2019-07-28 23:03:59 -07:00
jonkykong 4dd4f54a8e Refactor + add support for tap gesture option 2019-07-28 23:03:41 -07:00
jonkykong 7429a42c26 Fix for landscape mode menu tap to dismiss 2019-07-28 16:05:49 -07:00
jonkykong df032e6072 Fix for updating UI in demo project 2019-07-28 16:05:23 -07:00
jonkykong 3a7c74e2e0 Fix for viewWillDisappear not being called 2019-07-27 03:28:14 -07:00
jonkykong 900926f268 Updated strings 2019-07-27 03:27:46 -07:00
jonkykong f5e585857c Updated documentation 2019-07-27 03:27:24 -07:00
Mikhail Apurin 1d96ef80b3 Unreliable dismissal by tap gesture 2019-07-25 16:50:11 +09:00
Jon Kent 452b354e19 Update README.md 2019-07-24 10:20:04 -07:00
8 changed files with 109 additions and 70 deletions
+1 -1
View File
@@ -44,7 +44,7 @@ class MainViewController: UIViewController {
private func updateUI(settings: SideMenuSettings) {
let styles:[UIBlurEffect.Style] = [.dark, .light, .extraLight]
if let menuBlurEffectStyle = settings.blurEffectStyle {
blurSegmentControl.selectedSegmentIndex = styles.firstIndex(of: menuBlurEffectStyle) ?? 0
blurSegmentControl.selectedSegmentIndex = (styles.firstIndex(of: menuBlurEffectStyle) ?? 0) + 1
} else {
blurSegmentControl.selectedSegmentIndex = 0
}
+6
View File
@@ -182,6 +182,12 @@ extension SideMenuManager {
set {}
}
@available(*, deprecated, renamed: "enableSwipeToDismissGesture")
public var enableSwipeGestures: Bool {
get { return true }
set {}
}
@available(*, deprecated, renamed: "SideMenuPresentationStyle")
public typealias MenuPresentMode = SideMenuPresentationStyle
+14
View File
@@ -52,6 +52,20 @@ internal extension UIViewController {
}
}
internal extension UIGestureRecognizer {
convenience init(addTo view: UIView, target: Any, action: Selector) {
self.init()
addTarget(target, action: action)
view.addGestureRecognizer(self)
}
convenience init?(addTo view: UIView?, target: Any, action: Selector) {
guard let view = view else { return nil }
self.init(addTo: view, target: target, action: action)
}
}
internal extension UIPanGestureRecognizer {
var canSwitch: Bool {
+4 -2
View File
@@ -28,8 +28,10 @@ internal protocol MenuModel: TransitionModel {
var dismissOnRotation: Bool { get }
/// Automatically dismisses the menu when app goes to the background.
var dismissWhenBackgrounded: Bool { get }
/// Enable or disable gestures that would swipe to dismiss the menu. Default is true.
var enableSwipeGestures: Bool { get }
/// Enable or disable a swipe gesture that dismisses the menu. Will not be triggered when `presentingViewControllerUserInteractionEnabled` is set to true. Default is true.
var enableSwipeToDismissGesture: Bool { get }
/// Enable or disable a tap gesture that dismisses the menu. Will not be triggered when `presentingViewControllerUserInteractionEnabled` is set to true. Default is true.
var enableTapToDismissGesture: Bool { get }
/**
The push style of the menu.
+4 -9
View File
@@ -30,8 +30,8 @@ public class SideMenuManager: NSObject {
var name: String {
switch self {
case .left: return "menuLeftNavigationController"
case .right: return "menuRightNavigationController"
case .left: return "leftMenuNavigationController"
case .right: return "rightMenuNavigationController"
}
}
}
@@ -204,10 +204,8 @@ private extension SideMenuManager {
screenEdgeGestureRecognizer.edges == edge {
view.removeGestureRecognizer(screenEdgeGestureRecognizer)
}
return SideMenuScreenEdgeGestureRecognizer {
return SideMenuScreenEdgeGestureRecognizer(addTo: view, target: self, action: #selector(handlePresentMenuScreenEdge(_:))).with {
$0.edges = edge
$0.addTarget(self, action: #selector(handlePresentMenuScreenEdge(_:)))
view.addGestureRecognizer($0)
}
}
@@ -215,10 +213,7 @@ private extension SideMenuManager {
if let panGestureRecognizer = view.gestureRecognizers?.first(where: { $0 is SideMenuPanGestureRecognizer }) as? SideMenuPanGestureRecognizer {
return panGestureRecognizer
}
return SideMenuPanGestureRecognizer {
$0.addTarget(self, action: #selector(handlePresentMenuPan(_:)))
view.addGestureRecognizer($0)
}
return SideMenuPanGestureRecognizer(addTo: view, target: self, action: #selector(handlePresentMenuPan(_:)))
}
var activeViewController: UIViewController? {
@@ -39,7 +39,8 @@ public struct SideMenuSettings: MenuModel {
public var dismissOnPush: Bool = true
public var dismissOnRotation: Bool = true
public var dismissWhenBackgrounded: Bool = true
public var enableSwipeGestures: Bool = true
public var enableSwipeToDismissGesture: Bool = true
public var enableTapToDismissGesture: Bool = true
public var initialSpringVelocity: CGFloat = 1
public var menuWidth: CGFloat = {
let appScreenRect = UIApplication.shared.keyWindow?.bounds ?? UIWindow().bounds
@@ -67,13 +68,12 @@ internal typealias Menu = UISideMenuNavigationController
@objcMembers
open class UISideMenuNavigationController: UINavigationController {
private lazy var _leftSide =
Protected(false) { [weak self] oldValue, newValue in
guard self?.isHidden != false else {
Print.warning(.property, arguments: .leftSide, required: true)
return oldValue
}
return newValue
private lazy var _leftSide = Protected(false) { [weak self] oldValue, newValue in
guard self?.isHidden != false else {
Print.warning(.property, arguments: .leftSide, required: true)
return oldValue
}
return newValue
}
private weak var _sideMenuManager: SideMenuManager?
@@ -88,7 +88,9 @@ open class UISideMenuNavigationController: UINavigationController {
internal weak var sideMenuDelegate: UISideMenuNavigationControllerDelegate?
/// The swipe to dismiss gesture.
private(set) weak var swipeToDismissGesture: UIPanGestureRecognizer? = nil
open private(set) weak var swipeToDismissGesture: UIPanGestureRecognizer? = nil
/// The tap to dismiss gesture.
open private(set) weak var tapToDismissGesture: UITapGestureRecognizer? = nil
open var sideMenuManager: SideMenuManager {
get { return _sideMenuManager ?? SideMenuManager.default }
@@ -107,9 +109,12 @@ open class UISideMenuNavigationController: UINavigationController {
open var settings = SideMenuSettings() {
didSet {
setupBlur()
if !enableSwipeGestures {
if !enableSwipeToDismissGesture {
removeSwipeGesture()
}
if !enableTapToDismissGesture {
removeTapGesture()
}
}
}
@@ -165,26 +170,28 @@ open class UISideMenuNavigationController: UINavigationController {
override open func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if !isBeingDismissed {
// When presenting a view controller from the menu, the menu view gets moved into another transition view above our transition container
// which can break the visual layout we had before. So, we move the menu view back to its original transition view to preserve it.
if let presentingView = presentingViewController?.view, let containerView = presentingView.superview {
containerView.addSubview(view)
}
defer {
activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated)
}
if dismissOnPresent {
// We're presenting a view controller from the menu, so we need to hide the menu so it isn't showing when the presented view is dismissed.
transitionController?.transition(presenting: false, animated: animated, alongsideTransition: { [weak self] in
guard !isBeingDismissed else { return }
// When presenting a view controller from the menu, the menu view gets moved into another transition view above our transition container
// which can break the visual layout we had before. So, we move the menu view back to its original transition view to preserve it.
if let presentingView = presentingViewController?.view, let containerView = presentingView.superview {
containerView.addSubview(view)
}
if dismissOnPresent {
// We're presenting a view controller from the menu, so we need to hide the menu so it isn't showing when the presented view is dismissed.
transitionController?.transition(presenting: false, animated: animated, alongsideTransition: { [weak self] in
guard let self = self else { return }
self.activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated)
}, complete: false, completion: { [weak self] _ in
guard let self = self else { return }
self.activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated)
}, complete: false, completion: { [weak self] _ in
guard let self = self else { return }
self.activeDelegate?.sideMenuDidDisappear?(menu: self, animated: animated)
self.view.isHidden = true
})
} else {
activeDelegate?.sideMenuWillDisappear?(menu: self, animated: animated)
}
self.activeDelegate?.sideMenuDidDisappear?(menu: self, animated: animated)
self.view.isHidden = true
})
}
}
@@ -320,9 +327,14 @@ extension UISideMenuNavigationController: MenuModel {
set { settings.dismissWhenBackgrounded = newValue }
}
@IBInspectable open var enableSwipeGestures: Bool {
get { return settings.enableSwipeGestures }
set { settings.enableSwipeGestures = newValue }
@IBInspectable open var enableSwipeToDismissGesture: Bool {
get { return settings.enableSwipeToDismissGesture }
set { settings.enableSwipeToDismissGesture = newValue }
}
@IBInspectable open var enableTapToDismissGesture: Bool {
get { return settings.enableTapToDismissGesture }
set { settings.enableTapToDismissGesture = newValue }
}
@IBInspectable open var initialSpringVelocity: CGFloat {
@@ -416,12 +428,8 @@ extension UISideMenuNavigationController: SideMenuTransitionControllerDelegate {
internal func sideMenuTransitionController(_ transitionController: SideMenuTransitionController, didPresent viewController: UIViewController) {
removeSwipeGesture()
swipeToDismissGesture = addDismissPanGesture(to: view.superview)
let tapGestureRecognizer = UITapGestureRecognizer()
tapGestureRecognizer.addTarget(self, action: #selector(handleDismissMenuTap(_:)))
tapGestureRecognizer.cancelsTouchesInView = false
view.superview?.addGestureRecognizer(tapGestureRecognizer)
swipeToDismissGesture = addSwipeToDismissGesture(to: view.superview)
tapToDismissGesture = addTapToDismissGesture(to: view.superview)
}
}
@@ -633,6 +641,12 @@ private extension UISideMenuNavigationController {
}
}
func removeTapGesture() {
if let tapToDismissGesture = tapToDismissGesture {
tapToDismissGesture.view?.removeGestureRecognizer(tapToDismissGesture)
}
}
func registerForNotifications() {
NotificationCenter.default.removeObserver(self)
@@ -659,17 +673,23 @@ private extension UISideMenuNavigationController {
}
}
@discardableResult func addDismissPanGesture(to view: UIView?) -> UIPanGestureRecognizer? {
guard enableSwipeGestures, let view = view else { return nil }
return UIPanGestureRecognizer {
@discardableResult func addSwipeToDismissGesture(to view: UIView?) -> UIPanGestureRecognizer? {
guard enableSwipeToDismissGesture else { return nil }
return UIPanGestureRecognizer(addTo: view, target: self, action: #selector(handleDismissMenuPan(_:)))?.with {
$0.cancelsTouchesInView = false
}
}
@discardableResult func addTapToDismissGesture(to view: UIView?) -> UITapGestureRecognizer? {
guard enableTapToDismissGesture else { return nil }
return UITapGestureRecognizer(addTo: view, target: self, action: #selector(handleDismissMenuTap(_:)))?.with {
$0.cancelsTouchesInView = false
$0.addTarget(self, action: #selector(handleDismissMenuPan(_:)))
view.addGestureRecognizer($0)
}
}
@objc func handleDismissMenuTap(_ tap: UITapGestureRecognizer) {
guard view.window?.hitTest(tap.location(in: nil), with: nil) == view.superview else { return }
let hitTest = view.window?.hitTest(tap.location(in: view.superview), with: nil)
guard hitTest == view.superview else { return }
dismissMenu()
}
+16 -14
View File
@@ -149,9 +149,9 @@ SideMenuManager.default.addPanGestureToPresent(toView: self.navigationController
SideMenuManager.default.addScreenEdgePanGesturesToPresent(toView: self.navigationController!.view)
// (Optional) Prevent status bar area from turning black when menu appears:
menuLeftNavigationController.statusBarEndAlpha = 0
leftMenuNavigationController.statusBarEndAlpha = 0
// Copy all settings to the other menu
menuRightNavigationController.settings = menuLeftNavigationController.settings
rightMenuNavigationController.settings = leftMenuNavigationController.settings
```
That's it.
### Customization
@@ -159,9 +159,9 @@ That's it.
`SideMenuManager` supports the following:
``` swift
/// The left menu.
open var menuLeftNavigationController: UISideMenuNavigationController?
open var leftMenuNavigationController: UISideMenuNavigationController?
/// The right menu.
public var menuRightNavigationController: UISideMenuNavigationController?
public var rightMenuNavigationController: UISideMenuNavigationController?
/**
Adds screen edge gestures for both left and right sides to a view to present a menu.
@@ -217,8 +217,10 @@ var dismissOnPush: Bool = true
var dismissOnRotation: Bool = true
/// Automatically dismisses the menu when app goes to the background.
var dismissWhenBackgrounded: Bool = true
/// Enable or disable gestures that would swipe to dismiss the menu. Default is true.
var enableSwipeGestures: Bool = true
/// Enable or disable a swipe gesture that dismisses the menu. Will not be triggered when `presentingViewControllerUserInteractionEnabled` is set to true. Default is true.
var enableSwipeToDismissGesture: Bool = true
/// Enable or disable a tap gesture that dismisses the menu. Will not be triggered when `presentingViewControllerUserInteractionEnabled` is set to true. Default is true.
var enableTapToDismissGesture: Bool = true
/// The animation initial spring velocity when a menu is displayed. Ignored when displayed with a gesture.
var initialSpringVelocity: CGFloat = 1
/// Whether the menu appears on the right or left side of the screen. Right is the default. This property cannot be changed after the menu has loaded.
@@ -256,21 +258,21 @@ var isHidden: Bool
There are 8 pre-defined `SideMenuPresentStyle` options:
``` swift
/// Menu slides in over the existing view.
static let menuSlideIn = SideMenuPresentStyle
static let menuSlideIn: SideMenuPresentStyle
/// The existing view slides out to reveal the menu underneath.
static let viewSlideOut = SideMenuPresentStyle
static let viewSlideOut: SideMenuPresentStyle
/// The existing view slides out while the menu slides in.
static let viewSlideOutMenuIn = SideMenuPresentStyle
static let viewSlideOutMenuIn: SideMenuPresentStyle
/// The menu dissolves in over the existing view.
static let menuDissolveIn = SideMenuPresentStyle
static let menuDissolveIn: SideMenuPresentStyle
/// The existing view slides out while the menu partially slides in.
static let viewSlideOutMenuPartialIn = SideMenuPresentStyle
static let viewSlideOutMenuPartialIn: SideMenuPresentStyle
/// The existing view slides out while the menu slides out from under it.
static let viewSlideOutMenuOut = SideMenuPresentStyle
static let viewSlideOutMenuOut: SideMenuPresentStyle
/// The existing view slides out while the menu partially slides out from under it.
static let viewSlideOutMenuPartialOut = SideMenuPresentStyle
static let viewSlideOutMenuPartialOut: SideMenuPresentStyle
/// The existing view slides out and shrinks to reveal the menu underneath.
static let viewSlideOutMenuZoom = SideMenuPresentStyle
static let viewSlideOutMenuZoom: SideMenuPresentStyle
```
#### UISideMenuNavigationControllerDelegate
To receive notifications when a menu is displayed from a view controller, have it adhere to the `UISideMenuNavigationControllerDelegate` protocol:
+1 -1
View File
@@ -8,7 +8,7 @@
Pod::Spec.new do |s|
s.name = "SideMenu"
s.version = "6.0.9"
s.version = "6.1.1"
s.summary = "Simple side menu control for iOS in Swift inspired by Facebook. Right and Left sides. No coding required."
# This description is used to generate tags and improve search results.