Commit 6554f20e by Daniel Dahan

development: fixed grid issue, where views were causing an out of bounds index error

parent 8363fcbd
......@@ -91,29 +91,15 @@ open class ControlView: View {
open private(set) var contentView: View!
/// Left side UIControls.
open var leftControls: [UIView] {
open var leftControls = [UIView]() {
didSet {
for v in oldValue {
v.removeFromSuperview()
}
for v in leftControls {
addSubview(v)
}
layoutSubviews()
layoutSubviews()
}
}
/// Right side UIControls.
open var rightControls: [UIView] {
open var rightControls = [UIView]() {
didSet {
for v in oldValue {
v.removeFromSuperview()
}
for v in rightControls {
addSubview(v)
}
layoutSubviews()
}
}
......@@ -123,8 +109,6 @@ open class ControlView: View {
- Parameter aDecoder: A NSCoder instance.
*/
public required init?(coder aDecoder: NSCoder) {
leftControls = []
rightControls = []
super.init(coder: aDecoder)
}
......@@ -135,15 +119,11 @@ open class ControlView: View {
- Parameter frame: A CGRect instance.
*/
public override init(frame: CGRect) {
leftControls = []
rightControls = []
super.init(frame: frame)
super.init(frame: frame)
}
/// Basic initializer.
public init() {
leftControls = []
rightControls = []
super.init(frame: .zero)
frame.size = intrinsicContentSize
}
......
......@@ -173,7 +173,7 @@ public class Grid {
}
/// An Array of UIButtons.
public var views: [UIView] {
public var views = [UIView]() {
didSet {
reload()
}
......@@ -190,7 +190,6 @@ public class Grid {
self.rows = rows
self.columns = columns
self.interimSpace = interimSpace
views = [UIView]()
offset = GridOffset(grid: self)
axis = GridAxis(grid: self)
}
......@@ -198,57 +197,60 @@ public class Grid {
/// Reload the button layout.
public func reload() {
var n: Int = 0
var i: Int = 0
for i in 0..<views.count {
let child = views[i]
for child in views {
guard let parent = context else {
return
}
if parent != child.superview {
child.removeFromSuperview()
parent.addSubview(child)
}
if let parent = context {
if parent != child.superview {
child.removeFromSuperview()
parent.addSubview(child)
}
parent.layoutIfNeeded()
switch axis.direction {
case .horizontal:
let c = child.grid.columns
let co = child.grid.offset.columns
let w = (parent.bounds.width - contentEdgeInsets.left - contentEdgeInsets.right - layoutEdgeInsets.left - layoutEdgeInsets.right + interimSpace) / CGFloat(axis.columns)
child.x = CGFloat(i + n + co) * w + contentEdgeInsets.left + layoutEdgeInsets.left
child.y = contentEdgeInsets.top + layoutEdgeInsets.top
child.width = w * CGFloat(c) - interimSpace
child.height = parent.bounds.height - contentEdgeInsets.top - contentEdgeInsets.bottom - layoutEdgeInsets.top - layoutEdgeInsets.bottom
parent.layoutIfNeeded()
n += c + co - 1
switch axis.direction {
case .horizontal:
let c = child.grid.columns
let co = child.grid.offset.columns
let w = (parent.bounds.width - contentEdgeInsets.left - contentEdgeInsets.right - layoutEdgeInsets.left - layoutEdgeInsets.right + interimSpace) / CGFloat(axis.columns)
child.x = CGFloat(i + n + co) * w + contentEdgeInsets.left + layoutEdgeInsets.left
child.y = contentEdgeInsets.top + layoutEdgeInsets.top
child.width = w * CGFloat(c) - interimSpace
child.height = parent.bounds.height - contentEdgeInsets.top - contentEdgeInsets.bottom - layoutEdgeInsets.top - layoutEdgeInsets.bottom
n += c + co - 1
case .vertical:
let r = child.grid.rows
let ro = child.grid.offset.rows
let h = (parent.bounds.height - contentEdgeInsets.top - contentEdgeInsets.bottom - layoutEdgeInsets.top - layoutEdgeInsets.bottom + interimSpace) / CGFloat(axis.rows)
child.x = contentEdgeInsets.left + layoutEdgeInsets.left
child.y = CGFloat(i + n + ro) * h + contentEdgeInsets.top + layoutEdgeInsets.top
child.width = parent.bounds.width - contentEdgeInsets.left - contentEdgeInsets.right - layoutEdgeInsets.left - layoutEdgeInsets.right
child.height = h * CGFloat(r) - interimSpace
n += r + ro - 1
case .vertical:
let r = child.grid.rows
let ro = child.grid.offset.rows
let h = (parent.bounds.height - contentEdgeInsets.top - contentEdgeInsets.bottom - layoutEdgeInsets.top - layoutEdgeInsets.bottom + interimSpace) / CGFloat(axis.rows)
case .any:
let r = child.grid.rows
let ro = child.grid.offset.rows
let c = child.grid.columns
let co = child.grid.offset.columns
let w = (parent.bounds.width - contentEdgeInsets.left - contentEdgeInsets.right - layoutEdgeInsets.left - layoutEdgeInsets.right + interimSpace) / CGFloat(axis.columns)
let h = (parent.bounds.height - contentEdgeInsets.top - contentEdgeInsets.bottom - layoutEdgeInsets.top - layoutEdgeInsets.bottom + interimSpace) / CGFloat(axis.rows)
child.x = CGFloat(co) * w + contentEdgeInsets.left + layoutEdgeInsets.left
child.y = CGFloat(ro) * h + contentEdgeInsets.top + layoutEdgeInsets.top
child.width = w * CGFloat(c) - interimSpace
child.height = h * CGFloat(r) - interimSpace
}
child.x = contentEdgeInsets.left + layoutEdgeInsets.left
child.y = CGFloat(i + n + ro) * h + contentEdgeInsets.top + layoutEdgeInsets.top
child.width = parent.bounds.width - contentEdgeInsets.left - contentEdgeInsets.right - layoutEdgeInsets.left - layoutEdgeInsets.right
child.height = h * CGFloat(r) - interimSpace
n += r + ro - 1
case .any:
let r = child.grid.rows
let ro = child.grid.offset.rows
let c = child.grid.columns
let co = child.grid.offset.columns
let w = (parent.bounds.width - contentEdgeInsets.left - contentEdgeInsets.right - layoutEdgeInsets.left - layoutEdgeInsets.right + interimSpace) / CGFloat(axis.columns)
let h = (parent.bounds.height - contentEdgeInsets.top - contentEdgeInsets.bottom - layoutEdgeInsets.top - layoutEdgeInsets.bottom + interimSpace) / CGFloat(axis.rows)
child.x = CGFloat(co) * w + contentEdgeInsets.left + layoutEdgeInsets.left
child.y = CGFloat(ro) * h + contentEdgeInsets.top + layoutEdgeInsets.top
child.width = w * CGFloat(c) - interimSpace
child.height = h * CGFloat(r) - interimSpace
}
i += 1
}
}
}
......
......@@ -55,6 +55,9 @@ public protocol PageControllerDelegate {
@objc(PageController)
open class PageController: RootController {
/// A boolean that indicates when a button animation is active.
internal var animating = false
/// The currently selected UIViewController.
open internal(set) var selectedIndex: Int = 0
......@@ -137,6 +140,12 @@ open class PageController: RootController {
v.delegate = self
v.dataSource = self
v.isDoubleSided = false
for view in v.view.subviews {
if view.isKind(of: UIScrollView.self) {
(view as? UIScrollView)?.delegate = self
}
}
}
/// Prepares the tabBar.
......@@ -145,6 +154,7 @@ open class PageController: RootController {
tabBar = TabBar()
tabBar.zPosition = 1000
view.addSubview(tabBar)
tabBar.select(at: selectedIndex)
}
}
}
......@@ -157,7 +167,25 @@ extension PageController {
}
extension PageController: UIPageViewControllerDelegate {
public func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
guard let vc = previousViewControllers.first else {
return
}
guard let index = viewControllers.index(of: vc) else {
return
}
guard completed else {
tabBar.select(at: index) { [weak self] _ in
guard let s = self else {
return
}
s.animating = false
}
return
}
}
}
extension PageController: UIPageViewControllerDataSource {
......@@ -190,3 +218,28 @@ extension PageController: UIPageViewControllerDataSource {
return viewControllers[next]
}
}
extension PageController: UIScrollViewDelegate {
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard !animating else {
return
}
let x = scrollView.contentOffset.x / scrollView.contentSize.width * scrollView.width
guard 0 < x else {
return
}
tabBar.line.x = x
print("scrolling", x)
}
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
// animating = true
}
public func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
animating = true
}
}
......@@ -185,7 +185,28 @@ open class TabBar: View {
/// Handles the button touch event.
@objc
internal func handleButton(button: UIButton) {
delegate?.tabBarWillSelectButton?(tabBar: self, button: button)
animate(to: button)
}
/**
Selects a given index from the buttons array.
- Parameter at index: An Int.
- Paramater completion: An optional completion block.
*/
open func select(at index: Int, completion: (@escaping (UIButton) -> Void)? = nil) {
guard -1 < index, index < buttons.count else {
return
}
animate(to: buttons[index], completion: completion)
}
/**
Animates to a given button.
- Parameter to button: A UIButton.
- Paramater completion: An optional completion block.
*/
internal func animate(to button: UIButton, completion: (@escaping (UIButton) -> Void)? = nil) {
delegate?.tabBarWillSelectButton?(tabBar: self, button: button)
selected = button
UIView.animate(withDuration: 0.25, animations: { [weak self, button = button] in
......@@ -194,14 +215,15 @@ open class TabBar: View {
}
s.line.x = button.x
s.line.width = button.width
}) { [weak self, button = button] _ in
}) { [weak self, button = button, completion = completion] _ in
guard let s = self else {
return
}
s.delegate?.tabBarDidSelectButton?(tabBar: s, button: button)
completion?(button)
}
}
}
/**
Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepareView method
......
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