Skip to content

Commit bd1ebe9

Browse files
author
Alex Krzyżanowski
committed
Merge branch 'release/3.0.0'
2 parents c99b292 + 5b2e176 commit bd1ebe9

28 files changed

Lines changed: 179 additions & 128 deletions

File tree

.DS_Store

-6 KB
Binary file not shown.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ DerivedData
1717
*.ipa
1818
*.xcuserstate
1919

20+
.DS_Store
21+
2022
# CocoaPods
2123
#
2224
# We recommend against adding the Pods directory to your .gitignore. However

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 3.0.0
2+
3+
* Now it's possible to choose side where sibedar view controller appears from. Please the the PR #14 (https://github.com/alexkrzyzanowski/SidebarOverlay/pull/14). Thanks to [Eugene Mozharovsky](https://github.com/Mozharovsky).
4+
15
# 2.1.2
26

37
* Close sidebar menu on pan gesture also

README.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ It's quit simple to start developing with `SidebarOverlay`. First, we have to cr
2323

2424
* container view controller
2525
* top view controller
26-
* left view controller
26+
* side view controller
2727

28-
The container view controller is the root view controller that makes all magic for us. It's necessary to subclass `SOContainerViewController` and assign it to our container view controller. Then we can setup top and left view controllers:
28+
The container view controller is the root view controller that makes all magic for us. It's necessary to subclass `SOContainerViewController` and assign it to our container view controller. Then we can setup top and side view controllers:
2929

3030
```Swift
3131
import SidebarOverlay
@@ -35,8 +35,9 @@ class ContainerViewController: SOContainerViewController {
3535
override func viewDidLoad() {
3636
super.viewDidLoad()
3737

38+
self.menuSide = .Right
3839
self.topViewController = self.storyboard?.instantiateViewControllerWithIdentifier("topScreen")
39-
self.leftViewController = self.storyboard?.instantiateViewControllerWithIdentifier("leftScreen")
40+
self.sideViewController = self.storyboard?.instantiateViewControllerWithIdentifier("leftScreen")
4041
}
4142

4243
}
@@ -46,14 +47,14 @@ Set the container view controller as initial on your storyboard and your basic a
4647

4748
### Open sidebar menu programatically
4849

49-
It's always good if user is able to open sidebar menu not only by swipe gesture, but also by tap on menu button. To open sidebar menu programatically, call `setMenuOpened(true)` method of container view controller:
50+
It's always good if user is able to open sidebar menu not only by swipe gesture, but also by tap on menu button. To open sidebar menu programatically, set `isSideViewControllerPresented` property of container view controller to `true`:
5051

5152
```Swift
5253
class TopViewController: UIViewController {
5354

5455
@IBAction func showMeMyMenu () {
5556
if let container = self.so_containerViewController {
56-
container.isLeftViewControllerPresented = true
57+
container.isSideViewControllerPresented = true
5758
}
5859
}
5960

@@ -62,7 +63,7 @@ class TopViewController: UIViewController {
6263

6364
As you see, we have property named `so_containerViewController`. This property is automatically added to all view controllers and you're able to access it everywhere.
6465

65-
To close the sidebar menu, just set the `isLeftViewControllerPresented` property to `false`.
66+
To close the sidebar menu, just set the `isSideViewControllerPresented` property to `false`.
6667

6768
### Changing top view controller from the sidebar menu
6869

SidebarOverlay.podspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
Pod::Spec.new do |s|
22
s.name = "SidebarOverlay"
3-
s.version = "2.1.4"
3+
s.version = "3.0.0"
44
s.summary = "Yet another implementation of sidebar menu, but here your menu appears over the top view controller."
5-
5+
66
s.description = "Yet another implementation of sidebar menu, but here your menu appears over the top view controller. You questions and pull requests are wolcome."
77

88
s.homepage = "https://github.com/alexkrzyzanowski/SidebarOverlay"
99
s.license = { :type => 'MIT', :file => 'LICENSE' }
1010
s.author = { "Alex Krzyzanowski" => "alexkrzyzanowski@icloud.com" }
11-
s.source = { :git => "https://github.com/alexkrzyzanowski/SidebarOverlay.git", :tag => "2.1.4" }
11+
s.source = { :git => "https://github.com/alexkrzyzanowski/SidebarOverlay.git", :tag => "3.0.0" }
1212

1313
s.platform = :ios, '8.0'
1414
s.source_files = 'SidebarOverlay/SidebarOverlay/*.{h,m,swift}'

SidebarOverlay.xcworkspace/contents.xcworkspacedata

100644100755
File mode changed.

SidebarOverlay/SidebarOverlay.xcodeproj/project.pbxproj

100644100755
File mode changed.

SidebarOverlay/SidebarOverlay.xcodeproj/xcshareddata/xcschemes/SidebarOverlay.xcscheme

100644100755
File mode changed.

SidebarOverlay/SidebarOverlay/Info.plist

100644100755
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<key>CFBundlePackageType</key>
1616
<string>FMWK</string>
1717
<key>CFBundleShortVersionString</key>
18-
<string>2.1.4</string>
18+
<string>3.0.0</string>
1919
<key>CFBundleSignature</key>
2020
<string>????</string>
2121
<key>CFBundleVersion</key>

SidebarOverlay/SidebarOverlay/SOContainerViewController.swift

100644100755
Lines changed: 136 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,39 @@
88

99
import UIKit
1010

11+
public enum Side {
12+
case Left
13+
case Right
14+
}
1115

1216
public class SOContainerViewController: UIViewController, UIGestureRecognizerDelegate {
1317

18+
// ---------------------------------
19+
// MARK: Internal usage
20+
// ---------------------------------
21+
22+
/// Specifies the indent from trailing side. This means that
23+
/// if the sidebar comes from left, `SideViewControllerTrailingIndent` is the space
24+
/// on the right side of this sidebar. Otherwise it's the left side.
25+
internal let SideViewControllerTrailingIndent: CGFloat = 56.0
26+
27+
/// Specifies the leading offset for the sidebar.
28+
/// If `menuSide` is set to *Left*, this means the space
29+
/// from superview's `minX` (usually 0). Otherwise
30+
/// from the `maxX` (depends on the screen's dimension).
31+
internal let SideViewControllerOpenedLeadingOffset: CGFloat = 0.0
32+
33+
internal let SideViewControllerOpenAnimationDuration: NSTimeInterval = 0.24
34+
35+
private var _topViewController: UIViewController?
36+
private var _sideViewController: UIViewController?
37+
38+
private var contentCoverView: UIView
39+
40+
// ---------------------------------
41+
// MARK: Public properties
42+
// ---------------------------------
43+
1444
/**
1545
A view controller that is currently presented to user.
1646

@@ -44,7 +74,7 @@ public class SOContainerViewController: UIViewController, UIGestureRecognizerDel
4474
vc.view.addGestureRecognizer(self.createPanGestureRecognizer())
4575
}
4676

47-
self.brindLeftViewToFront()
77+
self.bringSideViewToFront()
4878
}
4979
}
5080

@@ -55,17 +85,17 @@ public class SOContainerViewController: UIViewController, UIGestureRecognizerDel
5585

5686
Usually you have to set it only once, when you prepare an instance of `SOContainerViewController` to be presented.
5787
*/
58-
public var leftViewController: UIViewController? {
88+
public var sideViewController: UIViewController? {
5989
get {
60-
return _leftViewController
90+
return _sideViewController
6191
}
6292
set {
63-
_leftViewController?.view.removeFromSuperview()
64-
_leftViewController?.removeFromParentViewController()
93+
_sideViewController?.view.removeFromSuperview()
94+
_sideViewController?.removeFromParentViewController()
6595

66-
_leftViewController = newValue
96+
_sideViewController = newValue
6797

68-
if let vc = _leftViewController {
98+
if let vc = _sideViewController {
6999
vc.willMoveToParentViewController(self)
70100
self.addChildViewController(vc)
71101
self.view.addSubview(vc.view)
@@ -74,39 +104,51 @@ public class SOContainerViewController: UIViewController, UIGestureRecognizerDel
74104
vc.view.addGestureRecognizer(self.createPanGestureRecognizer())
75105

76106
var menuFrame = vc.view.frame
77-
menuFrame.size.width = self.view.frame.size.width - LeftViewControllerRightIndent
78-
menuFrame.origin.x = -menuFrame.size.width
107+
menuFrame.size.width = self.view.frame.size.width - SideViewControllerTrailingIndent
108+
menuFrame.origin.x = menuSide == .Left ? -menuFrame.size.width : view.frame.maxX + menuFrame.size.width
79109
vc.view.frame = menuFrame
80110
}
81111

82-
self.brindLeftViewToFront()
112+
self.bringSideViewToFront()
83113
}
84114
}
85115

86-
public var isLeftViewControllerPresented: Bool {
116+
public var isSideViewControllerPresented: Bool {
87117
get {
88-
guard let leftVC = self.leftViewController else {
118+
guard let sideVC = self.sideViewController else {
89119
return false
90120
}
91-
92-
return leftVC.view.frame.origin.x == LeftViewControllerOpenedLeftOffset
121+
122+
return (menuSide == .Left) ? (sideVC.view.frame.origin.x == SideViewControllerOpenedLeadingOffset) :
123+
(view.frame.width - sideVC.view.frame.maxX == SideViewControllerOpenedLeadingOffset)
93124
}
94125
set {
95-
guard let leftVC = self.leftViewController else {
126+
guard let sideVC = self.sideViewController else {
96127
return
97128
}
98129

99-
var frame = leftVC.view.frame
100-
frame.origin.x = newValue ? LeftViewControllerOpenedLeftOffset : -frame.size.width
101-
130+
var frame = sideVC.view.frame
131+
if menuSide == .Left {
132+
frame.origin.x = newValue ? SideViewControllerOpenedLeadingOffset : -frame.size.width
133+
} else {
134+
frame.origin.x = newValue ? view.frame.maxX - frame.width - SideViewControllerOpenedLeadingOffset : frame.size.width + SideViewControllerTrailingIndent
135+
}
136+
102137
let animations = { () -> () in
103-
leftVC.view.frame = frame
138+
sideVC.view.frame = frame
104139
self.contentCoverView.alpha = newValue ? 1.0 : 0.0
105140
}
106141

107142
UIView.animateWithDuration(SideViewControllerOpenAnimationDuration, delay: 0, options: UIViewAnimationOptions.BeginFromCurrentState, animations: animations, completion: nil)
108143
}
109144
}
145+
146+
/// Determines where the side menu should come from.
147+
public var menuSide: Side = .Left
148+
149+
// ---------------------------------
150+
// MARK: Initialization
151+
// ---------------------------------
110152

111153
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
112154
self.contentCoverView = UIView()
@@ -118,6 +160,10 @@ public class SOContainerViewController: UIViewController, UIGestureRecognizerDel
118160
super.init(coder: aDecoder)
119161
}
120162

163+
// ---------------------------------
164+
// MARK: View life cycle
165+
// ---------------------------------
166+
121167
public override func viewDidLoad() {
122168
super.viewDidLoad()
123169

@@ -134,82 +180,107 @@ public class SOContainerViewController: UIViewController, UIGestureRecognizerDel
134180
self.view.addSubview(self.contentCoverView)
135181
}
136182

137-
//
183+
// ---------------------------------
138184
// MARK: Gesture recognizer delegate
185+
// ---------------------------------
139186

140187
public func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
141188
let panGestureRecognizer = gestureRecognizer as! UIPanGestureRecognizer
142189
let translation = panGestureRecognizer.translationInView(self.view)
143190
return self.vectorIsMoreHorizontal(translation)
144191
}
192+
193+
}
194+
195+
// MARK: - Utils
196+
197+
extension SOContainerViewController {
198+
private func bringSideViewToFront() {
199+
self.view.bringSubviewToFront(self.contentCoverView)
200+
201+
if let vc = self.sideViewController {
202+
self.view.bringSubviewToFront(vc.view)
203+
}
204+
}
145205

146-
//
147-
// MARK: Internal usage
148-
149-
let LeftViewControllerRightIndent: CGFloat = 56.0
150-
let LeftViewControllerOpenedLeftOffset: CGFloat = 0.0
151-
let SideViewControllerOpenAnimationDuration: NSTimeInterval = 0.24
152-
153-
var _topViewController: UIViewController?
154-
var _leftViewController: UIViewController?
206+
private func createPanGestureRecognizer() -> UIPanGestureRecognizer! {
207+
return UIPanGestureRecognizer.init(target: self, action: #selector(SOContainerViewController.moveMenu(_:)))
208+
}
209+
}
210+
211+
// MARK: - UIPanGesture Geometry Utils
212+
213+
extension SOContainerViewController {
214+
private func vectorIsMoreHorizontal(point: CGPoint) -> Bool {
215+
if fabs(point.x) > fabs(point.y) {
216+
return true
217+
}
218+
return false
219+
}
155220

156-
var contentCoverView: UIView
221+
private func viewPulledOutMoreThanHalfOfItsWidth(viewController: UIViewController) -> Bool {
222+
let frame = viewController.view.frame
223+
return fabs(frame.origin.x) < frame.size.width / 2
224+
}
157225

158-
func contentCoverViewClicked() {
159-
if self.isLeftViewControllerPresented {
160-
self.isLeftViewControllerPresented = false
226+
private func moveSidebarToVector(sidebar: UIView, vector: CGPoint) {
227+
let calculatedXPosition = menuSide == .Left ? min(sidebar.frame.size.width / 2.0, sidebar.center.x + vector.x) :
228+
max(sidebar.frame.size.width / 2.0, sidebar.center.x + vector.x)
229+
230+
let shouldMove = menuSide == .Left ? (calculatedXPosition < sidebar.frame.width / 2) :
231+
(calculatedXPosition - sidebar.frame.width / 2 > SideViewControllerTrailingIndent - SideViewControllerOpenedLeadingOffset)
232+
if shouldMove {
233+
sidebar.center = CGPointMake(calculatedXPosition, sidebar.center.y)
234+
}
235+
}
236+
}
237+
238+
// MARK: - Actions
239+
240+
extension SOContainerViewController {
241+
@IBAction internal func contentCoverViewClicked() {
242+
if self.isSideViewControllerPresented {
243+
self.isSideViewControllerPresented = false
161244
}
162245
}
163246

164-
func moveMenu(panGesture: UIPanGestureRecognizer) {
247+
@IBAction internal func moveMenu(panGesture: UIPanGestureRecognizer) {
165248
panGesture.view?.layer.removeAllAnimations()
166249

167250
let translatedPoint = panGesture.translationInView(self.view)
168251

169252
if panGesture.state == UIGestureRecognizerState.Changed {
170-
if let sidebarView = self.leftViewController?.view {
253+
if let sidebarView = self.sideViewController?.view {
171254
self.moveSidebarToVector(sidebarView, vector: translatedPoint)
172255
}
173256

174257
panGesture.setTranslation(CGPointMake(0, 0), inView: self.view)
175258

176-
if let view = self.leftViewController?.view {
259+
if let view = self.sideViewController?.view {
177260
self.contentCoverView.alpha = 1.0 - abs(view.frame.origin.x) / view.frame.size.width
178261
}
179262
} else if panGesture.state == UIGestureRecognizerState.Ended {
180-
if let sidebar = self.leftViewController {
181-
self.isLeftViewControllerPresented = self.viewPulledOutMoreThanHalfOfItsWidth(sidebar)
263+
if let sidebar = self.sideViewController {
264+
self.isSideViewControllerPresented = self.viewPulledOutMoreThanHalfOfItsWidth(sidebar)
182265
}
183266
}
184267
}
185-
186-
func brindLeftViewToFront() {
187-
self.view.bringSubviewToFront(self.contentCoverView)
268+
}
269+
270+
// MARK: - Autolayout management
271+
272+
extension SOContainerViewController {
273+
public override func viewDidLayoutSubviews() {
274+
super.viewDidLayoutSubviews()
188275

189-
if let vc = self.leftViewController {
190-
self.view.bringSubviewToFront(vc.view)
191-
}
192-
}
193-
194-
func createPanGestureRecognizer() -> UIPanGestureRecognizer! {
195-
return UIPanGestureRecognizer.init(target: self, action: #selector(SOContainerViewController.moveMenu(_:)))
196-
}
197-
198-
func vectorIsMoreHorizontal(point: CGPoint) -> Bool {
199-
if fabs(point.x) > fabs(point.y) {
200-
return true
276+
if menuSide == .Right && !isSideViewControllerPresented {
277+
guard let sideVC = self.sideViewController else {
278+
return
279+
}
280+
281+
var frame = sideVC.view.frame
282+
frame.origin.x = frame.size.width + SideViewControllerTrailingIndent
283+
sideVC.view.frame = frame
201284
}
202-
return false
203-
}
204-
205-
func viewPulledOutMoreThanHalfOfItsWidth(viewController: UIViewController) -> Bool {
206-
let frame = viewController.view.frame
207-
return fabs(frame.origin.x) < frame.size.width / 2
208-
}
209-
210-
func moveSidebarToVector(sidebar: UIView, vector: CGPoint) {
211-
let calculatedXPosition = min(sidebar.frame.size.width / 2.0, sidebar.center.x + vector.x)
212-
sidebar.center = CGPointMake(calculatedXPosition, sidebar.center.y)
213285
}
214-
215286
}

0 commit comments

Comments
 (0)