Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
Material
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Dmitriy Stepanets
Material
Commits
ee61c21c
Commit
ee61c21c
authored
Aug 27, 2015
by
adamdahan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Addition of bottom navigation
parent
4f6d7ab4
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
273 additions
and
21 deletions
+273
-21
Source/SideNavController.swift
+273
-21
No files found.
Source/SideNavController.swift
View file @
ee61c21c
...
...
@@ -56,6 +56,14 @@ public protocol SideNavDelegate {
optional
func
sideNavDidOpenRightViewContainer
(
nav
:
SideNavController
,
container
:
SideNavContainer
)
optional
func
sideNavDidCloseRightViewContainer
(
nav
:
SideNavController
,
container
:
SideNavContainer
)
optional
func
sideNavDidTapRight
(
nav
:
SideNavController
,
container
:
SideNavContainer
)
// bottom
optional
func
sideNavDidBeginBottomPan
(
nav
:
SideNavController
,
container
:
SideNavContainer
)
optional
func
sideNavDidChangeBottomPan
(
nav
:
SideNavController
,
container
:
SideNavContainer
)
optional
func
sideNavDidEndBottomPan
(
nav
:
SideNavController
,
container
:
SideNavContainer
)
optional
func
sideNavDidOpenBottomViewContainer
(
nav
:
SideNavController
,
container
:
SideNavContainer
)
optional
func
sideNavDidCloseBottomViewContainer
(
nav
:
SideNavController
,
container
:
SideNavContainer
)
optional
func
sideNavDidTapBottom
(
nav
:
SideNavController
,
container
:
SideNavContainer
)
}
@objc(SideNavController)
...
...
@@ -71,6 +79,7 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
public
static
var
contentViewOpacity
:
CGFloat
=
0.4
public
static
var
shouldHideStatusBar
:
Bool
=
true
public
static
var
pointOfNoReturnWidth
:
CGFloat
=
48
public
static
var
pointOfNoReturnheight
:
CGFloat
=
48
public
static
var
backdropViewContainerBackgroundColor
:
UIColor
=
.
blackColor
()
public
static
var
animationDuration
:
CGFloat
=
0.5
public
static
var
leftBezelWidth
:
CGFloat
=
16
...
...
@@ -79,6 +88,9 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
public
static
var
rightBezelWidth
:
CGFloat
=
16
public
static
var
rightViewContainerWidth
:
CGFloat
=
270
public
static
var
rightPanFromBezel
:
Bool
=
true
public
static
var
bottomBezelHeight
:
CGFloat
=
16
public
static
var
bottomViewContainerHeight
:
CGFloat
=
270
public
static
var
bottomPanFromBezel
:
Bool
=
true
}
/**
...
...
@@ -111,6 +123,16 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
}
/**
:name: isBottomContainerOpened
*/
public
var
isBottomContainerOpened
:
Bool
{
if
let
c
=
bottomViewContainer
{
return
c
.
frame
.
origin
.
y
==
bottomOriginY
-
c
.
frame
.
size
.
height
}
return
false
}
/**
:name: isUserInteractionEnabled
*/
public
private(set)
var
isUserInteractionEnabled
:
Bool
{
...
...
@@ -143,6 +165,11 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
public
private(set)
var
rightViewContainer
:
UIView
?
/**
:name: bottomViewContainer
*/
public
private(set)
var
bottomViewContainer
:
UIView
?
/**
:name: leftContainer
*/
public
private(set)
var
leftContainer
:
SideNavContainer
?
...
...
@@ -153,6 +180,11 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
public
private(set)
var
rightContainer
:
SideNavContainer
?
/**
:name: bottomContainer
*/
public
private(set)
var
bottomContainer
:
SideNavContainer
?
/**
:name: mainViewController
*/
public
var
mainViewController
:
UIViewController
?
...
...
@@ -168,6 +200,11 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
public
var
rightViewController
:
UIViewController
?
/**
:name: leftViewController
*/
public
var
bottomViewController
:
UIViewController
?
/**
:name: leftPanGesture
*/
public
var
leftPanGesture
:
UIPanGestureRecognizer
?
...
...
@@ -178,15 +215,24 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
public
var
leftTapGesture
:
UITapGestureRecognizer
?
/**
:name: rightTapGesture
*/
public
var
rightTapGesture
:
UITapGestureRecognizer
?
/**
:name: rightTapGesture
*/
public
var
bottomTapGesture
:
UITapGestureRecognizer
?
/**
:name: rightPanGesture
*/
public
var
rightPanGesture
:
UIPanGestureRecognizer
?
/**
:name: rightTap
Gesture
:name: rightPan
Gesture
*/
public
var
rightTapGesture
:
UITap
GestureRecognizer
?
public
var
bottomPanGesture
:
UIPan
GestureRecognizer
?
//
// :name: leftOriginX
...
...
@@ -202,6 +248,13 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
return
view
.
bounds
.
width
}
//
// :name: bottomOriginY
//
private
var
bottomOriginY
:
CGFloat
{
return
view
.
bounds
.
height
}
/**
:name: init
*/
...
...
@@ -241,6 +294,17 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
/**
:name: init
*/
public
convenience
init
(
mainViewController
:
UIViewController
,
bottomViewController
:
UIViewController
)
{
self
.
init
()
self
.
mainViewController
=
mainViewController
self
.
bottomViewController
=
bottomViewController
setupView
()
setupBottomView
()
}
/**
:name: init
*/
public
convenience
init
(
mainViewController
:
UIViewController
,
leftViewController
:
UIViewController
,
rightViewController
:
UIViewController
)
{
self
.
init
()
self
.
mainViewController
=
mainViewController
...
...
@@ -251,6 +315,21 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
setupRightView
()
}
/**
:name: init
*/
public
convenience
init
(
mainViewController
:
UIViewController
,
leftViewController
:
UIViewController
,
bottomViewController
:
UIViewController
,
rightViewController
:
UIViewController
)
{
self
.
init
()
self
.
mainViewController
=
mainViewController
self
.
leftViewController
=
leftViewController
self
.
bottomViewController
=
bottomViewController
self
.
rightViewController
=
rightViewController
setupView
()
setupLeftView
()
setupBottomView
()
setupRightView
()
}
//
// :name: viewDidLoad
//
...
...
@@ -267,6 +346,7 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
prepareContainedViewController
(
&
mainViewContainer
,
viewController
:
&
mainViewController
)
prepareContainedViewController
(
&
leftViewContainer
,
viewController
:
&
leftViewController
)
prepareContainedViewController
(
&
rightViewContainer
,
viewController
:
&
rightViewController
)
prepareContainedViewController
(
&
bottomViewContainer
,
viewController
:
&
bottomViewController
)
}
//
...
...
@@ -277,6 +357,7 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
mainViewContainer
?
.
transform
=
CGAffineTransformMakeScale
(
1
,
1
)
leftViewContainer
?
.
hidden
=
true
rightViewContainer
?
.
hidden
=
true
bottomViewContainer
?
.
hidden
=
true
coordinator
.
animateAlongsideTransition
(
nil
)
{
_
in
self
.
toggleWindow
()
self
.
backdropViewContainer
?
.
layer
.
opacity
=
0
...
...
@@ -296,6 +377,13 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
self
.
removeShadow
(
&
self
.
rightViewContainer
)
self
.
prepareRightGestures
()
}
if
let
vc
=
self
.
bottomViewContainer
{
vc
.
frame
.
origin
.
y
=
self
.
bottomOriginY
vc
.
hidden
=
false
self
.
removeShadow
(
&
self
.
bottomViewContainer
)
self
.
prepareBottomGestures
()
}
}
}
...
...
@@ -364,6 +452,31 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
}
/**
:name: openRightViewContainer
*/
public
func
openBottomViewContainer
(
velocity
:
CGFloat
=
0
)
{
if
let
vc
=
bottomViewContainer
{
if
let
c
=
bottomContainer
{
prepareContainerToOpen
(
&
bottomViewController
,
viewContainer
:
&
bottomViewContainer
,
state
:
c
.
state
)
UIView
.
animateWithDuration
(
Double
(
0
==
velocity
?
options
.
animationDuration
:
fmax
(
0.1
,
fmin
(
1
,
Double
(
fabs
(
vc
.
frame
.
origin
.
y
-
bottomOriginY
)
/
velocity
)))),
delay
:
0
,
options
:
.
CurveEaseInOut
,
animations
:
{
_
in
vc
.
frame
.
origin
.
y
=
self
.
bottomOriginY
-
vc
.
frame
.
size
.
height
self
.
backdropViewContainer
?
.
layer
.
opacity
=
Float
(
options
.
contentViewOpacity
)
self
.
mainViewContainer
?
.
transform
=
CGAffineTransformMakeScale
(
options
.
contentViewScale
,
options
.
contentViewScale
)
}
)
{
_
in
self
.
isUserInteractionEnabled
=
false
self
.
rightViewController
?
.
endAppearanceTransition
()
}
c
.
state
=
.
Opened
delegate
?
.
sideNavDidOpenRightViewContainer
?(
self
,
container
:
c
)
}
}
}
/**
:name: closeLeftViewContainer
*/
public
func
closeLeftViewContainer
(
velocity
:
CGFloat
=
0
)
{
...
...
@@ -416,6 +529,33 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
}
/**
:name: closeRightViewContainer
*/
public
func
closeBottomViewContainer
(
velocity
:
CGFloat
=
0
)
{
if
let
vc
=
bottomViewContainer
{
if
let
c
=
bottomContainer
{
prepareContainerToClose
(
&
bottomViewController
,
state
:
c
.
state
)
UIView
.
animateWithDuration
(
Double
(
0
==
velocity
?
options
.
animationDuration
:
fmax
(
0.1
,
fmin
(
1
,
fabs
(
vc
.
frame
.
origin
.
y
-
bottomOriginY
)
/
velocity
))),
delay
:
0
,
options
:
.
CurveEaseInOut
,
animations
:
{
_
in
vc
.
frame
.
origin
.
y
=
self
.
bottomOriginY
self
.
backdropViewContainer
?
.
layer
.
opacity
=
0
self
.
mainViewContainer
?
.
transform
=
CGAffineTransformMakeScale
(
1
,
1
)
}
)
{
_
in
self
.
removeShadow
(
&
self
.
bottomViewContainer
)
self
.
isUserInteractionEnabled
=
true
self
.
bottomViewController
?
.
endAppearanceTransition
()
}
c
.
state
=
.
Closed
delegate
?
.
sideNavDidCloseBottomViewContainer
?(
self
,
container
:
c
)
}
}
}
/**
:name: switchMainViewController
*/
public
func
switchMainViewController
(
viewController
:
UIViewController
,
closeViewContainers
:
Bool
)
{
...
...
@@ -452,6 +592,18 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
}
}
/**
:name: switchBottomViewController
*/
public
func
switchBottomViewController
(
viewController
:
UIViewController
,
closeBottomViewContainerViewContainer
:
Bool
)
{
removeViewController
(
&
rightViewController
)
rightViewController
=
viewController
prepareContainedViewController
(
&
rightViewContainer
,
viewController
:
&
rightViewController
)
if
closeBottomViewContainerViewContainer
{
closeBottomViewContainer
()
}
}
//
// :name: gestureRecognizer
//
...
...
@@ -462,12 +614,18 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
if
gestureRecognizer
==
rightPanGesture
{
return
gesturePanRightViewController
(
gestureRecognizer
,
withTouchPoint
:
touch
.
locationInView
(
view
))
}
if
gestureRecognizer
==
bottomPanGesture
{
return
gesturePanBottomViewController
(
gestureRecognizer
,
withTouchPoint
:
touch
.
locationInView
(
view
))
}
if
gestureRecognizer
==
leftTapGesture
{
return
isLeftContainerOpened
&&
!
isPointContainedWithinViewController
(
&
leftViewContainer
,
point
:
touch
.
locationInView
(
view
))
}
if
gestureRecognizer
==
rightTapGesture
{
return
isRightContainerOpened
&&
!
isPointContainedWithinViewController
(
&
rightViewContainer
,
point
:
touch
.
locationInView
(
view
))
}
if
gestureRecognizer
==
bottomTapGesture
{
return
isBottomContainerOpened
&&
!
isPointContainedWithinViewController
(
&
bottomViewContainer
,
point
:
touch
.
locationInView
(
view
))
}
return
true
}
...
...
@@ -483,7 +641,7 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
// :name: setupLeftView
//
internal
func
setupLeftView
()
{
prepareContainer
(
&
leftContainer
,
viewContainer
:
&
leftViewContainer
,
originX
:
leftOriginX
,
width
:
options
.
leftViewContainerWidth
)
prepareContainer
(
&
leftContainer
,
viewContainer
:
&
leftViewContainer
,
originX
:
leftOriginX
,
originY
:
0
,
width
:
options
.
leftViewContainerWidth
,
height
:
view
.
bounds
.
size
.
height
)
prepareLeftGestures
()
}
...
...
@@ -491,11 +649,19 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
// :name: setupRightView
//
internal
func
setupRightView
()
{
prepareContainer
(
&
rightContainer
,
viewContainer
:
&
rightViewContainer
,
originX
:
rightOriginX
,
width
:
options
.
rightViewContainerWidth
)
prepareContainer
(
&
rightContainer
,
viewContainer
:
&
rightViewContainer
,
originX
:
rightOriginX
,
originY
:
0
,
width
:
options
.
rightViewContainerWidth
,
height
:
view
.
bounds
.
size
.
height
)
prepareRightGestures
()
}
//
// :name: setupBottomView
//
internal
func
setupBottomView
()
{
prepareContainer
(
&
bottomContainer
,
viewContainer
:
&
bottomViewContainer
,
originX
:
0
,
originY
:
bottomOriginY
,
width
:
view
.
bounds
.
size
.
width
,
height
:
options
.
bottomViewContainerHeight
)
prepareBottomGestures
()
}
//
// :name: addGestures
//
private
func
addGestures
(
inout
pan
:
UIPanGestureRecognizer
?,
panSelector
:
Selector
,
inout
tap
:
UITapGestureRecognizer
?,
tapSelector
:
Selector
)
{
...
...
@@ -641,6 +807,64 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
}
//
// :name: handleRightPanGesture
//
internal
func
handleBottomPanGesture
(
gesture
:
UIPanGestureRecognizer
)
{
if
isLeftContainerOpened
||
isRightContainerOpened
{
return
}
if
.
Began
==
gesture
.
state
{
if
let
vc
=
bottomViewContainer
{
if
let
c
=
bottomContainer
{
bottomViewController
?
.
beginAppearanceTransition
(
!
isBottomContainerOpened
,
animated
:
true
)
addShadow
(
&
bottomViewContainer
)
toggleWindow
(
shouldOpen
:
true
)
c
.
state
=
isBottomContainerOpened
?
.
Opened
:
.
Closed
c
.
point
=
gesture
.
locationInView
(
view
)
c
.
frame
=
vc
.
frame
delegate
?
.
sideNavDidBeginBottomPan
?(
self
,
container
:
c
)
}
}
}
else
if
.
Changed
==
gesture
.
state
{
if
let
vc
=
bottomViewContainer
{
if
let
c
=
bottomContainer
{
c
.
point
=
gesture
.
translationInView
(
gesture
.
view
!
)
let
r
=
(
bottomOriginY
-
vc
.
frame
.
origin
.
y
)
/
vc
.
frame
.
size
.
height
let
s
:
CGFloat
=
1
-
(
1
-
options
.
contentViewScale
)
*
r
let
m
:
CGFloat
=
bottomOriginY
-
vc
.
frame
.
size
.
height
let
y
:
CGFloat
=
c
.
frame
.
origin
.
y
+
c
.
point
.
y
vc
.
frame
.
origin
.
y
=
y
>
bottomOriginY
?
bottomOriginY
:
y
<
m
?
m
:
y
backdropViewContainer
?
.
layer
.
opacity
=
Float
(
r
*
options
.
contentViewOpacity
)
mainViewContainer
?
.
transform
=
CGAffineTransformMakeScale
(
s
,
s
)
delegate
?
.
sideNavDidChangeBottomPan
?(
self
,
container
:
c
)
}
}
}
else
{
if
let
vc
=
bottomViewContainer
{
if
let
c
=
bottomContainer
{
c
.
point
=
gesture
.
velocityInView
(
gesture
.
view
)
let
y
:
CGFloat
=
c
.
point
.
y
<=
-
1000
||
c
.
point
.
y
>=
1000
?
c
.
point
.
y
:
0
c
.
state
=
vc
.
frame
.
origin
.
y
>=
CGFloat
(
floor
(
bottomOriginY
)
-
options
.
pointOfNoReturnheight
)
||
c
.
point
.
y
>=
1000
?
.
Closed
:
.
Opened
if
.
Closed
==
c
.
state
{
closeBottomViewContainer
(
velocity
:
y
)
}
else
{
openBottomViewContainer
(
velocity
:
y
)
}
delegate
?
.
sideNavDidEndBottomPan
?(
self
,
container
:
c
)
}
}
}
}
//
// :name: handleRightTapGesture
//
internal
func
handleBottomTapGesture
(
gesture
:
UIPanGestureRecognizer
)
{
if
let
c
=
bottomContainer
{
delegate
?
.
sideNavDidTapBottom
?(
self
,
container
:
c
)
closeBottomViewContainer
()
}
}
//
// :name: addShadow
//
private
func
addShadow
(
inout
viewContainer
:
UIView
?)
{
...
...
@@ -699,6 +923,20 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
}
//
// :name: gesturePanRightViewController
//
private
func
gesturePanRightViewController
(
gesture
:
UIGestureRecognizer
,
withTouchPoint
point
:
CGPoint
)
->
Bool
{
return
isRightContainerOpened
||
options
.
rightPanFromBezel
&&
isRightPointContainedWithinRect
(
point
)
}
//
// :name: gesturePanRightViewController
//
private
func
gesturePanBottomViewController
(
gesture
:
UIGestureRecognizer
,
withTouchPoint
point
:
CGPoint
)
->
Bool
{
return
isBottomContainerOpened
||
options
.
bottomPanFromBezel
&&
isBottomPointContainedWithinRect
(
point
)
}
//
// :name: isLeftPointContainedWithinRect
//
private
func
isLeftPointContainedWithinRect
(
point
:
CGPoint
)
->
Bool
{
...
...
@@ -710,13 +948,6 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
}
//
// :name: gesturePanRightViewController
//
private
func
gesturePanRightViewController
(
gesture
:
UIGestureRecognizer
,
withTouchPoint
point
:
CGPoint
)
->
Bool
{
return
isRightContainerOpened
||
options
.
rightPanFromBezel
&&
isRightPointContainedWithinRect
(
point
)
}
//
// :name: isRightPointContainedWithinRect
//
private
func
isRightPointContainedWithinRect
(
point
:
CGPoint
)
->
Bool
{
...
...
@@ -728,6 +959,17 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
}
//
// :name: isBottomPointContainedWithinRect
//
private
func
isBottomPointContainedWithinRect
(
point
:
CGPoint
)
->
Bool
{
var
r
:
CGRect
=
CGRectZero
var
t
:
CGRect
=
CGRectZero
let
h
:
CGFloat
=
bottomOriginY
-
options
.
bottomBezelHeight
CGRectDivide
(
view
.
bounds
,
&
t
,
&
r
,
h
,
.
MinYEdge
)
return
CGRectContainsPoint
(
r
,
point
)
}
//
// :name: isPointContainedWithinViewController
//
private
func
isPointContainedWithinViewController
(
inout
viewContainer
:
UIView
?,
point
:
CGPoint
)
->
Bool
{
...
...
@@ -767,13 +1009,31 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
}
//
// :name: prepareRightGestures
//
private
func
prepareRightGestures
()
{
removeGestures
(
&
rightPanGesture
,
tap
:
&
rightTapGesture
)
addGestures
(
&
rightPanGesture
,
panSelector
:
"handleRightPanGesture:"
,
tap
:
&
rightTapGesture
,
tapSelector
:
"handleRightTapGesture:"
)
}
//
// :name: prepareBottomGestures
//
private
func
prepareBottomGestures
()
{
removeGestures
(
&
bottomPanGesture
,
tap
:
&
bottomTapGesture
)
addGestures
(
&
bottomPanGesture
,
panSelector
:
"handleBottomPanGesture:"
,
tap
:
&
bottomTapGesture
,
tapSelector
:
"handleBottomTapGesture:"
)
}
//
// :name: prepareContainer
//
private
func
prepareContainer
(
inout
container
:
SideNavContainer
?,
inout
viewContainer
:
UIView
?,
originX
:
CGFloat
,
width
:
CGFloat
)
{
private
func
prepareContainer
(
inout
container
:
SideNavContainer
?,
inout
viewContainer
:
UIView
?,
originX
:
CGFloat
,
originY
:
CGFloat
,
width
:
CGFloat
,
height
:
CGFloat
)
{
container
=
SideNavContainer
(
state
:
.
Closed
,
point
:
CGPointZero
,
frame
:
CGRectZero
)
var
b
:
CGRect
=
view
.
bounds
b
.
size
.
width
=
width
b
.
size
.
height
=
height
b
.
origin
.
x
=
originX
b
.
origin
.
y
=
originY
viewContainer
=
UIView
(
frame
:
b
)
viewContainer
!.
backgroundColor
=
.
clearColor
()
viewContainer
!.
autoresizingMask
=
.
FlexibleHeight
...
...
@@ -781,14 +1041,6 @@ public class SideNavController: MaterialViewController, UIGestureRecognizerDeleg
}
//
// :name: prepareRightGestures
//
private
func
prepareRightGestures
()
{
removeGestures
(
&
rightPanGesture
,
tap
:
&
rightTapGesture
)
addGestures
(
&
rightPanGesture
,
panSelector
:
"handleRightPanGesture:"
,
tap
:
&
rightTapGesture
,
tapSelector
:
"handleRightTapGesture:"
)
}
//
// :name: prepareContainerToOpen
//
private
func
prepareContainerToOpen
(
inout
viewController
:
UIViewController
?,
inout
viewContainer
:
UIView
?,
state
:
SideNavState
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment