Commit d9378151 by Daniel Dahan

TabMenuController now supports swiping with 3 views

parent ce9ea5ec
...@@ -81,17 +81,7 @@ extension UIViewController { ...@@ -81,17 +81,7 @@ extension UIViewController {
open class TabMenuController: UIViewController { open class TabMenuController: UIViewController {
@IBInspectable @IBInspectable
open var selectedIndex: Int { open var selectedIndex = 0
didSet {
scrollView.setContentOffset(CGPoint(x: scrollView.width * CGFloat(selectedIndex), y: 0), animated: true)
guard false == tabBar?.isAnimating else {
return
}
tabBar?.select(at: selectedIndex)
}
}
/// Enables and disables bouncing when swiping. /// Enables and disables bouncing when swiping.
open var isBounceEnabled: Bool { open var isBounceEnabled: Bool {
...@@ -132,13 +122,15 @@ open class TabMenuController: UIViewController { ...@@ -132,13 +122,15 @@ open class TabMenuController: UIViewController {
/// The number of views used in the scrollViewPool. /// The number of views used in the scrollViewPool.
fileprivate let viewPoolCount = 3 fileprivate let viewPoolCount = 3
/// The last scroll view offset position.
fileprivate var scrollViewDirection = 0
/** /**
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) {
viewControllers = [] viewControllers = []
selectedIndex = 0
super.init(coder: aDecoder) super.init(coder: aDecoder)
} }
...@@ -225,12 +217,12 @@ extension TabMenuController { ...@@ -225,12 +217,12 @@ extension TabMenuController {
scrollView.contentSize = CGSize(width: scrollView.width * CGFloat(count), height: scrollView.height) scrollView.contentSize = CGSize(width: scrollView.width * CGFloat(count), height: scrollView.height)
if 0 == selectedIndex { if 0 == selectedIndex {
for i in 0..<count - 1 { for i in 0..<count {
prepareViewController(at: i) prepareViewController(at: i)
} }
} else if viewControllers.count - 1 == selectedIndex { } else if viewControllers.count - 1 == selectedIndex {
for i in 0..<count - 1 { for i in 0..<count {
prepareViewController(at: count - i - 1) prepareViewController(at: selectedIndex - i)
} }
} else { } else {
prepareViewController(at: selectedIndex) prepareViewController(at: selectedIndex)
...@@ -257,12 +249,11 @@ extension TabMenuController { ...@@ -257,12 +249,11 @@ extension TabMenuController {
v.removeTarget(self, action: #selector(handleTabBarButton(button:)), for: .touchUpInside) v.removeTarget(self, action: #selector(handleTabBarButton(button:)), for: .touchUpInside)
v.addTarget(self, action: #selector(handleTabBarButton(button:)), for: .touchUpInside) v.addTarget(self, action: #selector(handleTabBarButton(button:)), for: .touchUpInside)
} }
tb.select(at: selectedIndex)
} }
fileprivate func prepareTabBar() { fileprivate func prepareTabBar() {
guard 0 < viewControllers.count else { guard 0 < viewControllers.count else {
tabBar = nil
return return
} }
...@@ -327,13 +318,13 @@ extension TabMenuController { ...@@ -327,13 +318,13 @@ extension TabMenuController {
} }
} else if viewControllers.count - 1 == selectedIndex { } else if viewControllers.count - 1 == selectedIndex {
for i in 0..<count { for i in 0..<count {
let j = count - i - 1 layoutViewController(at: selectedIndex - i, position: count - i - 1)
layoutViewController(at: j, position: j)
} }
} else { } else {
layoutViewController(at: selectedIndex, position: 1) layoutViewController(at: selectedIndex, position: 1)
layoutViewController(at: selectedIndex - 1, position: 0) layoutViewController(at: selectedIndex - 1, position: 0)
layoutViewController(at: selectedIndex + 1, position: 2) layoutViewController(at: selectedIndex + 1, position: 2)
scrollView.setContentOffset(CGPoint(x: scrollView.width, y: 0), animated: false)
} }
} }
...@@ -342,19 +333,56 @@ extension TabMenuController { ...@@ -342,19 +333,56 @@ extension TabMenuController {
- Parameter position: An Int for the position of the view controller. - Parameter position: An Int for the position of the view controller.
*/ */
fileprivate func layoutViewController(at index: Int, position: Int) { fileprivate func layoutViewController(at index: Int, position: Int) {
let vc = viewControllers[index] guard 0 <= index && index < viewControllers.count else {
vc.view.frame = CGRect(x: CGFloat(position) * scrollView.width, y: 0, width: scrollView.width, height: scrollView.height) return
}
viewControllers[index].view.frame = CGRect(x: CGFloat(position) * scrollView.width, y: 0, width: scrollView.width, height: scrollView.height)
} }
} }
extension TabMenuController { extension TabMenuController {
/// Removes the view controllers not within the scrollView.
fileprivate func removeViewControllers() {
let count = viewPoolCount < viewControllers.count ? viewPoolCount : viewControllers.count
scrollView.contentSize = CGSize(width: scrollView.width * CGFloat(count), height: scrollView.height)
if 0 == selectedIndex {
for i in count..<viewControllers.count {
removeViewController(at: i)
}
} else if viewControllers.count - 1 == selectedIndex {
for i in 0..<viewControllers.count - 2 {
removeViewController(at: i)
}
} else {
for i in 0..<selectedIndex {
removeViewController(at: i)
}
let x = selectedIndex + 1
if x < viewControllers.count {
for i in x..<viewControllers.count {
removeViewController(at: i)
}
}
}
}
/** /**
Removes the view controller as a child view controller with Removes the view controller as a child view controller with
the given index. the given index.
- Parameter at index: An Int for the view controller position. - Parameter at index: An Int for the view controller position.
*/ */
fileprivate func removeViewController(at index: Int) { fileprivate func removeViewController(at index: Int) {
removeViewController(viewController: viewControllers[index]) let vc = viewControllers[index]
guard childViewControllers.contains(vc) else {
return
}
removeViewController(viewController: vc)
} }
/** /**
...@@ -387,22 +415,9 @@ extension TabMenuController { ...@@ -387,22 +415,9 @@ extension TabMenuController {
return return
} }
if 1 < abs(index - selectedIndex) {
let last = viewControllers.count - 1
var pos = 0
if last == selectedIndex {
pos = last - 1
} else if 0 == selectedIndex {
pos = 1
} else {
pos = selectedIndex + (index > selectedIndex ? 1 : -1)
}
scrollView.setContentOffset(CGPoint(x: scrollView.width * CGFloat(pos), y: 0), animated: false)
}
selectedIndex = index selectedIndex = index
removeViewControllers()
prepareViewControllers() prepareViewControllers()
layoutViewControllers() layoutViewControllers()
} }
...@@ -423,13 +438,28 @@ extension TabMenuController: UIScrollViewDelegate { ...@@ -423,13 +438,28 @@ extension TabMenuController: UIScrollViewDelegate {
return return
} }
let x = (scrollView.contentOffset.x - scrollView.width) / scrollView.contentSize.width * scrollView.width // let x = (scrollView.contentOffset.x - scrollView.width) / scrollView.contentSize.width * scrollView.width
tb.line.center.x = selected.center.x + x // tb.line.center.x = selected.center.x + x
}
@objc
open func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
let translation = scrollView.panGestureRecognizer.translation(in: scrollView.superview)
print(translation.x)
scrollViewDirection = 0 > translation.x ? 1 : -1
} }
@objc @objc
open func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { open func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
selectedIndex = lround(Double(scrollView.contentOffset.x / scrollView.width)) let index = selectedIndex + scrollViewDirection
guard 0 <= index && index < viewControllers.count else {
return
}
selectedIndex = index
removeViewControllers()
prepareViewControllers() prepareViewControllers()
layoutViewControllers() layoutViewControllers()
} }
......
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