Commit c3245ef5 by Daniel Dahan Committed by GitHub

Merge pull request #848 from seubseub/master

Add tabs natural slide option
parents 3c78808f 6e8dcb6e
...@@ -90,6 +90,18 @@ open class TabsController: TransitionController { ...@@ -90,6 +90,18 @@ open class TabsController: TransitionController {
} }
} }
fileprivate var _isAllDirectionSlideEnable: Bool = false
/// user can slide views left, right naturally.
open var isAllDirectionSlideEnabled: Bool {
get {
return _isAllDirectionSlideEnable
}
set(newVal) {
_isAllDirectionSlideEnable = newVal
}
}
/// A reference to the currently selected view controller index value. /// A reference to the currently selected view controller index value.
@IBInspectable @IBInspectable
open fileprivate(set) var selectedIndex = 0 open fileprivate(set) var selectedIndex = 0
...@@ -226,7 +238,7 @@ fileprivate extension TabsController { ...@@ -226,7 +238,7 @@ fileprivate extension TabsController {
container.y = 0 container.y = 0
container.height = y container.height = y
} }
container.width = view.width container.width = view.width
case .full: case .full:
...@@ -274,12 +286,22 @@ extension TabsController: TabBarDelegate { ...@@ -274,12 +286,22 @@ extension TabsController: TabBarDelegate {
return return
} }
transition(to: viewControllers[i]) { [weak self] (isFinished) in if(_isAllDirectionSlideEnable) {
guard isFinished else { tabsTransition(tabsController: self, to: viewControllers[i], completion: { [weak self] (isFinished) in
return guard isFinished else {
return
}
self?.selectedIndex = i
})
} else {
transition(to: viewControllers[i]) { [weak self] (isFinished) in
guard isFinished else {
return
}
self?.selectedIndex = i
} }
self?.selectedIndex = i
} }
} }
} }
...@@ -31,72 +31,72 @@ ...@@ -31,72 +31,72 @@
import UIKit import UIKit
open class TransitionController: UIViewController { open class TransitionController: UIViewController {
/** /**
A Boolean property used to enable and disable interactivity A Boolean property used to enable and disable interactivity
with the rootViewController. with the rootViewController.
*/ */
@IBInspectable @IBInspectable
open var isUserInteractionEnabled: Bool { open var isUserInteractionEnabled: Bool {
get { get {
return rootViewController.view.isUserInteractionEnabled return rootViewController.view.isUserInteractionEnabled
} }
set(value) { set(value) {
rootViewController.view.isUserInteractionEnabled = value rootViewController.view.isUserInteractionEnabled = value
} }
} }
/// A reference to the container view. /// A reference to the container view.
@IBInspectable @IBInspectable
open let container = UIView() open let container = UIView()
/** /**
A UIViewController property that references the active A UIViewController property that references the active
main UIViewController. To swap the rootViewController, it main UIViewController. To swap the rootViewController, it
is recommended to use the transitionFromRootViewController is recommended to use the transitionFromRootViewController
helper method. helper method.
*/ */
open internal(set) var rootViewController: UIViewController! open internal(set) var rootViewController: UIViewController!
/// The transition type used during a transition. /// The transition type used during a transition.
open var motionTransitionType = MotionTransitionType.fade open var motionTransitionType = MotionTransitionType.fade
/** /**
An initializer that initializes the object with a NSCoder object. An initializer that initializes the object with a NSCoder object.
- Parameter aDecoder: A NSCoder instance. - Parameter aDecoder: A NSCoder instance.
*/ */
public required init?(coder aDecoder: NSCoder) { public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) super.init(coder: aDecoder)
} }
/** /**
An initializer that initializes the object with an Optional nib and bundle. An initializer that initializes the object with an Optional nib and bundle.
- Parameter nibNameOrNil: An Optional String for the nib. - Parameter nibNameOrNil: An Optional String for the nib.
- Parameter bundle: An Optional NSBundle where the nib is located. - Parameter bundle: An Optional NSBundle where the nib is located.
*/ */
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
} }
/** /**
An initializer for the BarController. An initializer for the BarController.
- Parameter rootViewController: The main UIViewController. - Parameter rootViewController: The main UIViewController.
*/ */
public init(rootViewController: UIViewController) { public init(rootViewController: UIViewController) {
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
self.rootViewController = rootViewController self.rootViewController = rootViewController
} }
open override func viewDidLoad() { open override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
prepare() prepare()
} }
open override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
layoutSubviews()
}
/** open override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
layoutSubviews()
}
/**
A method to swap rootViewController objects. A method to swap rootViewController objects.
- Parameter toViewController: The UIViewController to swap - Parameter toViewController: The UIViewController to swap
with the active rootViewController. with the active rootViewController.
...@@ -104,7 +104,7 @@ open class TransitionController: UIViewController { ...@@ -104,7 +104,7 @@ open class TransitionController: UIViewController {
the transition animation from the active rootViewController the transition animation from the active rootViewController
to the toViewController has completed. to the toViewController has completed.
*/ */
open func transition(to viewController: UIViewController, completion: ((Bool) -> Void)? = nil) { open func transition(to viewController: UIViewController, completion: ((Bool) -> Void)? = nil) {
guard let fvc = rootViewController else { guard let fvc = rootViewController else {
return return
} }
...@@ -125,30 +125,84 @@ open class TransitionController: UIViewController { ...@@ -125,30 +125,84 @@ open class TransitionController: UIViewController {
s.view.isUserInteractionEnabled = true s.view.isUserInteractionEnabled = true
completion?(isFinished) completion?(isFinished)
} }
} }
/** /**
A method to swap rootViewController objects specially in tabsController.
- Parameter tabsController: indicate tabsController. if tabsController nil then default transition method will be executed.
- Parameter toViewController: The UIViewController to swap
with the active rootViewController.
- Parameter completion: A completion block that is execited after
the transition animation from the active rootViewController
to the toViewController has completed.
*/
open func tabsTransition(tabsController: TabsController?, to viewController: UIViewController, completion: ((Bool) -> Void)? = nil) {
guard let fvc = rootViewController else {
return
}
let tvc = viewController
tvc.view.isHidden = false
tvc.view.frame = container.bounds
if(tabsController == nil) {
tvc.motionModalTransitionType = motionTransitionType
view.isUserInteractionEnabled = false
Motion.shared.transition(from: fvc, to: tvc, in: container) { [weak self, tvc = tvc, completion = completion] (isFinished) in
guard let s = self else {
return
}
s.rootViewController = tvc
s.view.isUserInteractionEnabled = true
completion?(isFinished)
}
}
let fvcIndex = tabsController?.viewControllers.index(of: fvc)
let tvcIndex = tabsController?.viewControllers.index(of: viewController)
if(fvcIndex! < tvcIndex!) {
tvc.motionModalTransitionType = .slide(direction: .left)
} else {
tvc.motionModalTransitionType = .slide(direction: .right)
}
view.isUserInteractionEnabled = false
Motion.shared.transition(from: fvc, to: tvc, in: container) { [weak self, tvc = tvc, completion = completion] (isFinished) in
guard let s = self else {
return
}
s.rootViewController = tvc
s.view.isUserInteractionEnabled = true
completion?(isFinished)
}
}
/**
To execute in the order of the layout chain, override this To execute in the order of the layout chain, override this
method. `layoutSubviews` should be called immediately, unless you method. `layoutSubviews` should be called immediately, unless you
have a certain need. have a certain need.
*/ */
open func layoutSubviews() {} open func layoutSubviews() {}
/** /**
Prepares the view instance when intialized. When subclassing, Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepare method it is recommended to override the prepare method
to initialize property values and other setup operations. to initialize property values and other setup operations.
The super.prepare method should always be called immediately The super.prepare method should always be called immediately
when subclassing. when subclassing.
*/ */
open func prepare() { open func prepare() {
view.clipsToBounds = true view.clipsToBounds = true
view.backgroundColor = .white view.backgroundColor = .white
view.contentScaleFactor = Screen.scale view.contentScaleFactor = Screen.scale
prepareContainer() prepareContainer()
prepareRootViewController() prepareRootViewController()
} }
} }
internal extension TransitionController { internal extension TransitionController {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment