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
ffaaea85
Unverified
Commit
ffaaea85
authored
Dec 30, 2016
by
Daniel Dahan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
development: added BottomSheetController and BottomSheet
parent
4b8a39b8
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
928 additions
and
115 deletions
+928
-115
Material.xcodeproj/project.pbxproj
+16
-0
Sources/iOS/BottomSheet.swift
+35
-0
Sources/iOS/BottomSheetController.swift
+728
-0
Sources/iOS/Menu.swift
+3
-3
Sources/iOS/NavigationDrawerController.swift
+146
-112
No files found.
Material.xcodeproj/project.pbxproj
View file @
ffaaea85
...
...
@@ -9,6 +9,8 @@
/* Begin PBXBuildFile section */
961730361E0E156400A9A297
/* SpringMotion.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
961730351E0E156400A9A297
/* SpringMotion.swift */
;
};
9617305A1E145DE900A9A297
/* CollectionViewCard.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
961730591E145DE900A9A297
/* CollectionViewCard.swift */
;
};
961730701E16EFFF00A9A297
/* BottomSheet.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
9617306F1E16EFFF00A9A297
/* BottomSheet.swift */
;
};
961730721E16F00C00A9A297
/* BottomSheetController.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
961730711E16F00C00A9A297
/* BottomSheetController.swift */
;
};
9617B07D1DFCA8CF00410F8F
/* Application.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
961E6BDE1DDA2A95004E6C93
/* Application.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
9617B07E1DFCA8CF00410F8F
/* Card.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB75D1CB40DC500C806FE
/* Card.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
9617B07F1DFCA8CF00410F8F
/* ImageCard.swift in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96BCB7621CB40DC500C806FE
/* ImageCard.swift */
;
settings
=
{
ATTRIBUTES
=
(
Public
,
);
};
};
...
...
@@ -228,6 +230,8 @@
961276621DCD8B1800A7D920
/* CharacterAttribute.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CharacterAttribute.swift
;
sourceTree
=
"<group>"
;
};
961730351E0E156400A9A297
/* SpringMotion.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
SpringMotion.swift
;
sourceTree
=
"<group>"
;
};
961730591E145DE900A9A297
/* CollectionViewCard.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CollectionViewCard.swift
;
sourceTree
=
"<group>"
;
};
9617306F1E16EFFF00A9A297
/* BottomSheet.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
BottomSheet.swift
;
sourceTree
=
"<group>"
;
};
961730711E16F00C00A9A297
/* BottomSheetController.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
BottomSheetController.swift
;
sourceTree
=
"<group>"
;
};
961DED451DCC40C500F425B6
/* Editor.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Editor.swift
;
sourceTree
=
"<group>"
;
};
961DED4A1DCC546100F425B6
/* EditorController.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
EditorController.swift
;
sourceTree
=
"<group>"
;
};
961E6BDE1DDA2A95004E6C93
/* Application.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
Application.swift
;
sourceTree
=
"<group>"
;
};
...
...
@@ -386,6 +390,15 @@
name
=
TextField
;
sourceTree
=
"<group>"
;
};
9617306E1E16EFE300A9A297
/* BottomSheet */
=
{
isa
=
PBXGroup
;
children
=
(
9617306F1E16EFFF00A9A297
/* BottomSheet.swift */
,
961730711E16F00C00A9A297
/* BottomSheetController.swift */
,
);
name
=
BottomSheet
;
sourceTree
=
"<group>"
;
};
961DED441DCC40AC00F425B6
/* Editor */
=
{
isa
=
PBXGroup
;
children
=
(
...
...
@@ -627,6 +640,7 @@
children
=
(
961E6BDD1DDA2A7E004E6C93
/* Application */
,
96264BE41D833C8400576F37
/* Bar */
,
9617306E1E16EFE300A9A297
/* BottomSheet */
,
962DDD081D6FBBD0001C307C
/* BottomTabBar */
,
96BCB8031CB40F4B00C806FE
/* Button */
,
96BCB8021CB40F3B00C806FE
/* Card */
,
...
...
@@ -1200,6 +1214,7 @@
965E80E51DD4C53300D61E4B
/* PulseMotion.swift in Sources */
,
965E80FE1DD4D59500D61E4B
/* ToolbarController.swift in Sources */
,
96328B971E05C0BB009A4C90
/* TableView.swift in Sources */
,
961730701E16EFFF00A9A297
/* BottomSheet.swift in Sources */
,
965E80C81DD4C50600D61E4B
/* Motion.swift in Sources */
,
965E80C91DD4C50600D61E4B
/* TransitionMotion.swift in Sources */
,
965E80CA1DD4C50600D61E4B
/* KeyframeMotion.swift in Sources */
,
...
...
@@ -1222,6 +1237,7 @@
965E80D51DD4C50600D61E4B
/* Grid.swift in Sources */
,
965E80D61DD4C50600D61E4B
/* HeightPreset.swift in Sources */
,
961E6BDF1DDA2A95004E6C93
/* Application.swift in Sources */
,
961730721E16F00C00A9A297
/* BottomSheetController.swift in Sources */
,
965E80D71DD4C50600D61E4B
/* Icon.swift in Sources */
,
965E80FC1DD4D59500D61E4B
/* SearchBarController.swift in Sources */
,
965E80D81DD4C50600D61E4B
/* Layer.swift in Sources */
,
...
...
Sources/iOS/BottomSheet.swift
0 → 100644
View file @
ffaaea85
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import
UIKit
class
BottomSheet
:
CollectionViewCard
{
}
Sources/iOS/BottomSheetController.swift
0 → 100644
View file @
ffaaea85
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import
UIKit
@objc(BottomSheetPosition)
public
enum
BottomSheetPosition
:
Int
{
case
left
case
right
}
extension
UIViewController
{
/**
A convenience property that provides access to the BottomSheetController.
This is the recommended method of accessing the BottomSheetController
through child UIViewControllers.
*/
public
var
bottomSheetController
:
BottomSheetController
?
{
var
viewController
:
UIViewController
?
=
self
while
nil
!=
viewController
{
if
viewController
is
BottomSheetController
{
return
viewController
as?
BottomSheetController
}
viewController
=
viewController
?
.
parent
}
return
nil
}
}
@objc(BottomSheetControllerDelegate)
public
protocol
BottomSheetControllerDelegate
{
/**
An optional delegation method that is fired before the
BottomSheetController opens.
- Parameter bottomSheetController: A BottomSheetController.
- Parameter position: The BottomSheetPosition.
*/
@objc
optional
func
bottomSheetController
(
bottomSheetController
:
BottomSheetController
,
willOpen
position
:
BottomSheetPosition
)
/**
An optional delegation method that is fired after the
BottomSheetController opened.
- Parameter bottomSheetController: A BottomSheetController.
- Parameter position: The BottomSheetPosition.
*/
@objc
optional
func
bottomSheetController
(
bottomSheetController
:
BottomSheetController
,
didOpen
position
:
BottomSheetPosition
)
/**
An optional delegation method that is fired before the
BottomSheetController closes.
- Parameter bottomSheetController: A BottomSheetController.
- Parameter position: The BottomSheetPosition.
*/
@objc
optional
func
bottomSheetController
(
bottomSheetController
:
BottomSheetController
,
willClose
position
:
BottomSheetPosition
)
/**
An optional delegation method that is fired after the
BottomSheetController closed.
- Parameter bottomSheetController: A BottomSheetController.
- Parameter position: The BottomSheetPosition.
*/
@objc
optional
func
bottomSheetController
(
bottomSheetController
:
BottomSheetController
,
didClose
position
:
BottomSheetPosition
)
/**
An optional delegation method that is fired when the
BottomSheetController pan gesture begins.
- Parameter bottomSheetController: A BottomSheetController.
- Parameter didBeginPanAt point: A CGPoint.
- Parameter position: The BottomSheetPosition.
*/
@objc
optional
func
bottomSheetController
(
bottomSheetController
:
BottomSheetController
,
didBeginPanAt
point
:
CGPoint
,
position
:
BottomSheetPosition
)
/**
An optional delegation method that is fired when the
BottomSheetController pan gesture changes position.
- Parameter bottomSheetController: A BottomSheetController.
- Parameter didChangePanAt point: A CGPoint.
- Parameter position: The BottomSheetPosition.
*/
@objc
optional
func
bottomSheetController
(
bottomSheetController
:
BottomSheetController
,
didChangePanAt
point
:
CGPoint
,
position
:
BottomSheetPosition
)
/**
An optional delegation method that is fired when the
BottomSheetController pan gesture ends.
- Parameter bottomSheetController: A BottomSheetController.
- Parameter didEndPanAt point: A CGPoint.
- Parameter position: The BottomSheetPosition.
*/
@objc
optional
func
bottomSheetController
(
bottomSheetController
:
BottomSheetController
,
didEndPanAt
point
:
CGPoint
,
position
:
BottomSheetPosition
)
/**
An optional delegation method that is fired when the
BottomSheetController tap gesture executes.
- Parameter bottomSheetController: A BottomSheetController.
- Parameter didTapAt point: A CGPoint.
- Parameter position: The BottomSheetPosition.
*/
@objc
optional
func
bottomSheetController
(
bottomSheetController
:
BottomSheetController
,
didTapAt
point
:
CGPoint
,
position
:
BottomSheetPosition
)
/**
An optional delegation method that is fired when the
status bar is about to change display, isHidden or not.
- Parameter bottomSheetController: A BottomSheetController.
- Parameter statusBar isHidden: A boolean.
*/
@objc
optional
func
bottomSheetController
(
bottomSheetController
:
BottomSheetController
,
statusBar
isHidden
:
Bool
)
}
@objc(BottomSheetController)
open
class
BottomSheetController
:
RootController
{
/**
A CGFloat property that is used internally to track
the original (x) position of the container view when panning.
*/
fileprivate
var
originalX
:
CGFloat
=
0
/**
A UIPanGestureRecognizer property internally used for the
bottomView pan gesture.
*/
internal
fileprivate
(
set
)
var
bottomPanGesture
:
UIPanGestureRecognizer
?
/**
A UITapGestureRecognizer property internally used for the
bottomView tap gesture.
*/
internal
fileprivate
(
set
)
var
bottomTapGesture
:
UITapGestureRecognizer
?
/**
A CGFloat property that accesses the bottomView threshold of
the BottomSheetController. When the panning gesture has
ended, if the position is beyond the threshold,
the bottomView is opened, if it is below the threshold, the
bottomView is closed.
*/
@IBInspectable
open
var
bottomThreshold
:
CGFloat
=
64
fileprivate
var
bottomViewThreshold
:
CGFloat
=
0
/**
A BottomSheetControllerDelegate property used to bind
the delegation object.
*/
open
weak
var
delegate
:
BottomSheetControllerDelegate
?
/**
A CGFloat property that sets the animation duration of the
bottomView when closing and opening. Defaults to 0.25.
*/
@IBInspectable
open
var
animationDuration
:
TimeInterval
=
0.25
/**
A Boolean property that enables and disables the bottomView from
opening and closing. Defaults to true.
*/
@IBInspectable
open
var
isEnabled
:
Bool
{
get
{
return
isBottomViewEnabled
}
set
(
value
)
{
if
nil
!=
bottomView
{
isBottomViewEnabled
=
value
}
}
}
/**
A Boolean property that enables and disables the bottomView from
opening and closing. Defaults to true.
*/
@IBInspectable
open
var
isBottomViewEnabled
=
false
{
didSet
{
isBottomPanGestureEnabled
=
isBottomViewEnabled
isBottomTapGestureEnabled
=
isBottomViewEnabled
}
}
/// Enables the left pan gesture.
@IBInspectable
open
var
isBottomPanGestureEnabled
=
false
{
didSet
{
if
isBottomPanGestureEnabled
{
prepareBottomPanGesture
()
}
else
{
removeBottomPanGesture
()
}
}
}
/// Enables the left tap gesture.
@IBInspectable
open
var
isBottomTapGestureEnabled
=
false
{
didSet
{
if
isBottomTapGestureEnabled
{
prepareBottomTapGesture
()
}
else
{
removeBottomTapGesture
()
}
}
}
/**
A DepthPreset property that is used to set the depth of the
bottomView when opened.
*/
open
var
depthPreset
=
DepthPreset
.
depth1
/**
A UIView property that is used to hide and reveal the
bottomViewController. It is very rare that this property will
need to be accessed externally.
*/
open
fileprivate
(
set
)
var
bottomView
:
UIView
?
/// Indicates whether the bottomView or rightView is opened.
open
var
isOpened
:
Bool
{
return
isBottomViewOpened
}
/// indicates if the bottomView is opened.
open
var
isBottomViewOpened
:
Bool
{
guard
nil
!=
bottomView
else
{
return
false
}
return
bottomView
!.
x
!=
-
bottomViewWidth
}
/**
A UIViewController property that references the
active left UIViewController.
*/
open
fileprivate
(
set
)
var
bottomViewController
:
UIViewController
?
/**
A CGFloat property to access the width that the bottomView
opens up to.
*/
@IBInspectable
open
fileprivate
(
set
)
var
bottomViewWidth
:
CGFloat
!
/**
An initializer that initializes the object with a NSCoder object.
- Parameter aDecoder: A NSCoder instance.
*/
public
required
init
?(
coder
aDecoder
:
NSCoder
)
{
super
.
init
(
coder
:
aDecoder
)
prepare
()
}
/**
An initializer that initializes the object with an Optional nib and bundle.
- Parameter nibNameOrNil: An Optional String for the nib.
- Parameter bundle: An Optional NSBundle where the nib is located.
*/
public
override
init
(
nibName
nibNameOrNil
:
String
?,
bundle
nibBundleOrNil
:
Bundle
?)
{
super
.
init
(
nibName
:
nibNameOrNil
,
bundle
:
nibBundleOrNil
)
prepare
()
}
/**
An initializer for the BottomSheetController.
- Parameter rootViewController: The main UIViewController.
- Parameter bottomViewController: An Optional left UIViewController.
*/
public
init
(
rootViewController
:
UIViewController
,
bottomViewController
:
UIViewController
?
=
nil
)
{
super
.
init
(
rootViewController
:
rootViewController
)
self
.
bottomViewController
=
bottomViewController
prepare
()
}
/// Layout subviews.
open
override
func
layoutSubviews
()
{
super
.
layoutSubviews
()
guard
let
v
=
bottomView
else
{
return
}
v
.
width
=
bottomViewWidth
v
.
height
=
view
.
bounds
.
height
bottomViewThreshold
=
bottomViewWidth
/
2
guard
let
vc
=
bottomViewController
else
{
return
}
vc
.
view
.
width
=
v
.
width
vc
.
view
.
height
=
v
.
height
vc
.
view
.
center
=
CGPoint
(
x
:
v
.
width
/
2
,
y
:
v
.
height
/
2
)
}
/**
Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepare method
to initialize property values and other setup operations.
The super.prepare method should always be called immediately
when subclassing.
*/
open
override
func
prepare
()
{
super
.
prepare
()
prepareBottomView
()
}
/**
A method that is used to set the width of the bottomView when
opened. This is the recommended method of setting the bottomView
width.
- Parameter width: A CGFloat value to set as the new width.
- Parameter isHidden: A Boolean value of whether the bottomView
should be isHidden after the width has been updated or not.
- Parameter animated: A Boolean value that indicates to animate
the bottomView width change.
*/
open
func
setBottomViewHeight
(
width
:
CGFloat
,
isHidden
:
Bool
,
animated
:
Bool
,
duration
:
TimeInterval
=
0.5
)
{
guard
let
v
=
bottomView
else
{
return
}
bottomViewWidth
=
width
if
animated
{
v
.
isShadowPathAutoSizing
=
false
if
isHidden
{
UIView
.
animate
(
withDuration
:
duration
,
animations
:
{
[
weak
self
]
in
guard
let
s
=
self
else
{
return
}
v
.
bounds
.
size
.
width
=
width
v
.
position
.
x
=
-
width
/
2
s
.
rootViewController
.
view
.
alpha
=
1
})
{
[
weak
self
]
_
in
guard
let
s
=
self
else
{
return
}
v
.
isShadowPathAutoSizing
=
true
s
.
layoutSubviews
()
s
.
hideView
(
container
:
v
)
}
}
else
{
UIView
.
animate
(
withDuration
:
duration
,
animations
:
{
[
weak
self
]
in
guard
let
s
=
self
else
{
return
}
v
.
bounds
.
size
.
width
=
width
v
.
position
.
x
=
width
/
2
s
.
rootViewController
.
view
.
alpha
=
0.5
})
{
[
weak
self
]
_
in
guard
let
s
=
self
else
{
return
}
v
.
isShadowPathAutoSizing
=
true
s
.
layoutSubviews
()
s
.
showView
(
container
:
v
)
}
}
}
else
{
v
.
bounds
.
size
.
width
=
width
if
isHidden
{
hideView
(
container
:
v
)
v
.
position
.
x
=
-
v
.
width
/
2
rootViewController
.
view
.
alpha
=
1
}
else
{
v
.
isShadowPathAutoSizing
=
false
showView
(
container
:
v
)
v
.
position
.
x
=
width
/
2
rootViewController
.
view
.
alpha
=
0.5
v
.
isShadowPathAutoSizing
=
true
}
layoutSubviews
()
}
}
/**
A method that toggles the bottomView opened if previously closed,
or closed if previously opened.
- Parameter velocity: A CGFloat value that sets the
velocity of the user interaction when animating the
bottomView. Defaults to 0.
*/
open
func
toggleBottomView
(
velocity
:
CGFloat
=
0
)
{
isBottomViewOpened
?
closeBottomView
(
velocity
:
velocity
)
:
openBottomView
(
velocity
:
velocity
)
}
/**
A method that opens the bottomView.
- Parameter velocity: A CGFloat value that sets the
velocity of the user interaction when animating the
bottomView. Defaults to 0.
*/
open
func
openBottomView
(
velocity
:
CGFloat
=
0
)
{
guard
isBottomViewEnabled
else
{
return
}
guard
let
v
=
bottomView
else
{
return
}
showView
(
container
:
v
)
isUserInteractionEnabled
=
false
delegate
?
.
bottomSheetController
?(
bottomSheetController
:
self
,
willOpen
:
.
left
)
UIView
.
animate
(
withDuration
:
TimeInterval
(
0
==
velocity
?
animationDuration
:
fmax
(
0.1
,
fmin
(
1
,
Double
(
v
.
x
/
velocity
)))),
animations
:
{
[
weak
self
,
v
=
v
]
in
guard
let
s
=
self
else
{
return
}
v
.
position
.
x
=
v
.
width
/
2
s
.
rootViewController
.
view
.
alpha
=
0.5
})
{
[
weak
self
]
_
in
guard
let
s
=
self
else
{
return
}
s
.
delegate
?
.
bottomSheetController
?(
bottomSheetController
:
s
,
didOpen
:
.
left
)
}
}
/**
A method that closes the bottomView.
- Parameter velocity: A CGFloat value that sets the
velocity of the user interaction when animating the
bottomView. Defaults to 0.
*/
open
func
closeBottomView
(
velocity
:
CGFloat
=
0
)
{
guard
isBottomViewEnabled
else
{
return
}
guard
let
v
=
bottomView
else
{
return
}
isUserInteractionEnabled
=
true
delegate
?
.
bottomSheetController
?(
bottomSheetController
:
self
,
willClose
:
.
left
)
UIView
.
animate
(
withDuration
:
TimeInterval
(
0
==
velocity
?
animationDuration
:
fmax
(
0.1
,
fmin
(
1
,
Double
(
v
.
x
/
velocity
)))),
animations
:
{
[
weak
self
,
v
=
v
]
in
guard
let
s
=
self
else
{
return
}
v
.
position
.
x
=
-
v
.
width
/
2
s
.
rootViewController
.
view
.
alpha
=
1
})
{
[
weak
self
]
_
in
guard
let
s
=
self
else
{
return
}
s
.
hideView
(
container
:
v
)
s
.
delegate
?
.
bottomSheetController
?(
bottomSheetController
:
s
,
didClose
:
.
left
)
}
}
/// A method that removes the passed in pan and bottomView tap gesture recognizers.
fileprivate
func
removeBottomViewGestures
()
{
removeBottomPanGesture
()
removeBottomTapGesture
()
}
/// Removes the left pan gesture.
fileprivate
func
removeBottomPanGesture
()
{
guard
let
v
=
bottomPanGesture
else
{
return
}
view
.
removeGestureRecognizer
(
v
)
bottomPanGesture
=
nil
}
/// Removes the left tap gesture.
fileprivate
func
removeBottomTapGesture
()
{
guard
let
v
=
bottomTapGesture
else
{
return
}
view
.
removeGestureRecognizer
(
v
)
bottomTapGesture
=
nil
}
/**
A method that determines whether the passed point is
contained within the bounds of the bottomViewThreshold
and height of the BottomSheetController view frame
property.
- Parameter point: A CGPoint to test against.
- Returns: A Boolean of the result, true if yes, false
otherwise.
*/
fileprivate
func
isPointContainedWithinBottomThreshold
(
point
:
CGPoint
)
->
Bool
{
return
point
.
x
<=
bottomThreshold
}
/**
A method that determines whether the passed in point is
contained within the bounds of the passed in container view.
- Parameter container: A UIView that sets the bounds to test
against.
- Parameter point: A CGPoint to test whether or not it is
within the bounds of the container parameter.
- Returns: A Boolean of the result, true if yes, false
otherwise.
*/
fileprivate
func
isPointContainedWithinView
(
container
:
UIView
,
point
:
CGPoint
)
->
Bool
{
return
container
.
bounds
.
contains
(
point
)
}
/**
A method that shows a view.
- Parameter container: A container view.
*/
fileprivate
func
showView
(
container
:
UIView
)
{
container
.
depthPreset
=
depthPreset
container
.
isHidden
=
false
}
/**
A method that hides a view.
- Parameter container: A container view.
*/
fileprivate
func
hideView
(
container
:
UIView
)
{
container
.
depthPreset
=
.
none
container
.
isHidden
=
true
}
}
extension
BottomSheetController
{
/// A method that prepares the bottomViewController.
fileprivate
func
prepareBottomViewController
()
{
guard
let
v
=
bottomView
else
{
return
}
prepare
(
viewController
:
bottomViewController
,
withContainer
:
v
)
}
/// A method that prepares the bottomView.
fileprivate
func
prepareBottomView
()
{
guard
nil
!=
bottomViewController
else
{
return
}
isBottomViewEnabled
=
true
bottomViewWidth
=
.
phone
==
Device
.
userInterfaceIdiom
?
280
:
320
bottomView
=
UIView
()
bottomView
!.
frame
=
CGRect
(
x
:
0
,
y
:
0
,
width
:
bottomViewWidth
,
height
:
view
.
height
)
bottomView
!.
backgroundColor
=
nil
view
.
addSubview
(
bottomView
!
)
bottomView
!.
isHidden
=
true
bottomView
!.
position
.
x
=
-
bottomViewWidth
/
2
bottomView
!.
zPosition
=
2000
prepareBottomViewController
()
}
/// Prepare the left pan gesture.
fileprivate
func
prepareBottomPanGesture
()
{
guard
nil
==
bottomPanGesture
else
{
return
}
bottomPanGesture
=
UIPanGestureRecognizer
(
target
:
self
,
action
:
#selector(
handleBottomViewPanGesture(recognizer:)
)
)
bottomPanGesture
!.
delegate
=
self
view
.
addGestureRecognizer
(
bottomPanGesture
!
)
}
/// Prepare the left tap gesture.
fileprivate
func
prepareBottomTapGesture
()
{
guard
nil
==
bottomTapGesture
else
{
return
}
bottomTapGesture
=
UITapGestureRecognizer
(
target
:
self
,
action
:
#selector(
handleBottomViewTapGesture(recognizer:)
)
)
bottomTapGesture
!.
delegate
=
self
bottomTapGesture
!.
cancelsTouchesInView
=
false
view
.
addGestureRecognizer
(
bottomTapGesture
!
)
}
}
extension
BottomSheetController
:
UIGestureRecognizerDelegate
{
/**
Detects the gesture recognizer being used.
- Parameter gestureRecognizer: A UIGestureRecognizer to detect.
- Parameter touch: The UITouch event.
- Returns: A Boolean of whether to continue the gesture or not.
*/
@objc
open
func
gestureRecognizer
(
_
gestureRecognizer
:
UIGestureRecognizer
,
shouldReceive
touch
:
UITouch
)
->
Bool
{
if
gestureRecognizer
==
bottomPanGesture
&&
(
isBottomViewOpened
||
isPointContainedWithinBottomThreshold
(
point
:
touch
.
location
(
in
:
view
)))
{
return
true
}
if
isBottomViewOpened
&&
gestureRecognizer
==
bottomTapGesture
{
return
true
}
return
false
}
/**
A method that is fired when the pan gesture is recognized
for the bottomView.
- Parameter recognizer: A UIPanGestureRecognizer that is
passed to the handler when recognized.
*/
@objc
fileprivate
func
handleBottomViewPanGesture
(
recognizer
:
UIPanGestureRecognizer
)
{
guard
isBottomViewEnabled
&&
(
isBottomViewOpened
||
isPointContainedWithinBottomThreshold
(
point
:
recognizer
.
location
(
in
:
view
)))
else
{
return
}
guard
let
v
=
bottomView
else
{
return
}
let
point
=
recognizer
.
location
(
in
:
view
)
// Animate the panel.
switch
recognizer
.
state
{
case
.
began
:
originalX
=
v
.
position
.
x
showView
(
container
:
v
)
delegate
?
.
bottomSheetController
?(
bottomSheetController
:
self
,
didBeginPanAt
:
point
,
position
:
.
left
)
case
.
changed
:
let
w
=
v
.
width
let
translationX
=
recognizer
.
translation
(
in
:
v
)
.
x
v
.
position
.
x
=
originalX
+
translationX
>
(
w
/
2
)
?
(
w
/
2
)
:
originalX
+
translationX
let
a
=
1
-
v
.
position
.
x
/
v
.
width
rootViewController
.
view
.
alpha
=
0.5
<
a
&&
v
.
position
.
x
<=
v
.
width
/
2
?
a
:
0.5
delegate
?
.
bottomSheetController
?(
bottomSheetController
:
self
,
didChangePanAt
:
point
,
position
:
.
left
)
case
.
ended
,
.
cancelled
,
.
failed
:
let
p
=
recognizer
.
velocity
(
in
:
recognizer
.
view
)
let
x
=
p
.
x
>=
1000
||
p
.
x
<=
-
1000
?
p
.
x
:
0
delegate
?
.
bottomSheetController
?(
bottomSheetController
:
self
,
didEndPanAt
:
point
,
position
:
.
left
)
if
v
.
x
<=
-
bottomViewWidth
+
bottomViewThreshold
||
x
<
-
1000
{
closeBottomView
(
velocity
:
x
)
}
else
{
openBottomView
(
velocity
:
x
)
}
case
.
possible
:
break
}
}
/**
A method that is fired when the tap gesture is recognized
for the bottomView.
- Parameter recognizer: A UITapGestureRecognizer that is
passed to the handler when recognized.
*/
@objc
fileprivate
func
handleBottomViewTapGesture
(
recognizer
:
UITapGestureRecognizer
)
{
guard
isBottomViewOpened
else
{
return
}
guard
let
v
=
bottomView
else
{
return
}
delegate
?
.
bottomSheetController
?(
bottomSheetController
:
self
,
didTapAt
:
recognizer
.
location
(
in
:
view
),
position
:
.
left
)
guard
isBottomViewEnabled
&&
isBottomViewOpened
&&
!
isPointContainedWithinView
(
container
:
v
,
point
:
recognizer
.
location
(
in
:
v
))
else
{
return
}
closeBottomView
()
}
}
Sources/iOS/Menu.swift
View file @
ffaaea85
...
...
@@ -175,7 +175,7 @@ open class Menu: Button {
open
override
func
prepare
()
{
super
.
prepare
()
prepareCard
()
prepareC
ollectionViewC
ard
()
prepareHandler
()
}
...
...
@@ -187,8 +187,8 @@ open class Menu: Button {
}
extension
Menu
{
/// Prepares the card.
fileprivate
func
prepareCard
()
{
/// Prepares the c
ollectionViewC
ard.
fileprivate
func
prepareC
ollectionViewC
ard
()
{
collectionViewCard
.
collectionView
.
delegate
=
self
collectionViewCard
.
collectionView
.
dataSource
=
self
collectionViewCard
.
collectionView
.
register
(
MenuCollectionViewCell
.
self
,
forCellWithReuseIdentifier
:
"MenuCollectionViewCell"
)
...
...
Sources/iOS/NavigationDrawerController.swift
View file @
ffaaea85
...
...
@@ -181,7 +181,8 @@ open class NavigationDrawerController: RootController {
the leftView is opened, if it is below the threshold, the
leftView is closed.
*/
@IBInspectable
public
var
leftThreshold
:
CGFloat
=
64
@IBInspectable
open
var
leftThreshold
:
CGFloat
=
64
fileprivate
var
leftViewThreshold
:
CGFloat
=
0
/**
...
...
@@ -191,7 +192,8 @@ open class NavigationDrawerController: RootController {
the rightView is closed, if it is below the threshold, the
rightView is opened.
*/
@IBInspectable
public
var
rightThreshold
:
CGFloat
=
64
@IBInspectable
open
var
rightThreshold
:
CGFloat
=
64
fileprivate
var
rightViewThreshold
:
CGFloat
=
0
/**
...
...
@@ -505,36 +507,45 @@ open class NavigationDrawerController: RootController {
if
hide
{
UIView
.
animate
(
withDuration
:
duration
,
animations
:
{
[
weak
self
]
in
if
let
s
=
self
{
v
.
bounds
.
size
.
width
=
width
v
.
position
.
x
=
-
width
/
2
s
.
rootViewController
.
view
.
alpha
=
1
guard
let
s
=
self
else
{
return
}
v
.
bounds
.
size
.
width
=
width
v
.
position
.
x
=
-
width
/
2
s
.
rootViewController
.
view
.
alpha
=
1
})
{
[
weak
self
]
_
in
if
let
s
=
self
{
v
.
isShadowPathAutoSizing
=
true
s
.
layoutSubviews
()
s
.
hideView
(
container
:
v
)
guard
let
s
=
self
else
{
return
}
v
.
isShadowPathAutoSizing
=
true
s
.
layoutSubviews
()
s
.
hideView
(
container
:
v
)
}
}
else
{
UIView
.
animate
(
withDuration
:
duration
,
animations
:
{
[
weak
self
]
in
if
let
s
=
self
{
v
.
bounds
.
size
.
width
=
width
v
.
position
.
x
=
width
/
2
s
.
rootViewController
.
view
.
alpha
=
0.5
guard
let
s
=
self
else
{
return
}
v
.
bounds
.
size
.
width
=
width
v
.
position
.
x
=
width
/
2
s
.
rootViewController
.
view
.
alpha
=
0.5
})
{
[
weak
self
]
_
in
if
let
s
=
self
{
v
.
isShadowPathAutoSizing
=
true
s
.
layoutSubviews
()
s
.
showView
(
container
:
v
)
guard
let
s
=
self
else
{
return
}
v
.
isShadowPathAutoSizing
=
true
s
.
layoutSubviews
()
s
.
showView
(
container
:
v
)
}
}
}
else
{
v
.
bounds
.
size
.
width
=
width
if
hide
{
hideView
(
container
:
v
)
v
.
position
.
x
=
-
v
.
width
/
2
...
...
@@ -547,6 +558,7 @@ open class NavigationDrawerController: RootController {
rootViewController
.
view
.
alpha
=
0.5
v
.
isShadowPathAutoSizing
=
true
}
layoutSubviews
()
}
}
...
...
@@ -580,36 +592,45 @@ open class NavigationDrawerController: RootController {
if
hide
{
UIView
.
animate
(
withDuration
:
duration
,
animations
:
{
[
weak
self
]
in
if
let
s
=
self
{
v
.
bounds
.
size
.
width
=
width
v
.
position
.
x
=
s
.
view
.
bounds
.
width
+
width
/
2
s
.
rootViewController
.
view
.
alpha
=
1
guard
let
s
=
self
else
{
return
}
v
.
bounds
.
size
.
width
=
width
v
.
position
.
x
=
s
.
view
.
bounds
.
width
+
width
/
2
s
.
rootViewController
.
view
.
alpha
=
1
})
{
[
weak
self
]
_
in
if
let
s
=
self
{
v
.
isShadowPathAutoSizing
=
true
s
.
layoutSubviews
()
s
.
hideView
(
container
:
v
)
guard
let
s
=
self
else
{
return
}
v
.
isShadowPathAutoSizing
=
true
s
.
layoutSubviews
()
s
.
hideView
(
container
:
v
)
}
}
else
{
UIView
.
animate
(
withDuration
:
duration
,
animations
:
{
[
weak
self
]
in
if
let
s
=
self
{
v
.
bounds
.
size
.
width
=
width
v
.
position
.
x
=
s
.
view
.
bounds
.
width
-
width
/
2
s
.
rootViewController
.
view
.
alpha
=
0.5
guard
let
s
=
self
else
{
return
}
v
.
bounds
.
size
.
width
=
width
v
.
position
.
x
=
s
.
view
.
bounds
.
width
-
width
/
2
s
.
rootViewController
.
view
.
alpha
=
0.5
})
{
[
weak
self
]
_
in
if
let
s
=
self
{
v
.
isShadowPathAutoSizing
=
true
s
.
layoutSubviews
()
s
.
showView
(
container
:
v
)
guard
let
s
=
self
else
{
return
}
v
.
isShadowPathAutoSizing
=
true
s
.
layoutSubviews
()
s
.
showView
(
container
:
v
)
}
}
}
else
{
v
.
bounds
.
size
.
width
=
width
if
hide
{
hideView
(
container
:
v
)
v
.
position
.
x
=
view
.
bounds
.
width
+
v
.
width
/
2
...
...
@@ -622,6 +643,7 @@ open class NavigationDrawerController: RootController {
rootViewController
.
view
.
alpha
=
0.5
v
.
isShadowPathAutoSizing
=
true
}
layoutSubviews
()
}
}
...
...
@@ -1088,15 +1110,19 @@ extension NavigationDrawerController: UIGestureRecognizerDelegate {
if
!
isRightViewOpened
&&
gestureRecognizer
==
leftPanGesture
&&
(
isLeftViewOpened
||
isPointContainedWithinLeftThreshold
(
point
:
touch
.
location
(
in
:
view
)))
{
return
true
}
if
!
isLeftViewOpened
&&
gestureRecognizer
==
rightPanGesture
&&
(
isRightViewOpened
||
isPointContainedWithinRighThreshold
(
point
:
touch
.
location
(
in
:
view
)))
{
return
true
}
if
isLeftViewOpened
&&
gestureRecognizer
==
leftTapGesture
{
return
true
}
if
isRightViewOpened
&&
gestureRecognizer
==
rightTapGesture
{
return
true
}
return
false
}
...
...
@@ -1108,47 +1134,49 @@ extension NavigationDrawerController: UIGestureRecognizerDelegate {
*/
@objc
fileprivate
func
handleLeftViewPanGesture
(
recognizer
:
UIPanGestureRecognizer
)
{
if
isLeftViewEnabled
&&
(
isLeftViewOpened
||
!
isRightViewOpened
&&
isPointContainedWithinLeftThreshold
(
point
:
recognizer
.
location
(
in
:
view
)))
{
guard
let
v
=
leftView
else
{
return
guard
isLeftViewEnabled
&&
(
isLeftViewOpened
||
!
isRightViewOpened
&&
isPointContainedWithinLeftThreshold
(
point
:
recognizer
.
location
(
in
:
view
)))
else
{
return
}
guard
let
v
=
leftView
else
{
return
}
let
point
=
recognizer
.
location
(
in
:
view
)
// Animate the panel.
switch
recognizer
.
state
{
case
.
began
:
originalX
=
v
.
position
.
x
showView
(
container
:
v
)
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didBeginPanAt
:
point
,
position
:
.
left
)
case
.
changed
:
let
w
=
v
.
width
let
translationX
=
recognizer
.
translation
(
in
:
v
)
.
x
v
.
position
.
x
=
originalX
+
translationX
>
(
w
/
2
)
?
(
w
/
2
)
:
originalX
+
translationX
let
a
=
1
-
v
.
position
.
x
/
v
.
width
rootViewController
.
view
.
alpha
=
0.5
<
a
&&
v
.
position
.
x
<=
v
.
width
/
2
?
a
:
0.5
if
translationX
>=
leftThreshold
{
hideStatusBar
()
}
let
point
=
recognizer
.
location
(
in
:
view
)
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didChangePanAt
:
point
,
position
:
.
left
)
case
.
ended
,
.
cancelled
,
.
failed
:
let
p
=
recognizer
.
velocity
(
in
:
recognizer
.
view
)
let
x
=
p
.
x
>=
1000
||
p
.
x
<=
-
1000
?
p
.
x
:
0
// Animate the panel.
switch
recognizer
.
state
{
case
.
began
:
originalX
=
v
.
position
.
x
showView
(
container
:
v
)
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didBeginPanAt
:
point
,
position
:
.
left
)
case
.
changed
:
let
w
=
v
.
width
let
translationX
=
recognizer
.
translation
(
in
:
v
)
.
x
v
.
position
.
x
=
originalX
+
translationX
>
(
w
/
2
)
?
(
w
/
2
)
:
originalX
+
translationX
let
a
=
1
-
v
.
position
.
x
/
v
.
width
rootViewController
.
view
.
alpha
=
0.5
<
a
&&
v
.
position
.
x
<=
v
.
width
/
2
?
a
:
0.5
if
translationX
>=
leftThreshold
{
hideStatusBar
()
}
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didChangePanAt
:
point
,
position
:
.
left
)
case
.
ended
,
.
cancelled
,
.
failed
:
let
p
=
recognizer
.
velocity
(
in
:
recognizer
.
view
)
let
x
=
p
.
x
>=
1000
||
p
.
x
<=
-
1000
?
p
.
x
:
0
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didEndPanAt
:
point
,
position
:
.
left
)
if
v
.
x
<=
-
leftViewWidth
+
leftViewThreshold
||
x
<
-
1000
{
closeLeftView
(
velocity
:
x
)
}
else
{
openLeftView
(
velocity
:
x
)
}
case
.
possible
:
break
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didEndPanAt
:
point
,
position
:
.
left
)
if
v
.
x
<=
-
leftViewWidth
+
leftViewThreshold
||
x
<
-
1000
{
closeLeftView
(
velocity
:
x
)
}
else
{
openLeftView
(
velocity
:
x
)
}
case
.
possible
:
break
}
}
...
...
@@ -1160,47 +1188,49 @@ extension NavigationDrawerController: UIGestureRecognizerDelegate {
*/
@objc
fileprivate
func
handleRightViewPanGesture
(
recognizer
:
UIPanGestureRecognizer
)
{
if
isRightViewEnabled
&&
(
isRightViewOpened
||
!
isLeftViewOpened
&&
isPointContainedWithinRighThreshold
(
point
:
recognizer
.
location
(
in
:
view
)))
{
guard
let
v
=
rightView
else
{
return
guard
isRightViewEnabled
&&
(
isRightViewOpened
||
!
isLeftViewOpened
&&
isPointContainedWithinRighThreshold
(
point
:
recognizer
.
location
(
in
:
view
)))
else
{
return
}
guard
let
v
=
rightView
else
{
return
}
let
point
=
recognizer
.
location
(
in
:
view
)
// Animate the panel.
switch
recognizer
.
state
{
case
.
began
:
originalX
=
v
.
position
.
x
showView
(
container
:
v
)
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didBeginPanAt
:
point
,
position
:
.
right
)
case
.
changed
:
let
w
=
v
.
width
let
translationX
=
recognizer
.
translation
(
in
:
v
)
.
x
v
.
position
.
x
=
originalX
+
translationX
<
view
.
bounds
.
width
-
(
w
/
2
)
?
view
.
bounds
.
width
-
(
w
/
2
)
:
originalX
+
translationX
let
a
=
1
-
(
view
.
bounds
.
width
-
v
.
position
.
x
)
/
v
.
width
rootViewController
.
view
.
alpha
=
0.5
<
a
&&
v
.
position
.
x
>=
v
.
width
/
2
?
a
:
0.5
if
translationX
<=
-
rightThreshold
{
hideStatusBar
()
}
let
point
=
recognizer
.
location
(
in
:
view
)
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didChangePanAt
:
point
,
position
:
.
right
)
case
.
ended
,
.
cancelled
,
.
failed
:
let
p
=
recognizer
.
velocity
(
in
:
recognizer
.
view
)
let
x
=
p
.
x
>=
1000
||
p
.
x
<=
-
1000
?
p
.
x
:
0
// Animate the panel.
switch
recognizer
.
state
{
case
.
began
:
originalX
=
v
.
position
.
x
showView
(
container
:
v
)
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didBeginPanAt
:
point
,
position
:
.
right
)
case
.
changed
:
let
w
=
v
.
width
let
translationX
=
recognizer
.
translation
(
in
:
v
)
.
x
v
.
position
.
x
=
originalX
+
translationX
<
view
.
bounds
.
width
-
(
w
/
2
)
?
view
.
bounds
.
width
-
(
w
/
2
)
:
originalX
+
translationX
let
a
=
1
-
(
view
.
bounds
.
width
-
v
.
position
.
x
)
/
v
.
width
rootViewController
.
view
.
alpha
=
0.5
<
a
&&
v
.
position
.
x
>=
v
.
width
/
2
?
a
:
0.5
if
translationX
<=
-
rightThreshold
{
hideStatusBar
()
}
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didChangePanAt
:
point
,
position
:
.
right
)
case
.
ended
,
.
cancelled
,
.
failed
:
let
p
=
recognizer
.
velocity
(
in
:
recognizer
.
view
)
let
x
=
p
.
x
>=
1000
||
p
.
x
<=
-
1000
?
p
.
x
:
0
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didEndPanAt
:
point
,
position
:
.
right
)
if
v
.
x
>=
rightViewThreshold
||
x
>
1000
{
closeRightView
(
velocity
:
x
)
}
else
{
openRightView
(
velocity
:
x
)
}
case
.
possible
:
break
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didEndPanAt
:
point
,
position
:
.
right
)
if
v
.
x
>=
rightViewThreshold
||
x
>
1000
{
closeRightView
(
velocity
:
x
)
}
else
{
openRightView
(
velocity
:
x
)
}
case
.
possible
:
break
}
}
...
...
@@ -1222,9 +1252,11 @@ extension NavigationDrawerController: UIGestureRecognizerDelegate {
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didTapAt
:
recognizer
.
location
(
in
:
view
),
position
:
.
left
)
if
isLeftViewEnabled
&&
isLeftViewOpened
&&
!
isPointContainedWithinView
(
container
:
v
,
point
:
recognizer
.
location
(
in
:
v
))
{
closeLeftView
()
guard
isLeftViewEnabled
&&
isLeftViewOpened
&&
!
isPointContainedWithinView
(
container
:
v
,
point
:
recognizer
.
location
(
in
:
v
))
else
{
return
}
closeLeftView
()
}
/**
...
...
@@ -1245,8 +1277,10 @@ extension NavigationDrawerController: UIGestureRecognizerDelegate {
delegate
?
.
navigationDrawerController
?(
navigationDrawerController
:
self
,
didTapAt
:
recognizer
.
location
(
in
:
view
),
position
:
.
right
)
if
isRightViewEnabled
&&
isRightViewOpened
&&
!
isPointContainedWithinView
(
container
:
v
,
point
:
recognizer
.
location
(
in
:
v
))
{
closeRightView
()
guard
isRightViewEnabled
&&
isRightViewOpened
&&
!
isPointContainedWithinView
(
container
:
v
,
point
:
recognizer
.
location
(
in
:
v
))
else
{
return
}
closeRightView
()
}
}
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