Commit b254e22d by Daniel Dahan

updated layout mathematics for TabBarController and ChipBarController

parent 4d61e3f8
...@@ -265,6 +265,7 @@ open class Bar: View { ...@@ -265,6 +265,7 @@ open class Bar: View {
autoresizingMask = .flexibleWidth autoresizingMask = .flexibleWidth
interimSpacePreset = .interimSpace3 interimSpacePreset = .interimSpace3
contentEdgeInsetsPreset = .square1 contentEdgeInsetsPreset = .square1
prepareContentView() prepareContentView()
} }
} }
......
...@@ -156,10 +156,10 @@ open class ChipBar: Bar { ...@@ -156,10 +156,10 @@ open class ChipBar: Bar {
/// A preset wrapper around chipItems contentEdgeInsets. /// A preset wrapper around chipItems contentEdgeInsets.
open var chipItemsContentEdgeInsetsPreset: EdgeInsetsPreset { open var chipItemsContentEdgeInsetsPreset: EdgeInsetsPreset {
get { get {
return scrollView.grid.contentEdgeInsetsPreset return contentView.grid.contentEdgeInsetsPreset
} }
set(value) { set(value) {
scrollView.grid.contentEdgeInsetsPreset = value contentView.grid.contentEdgeInsetsPreset = value
} }
} }
...@@ -167,20 +167,20 @@ open class ChipBar: Bar { ...@@ -167,20 +167,20 @@ open class ChipBar: Bar {
@IBInspectable @IBInspectable
open var chipItemsContentEdgeInsets: EdgeInsets { open var chipItemsContentEdgeInsets: EdgeInsets {
get { get {
return scrollView.grid.contentEdgeInsets return contentView.grid.contentEdgeInsets
} }
set(value) { set(value) {
scrollView.grid.contentEdgeInsets = value contentView.grid.contentEdgeInsets = value
} }
} }
/// A preset wrapper around chipItems interimSpace. /// A preset wrapper around chipItems interimSpace.
open var chipItemsInterimSpacePreset: InterimSpacePreset { open var chipItemsInterimSpacePreset: InterimSpacePreset {
get { get {
return scrollView.grid.interimSpacePreset return contentView.grid.interimSpacePreset
} }
set(value) { set(value) {
scrollView.grid.interimSpacePreset = value contentView.grid.interimSpacePreset = value
} }
} }
...@@ -188,10 +188,10 @@ open class ChipBar: Bar { ...@@ -188,10 +188,10 @@ open class ChipBar: Bar {
@IBInspectable @IBInspectable
open var chipItemsInterimSpace: InterimSpace { open var chipItemsInterimSpace: InterimSpace {
get { get {
return scrollView.grid.interimSpace return contentView.grid.interimSpace
} }
set(value) { set(value) {
scrollView.grid.interimSpace = value contentView.grid.interimSpace = value
} }
} }
...@@ -213,116 +213,17 @@ open class ChipBar: Bar { ...@@ -213,116 +213,17 @@ open class ChipBar: Bar {
return return
} }
var lc = 0 layoutScrollView()
var rc = 0
grid.begin()
grid.views.removeAll()
for v in leftViews {
if let b = v as? ChipItem {
b.contentEdgeInsets = .zero
b.titleEdgeInsets = .zero
}
v.width = v.intrinsicContentSize.width
v.sizeToFit()
v.grid.columns = Int(ceil(v.width / gridFactor)) + 2
lc += v.grid.columns
grid.views.append(v)
}
grid.views.append(contentView)
for v in rightViews {
if let b = v as? ChipItem {
b.contentEdgeInsets = .zero
b.titleEdgeInsets = .zero
}
v.width = v.intrinsicContentSize.width
v.sizeToFit()
v.grid.columns = Int(ceil(v.width / gridFactor)) + 2
rc += v.grid.columns
grid.views.append(v)
}
contentView.grid.begin()
contentView.grid.offset.columns = 0
var l: CGFloat = 0
var r: CGFloat = 0
if .center == contentViewAlignment {
if leftViews.count < rightViews.count {
r = CGFloat(rightViews.count) * interimSpace
l = r
} else {
l = CGFloat(leftViews.count) * interimSpace
r = l
}
}
let p = width - l - r - contentEdgeInsets.left - contentEdgeInsets.right
let columns = Int(ceil(p / gridFactor))
if .center == contentViewAlignment {
if lc < rc {
contentView.grid.columns = columns - 2 * rc
contentView.grid.offset.columns = rc - lc
} else {
contentView.grid.columns = columns - 2 * lc
rightViews.first?.grid.offset.columns = lc - rc
}
} else {
contentView.grid.columns = columns - lc - rc
}
grid.axis.columns = columns
if .scrollable == chipBarStyle || (.auto == chipBarStyle && chipItemsTotalWidth > bounds.width) {
var w: CGFloat = chipItemsContentEdgeInsets.left
let q = 2 * chipItemsInterimSpace
let p = q + chipItemsInterimSpace
for v in chipItems {
let x = v.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: scrollView.height)).width
v.height = scrollView.height
v.width = x + q
v.x = w
w += x
w += p
if scrollView != v.superview {
v.removeFromSuperview()
scrollView.addSubview(v)
}
}
w += chipItemsContentEdgeInsets.right - chipItemsInterimSpace
scrollView.contentSize = CGSize(width: w, height: scrollView.height - chipItemsContentEdgeInsets.top - chipItemsContentEdgeInsets.bottom)
} else {
scrollView.grid.views = chipItems
scrollView.grid.axis.columns = chipItems.count
scrollView.contentSize = CGSize(width: scrollView.width, height: scrollView.height - chipItemsContentEdgeInsets.top - chipItemsContentEdgeInsets.bottom)
}
grid.commit()
contentView.grid.commit()
layoutDivider()
} }
open override func prepare() { open override func prepare() {
super.prepare() super.prepare()
contentEdgeInsetsPreset = .square2 interimSpacePreset = .interimSpace3
interimSpacePreset = .interimSpace6 contentEdgeInsetsPreset = .square1
chipItemsInterimSpacePreset = .interimSpace4 chipItemsInterimSpacePreset = .interimSpace4
chipItemsContentEdgeInsetsPreset = .square2
chipItemsContentEdgeInsets.left = 0
chipItemsContentEdgeInsets.right = 0
prepareContentView() prepareContentView()
prepareScrollView() prepareScrollView()
...@@ -363,6 +264,39 @@ fileprivate extension ChipBar { ...@@ -363,6 +264,39 @@ fileprivate extension ChipBar {
} }
fileprivate extension ChipBar { fileprivate extension ChipBar {
/// Layout the scrollView.
func layoutScrollView() {
if .scrollable == chipBarStyle || (.auto == chipBarStyle && chipItemsTotalWidth > bounds.width) {
var w: CGFloat = 0
let q = 2 * chipItemsInterimSpace
let p = q + chipItemsInterimSpace
for v in chipItems {
let x = v.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: scrollView.height)).width
v.height = scrollView.height
v.width = x + q
v.x = w
w += x
w += p
if scrollView != v.superview {
v.removeFromSuperview()
scrollView.addSubview(v)
}
}
w -= chipItemsInterimSpace
scrollView.contentSize = CGSize(width: w, height: scrollView.height)
} else {
scrollView.grid.views = chipItems
scrollView.grid.axis.columns = chipItems.count
scrollView.contentSize = scrollView.bounds.size
}
}
}
fileprivate extension ChipBar {
/// Handles the chipItem touch event. /// Handles the chipItem touch event.
@objc @objc
func handle(chipItem: ChipItem) { func handle(chipItem: ChipItem) {
......
...@@ -75,19 +75,9 @@ open class ChipBarController: TransitionController { ...@@ -75,19 +75,9 @@ open class ChipBarController: TransitionController {
open override func layoutSubviews() { open override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()
layoutChipBar()
chipBar.width = view.width layoutContainer()
layoutRootViewController()
switch displayStyle {
case .partial:
let h = chipBar.height
container.y = h
container.height = view.height - h
case .full:
container.frame = view.bounds
}
rootViewController.view.frame = container.bounds
} }
open override func prepare() { open override func prepare() {
...@@ -103,3 +93,54 @@ fileprivate extension ChipBarController { ...@@ -103,3 +93,54 @@ fileprivate extension ChipBarController {
view.addSubview(chipBar) view.addSubview(chipBar)
} }
} }
fileprivate extension ChipBarController {
/// Layout the container.
func layoutContainer() {
chipBar.width = view.width
switch displayStyle {
case .partial:
let p = chipBar.height
let y = view.height - p
switch chipBarAlignment {
case .top:
container.y = p
container.height = y
case .bottom:
container.y = 0
container.height = y
case .hidden:
container.y = 0
container.height = view.height
}
container.width = view.width
case .full:
container.frame = view.bounds
}
}
/// Layout the chipBar.
func layoutChipBar() {
chipBar.width = view.width
switch chipBarAlignment {
case .top:
chipBar.isHidden = false
chipBar.y = 0
case .bottom:
chipBar.isHidden = false
chipBar.y = view.height - chipBar.height
case .hidden:
chipBar.isHidden = true
}
}
/// Layout the rootViewController.
func layoutRootViewController() {
rootViewController.view.frame = container.bounds
}
}
...@@ -115,10 +115,10 @@ open class TabBar: Bar { ...@@ -115,10 +115,10 @@ open class TabBar: Bar {
/// A preset wrapper around tabItems contentEdgeInsets. /// A preset wrapper around tabItems contentEdgeInsets.
open var tabItemsContentEdgeInsetsPreset: EdgeInsetsPreset { open var tabItemsContentEdgeInsetsPreset: EdgeInsetsPreset {
get { get {
return scrollView.grid.contentEdgeInsetsPreset return contentView.grid.contentEdgeInsetsPreset
} }
set(value) { set(value) {
scrollView.grid.contentEdgeInsetsPreset = value contentView.grid.contentEdgeInsetsPreset = value
} }
} }
...@@ -126,20 +126,20 @@ open class TabBar: Bar { ...@@ -126,20 +126,20 @@ open class TabBar: Bar {
@IBInspectable @IBInspectable
open var tabItemsContentEdgeInsets: EdgeInsets { open var tabItemsContentEdgeInsets: EdgeInsets {
get { get {
return scrollView.grid.contentEdgeInsets return contentView.grid.contentEdgeInsets
} }
set(value) { set(value) {
scrollView.grid.contentEdgeInsets = value contentView.grid.contentEdgeInsets = value
} }
} }
/// A preset wrapper around tabItems interimSpace. /// A preset wrapper around tabItems interimSpace.
open var tabItemsInterimSpacePreset: InterimSpacePreset { open var tabItemsInterimSpacePreset: InterimSpacePreset {
get { get {
return scrollView.grid.interimSpacePreset return contentView.grid.interimSpacePreset
} }
set(value) { set(value) {
scrollView.grid.interimSpacePreset = value contentView.grid.interimSpacePreset = value
} }
} }
...@@ -147,10 +147,10 @@ open class TabBar: Bar { ...@@ -147,10 +147,10 @@ open class TabBar: Bar {
@IBInspectable @IBInspectable
open var tabItemsInterimSpace: InterimSpace { open var tabItemsInterimSpace: InterimSpace {
get { get {
return scrollView.grid.interimSpace return contentView.grid.interimSpace
} }
set(value) { set(value) {
scrollView.grid.interimSpace = value contentView.grid.interimSpace = value
} }
} }
...@@ -216,109 +216,7 @@ open class TabBar: Bar { ...@@ -216,109 +216,7 @@ open class TabBar: Bar {
return return
} }
var lc = 0 layoutScrollView()
var rc = 0
grid.begin()
grid.views.removeAll()
for v in leftViews {
if let b = v as? TabItem {
b.contentEdgeInsets = .zero
b.titleEdgeInsets = .zero
}
v.width = v.intrinsicContentSize.width
v.sizeToFit()
v.grid.columns = Int(ceil(v.width / gridFactor)) + 2
lc += v.grid.columns
grid.views.append(v)
}
grid.views.append(contentView)
for v in rightViews {
if let b = v as? TabItem {
b.contentEdgeInsets = .zero
b.titleEdgeInsets = .zero
}
v.width = v.intrinsicContentSize.width
v.sizeToFit()
v.grid.columns = Int(ceil(v.width / gridFactor)) + 2
rc += v.grid.columns
grid.views.append(v)
}
contentView.grid.begin()
contentView.grid.offset.columns = 0
var l: CGFloat = 0
var r: CGFloat = 0
if .center == contentViewAlignment {
if leftViews.count < rightViews.count {
r = CGFloat(rightViews.count) * interimSpace
l = r
} else {
l = CGFloat(leftViews.count) * interimSpace
r = l
}
}
let p = width - l - r - contentEdgeInsets.left - contentEdgeInsets.right
let columns = Int(ceil(p / gridFactor))
if .center == contentViewAlignment {
if lc < rc {
contentView.grid.columns = columns - 2 * rc
contentView.grid.offset.columns = rc - lc
} else {
contentView.grid.columns = columns - 2 * lc
rightViews.first?.grid.offset.columns = lc - rc
}
} else {
contentView.grid.columns = columns - lc - rc
}
grid.axis.columns = columns
if .scrollable == tabBarStyle || (.auto == tabBarStyle && tabItemsTotalWidth > bounds.width) {
var w: CGFloat = tabItemsContentEdgeInsets.left
let q = scrollView.height / 2
let p = q + tabItemsInterimSpace
for v in tabItems {
let x = v.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: scrollView.height)).width
v.height = scrollView.height
v.width = x + q
v.x = w
w += x
w += p
if scrollView != v.superview {
v.removeFromSuperview()
scrollView.addSubview(v)
}
}
w += tabItemsContentEdgeInsets.right - tabItemsInterimSpace
scrollView.contentSize = CGSize(width: w, height: scrollView.height - tabItemsContentEdgeInsets.top - tabItemsContentEdgeInsets.bottom)
} else {
scrollView.grid.views = tabItems
scrollView.grid.axis.columns = tabItems.count
scrollView.contentSize = CGSize(width: scrollView.width, height: scrollView.height - tabItemsContentEdgeInsets.top - tabItemsContentEdgeInsets.bottom)
}
grid.commit()
contentView.grid.commit()
layoutDivider()
layoutLine() layoutLine()
} }
...@@ -387,6 +285,37 @@ fileprivate extension TabBar { ...@@ -387,6 +285,37 @@ fileprivate extension TabBar {
} }
fileprivate extension TabBar { fileprivate extension TabBar {
/// Layout the scrollView.
func layoutScrollView() {
if .scrollable == tabBarStyle || (.auto == tabBarStyle && tabItemsTotalWidth > bounds.width) {
var w: CGFloat = 0
let q = 2 * tabItemsInterimSpace
let p = q + tabItemsInterimSpace
for v in tabItems {
let x = v.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: scrollView.height)).width
v.height = scrollView.height
v.width = x + q
v.x = w
w += x
w += p
if scrollView != v.superview {
v.removeFromSuperview()
scrollView.addSubview(v)
}
}
w -= tabItemsInterimSpace
scrollView.contentSize = CGSize(width: w, height: scrollView.height)
} else {
scrollView.grid.views = tabItems
scrollView.grid.axis.columns = tabItems.count
scrollView.contentSize = scrollView.bounds.size
}
}
/// Layout the line view. /// Layout the line view.
func layoutLine() { func layoutLine() {
guard 0 < tabItems.count else { guard 0 < tabItems.count else {
......
...@@ -65,6 +65,17 @@ extension UIViewController { ...@@ -65,6 +65,17 @@ extension UIViewController {
} }
open class TabBarController: UIViewController { open class TabBarController: UIViewController {
/**
A Display value to indicate whether or not to
display the rootViewController to the full view
bounds, or up to the toolbar height.
*/
open var displayStyle = DisplayStyle.partial {
didSet {
layoutSubviews()
}
}
/// The TabBar used to switch between view controllers. /// The TabBar used to switch between view controllers.
@IBInspectable @IBInspectable
open let tabBar = TabBar() open let tabBar = TabBar()
...@@ -150,9 +161,9 @@ open class TabBarController: UIViewController { ...@@ -150,9 +161,9 @@ open class TabBarController: UIViewController {
open func prepare() { open func prepare() {
view.backgroundColor = .white view.backgroundColor = .white
view.contentScaleFactor = Screen.scale view.contentScaleFactor = Screen.scale
prepareContainer()
prepareTabBar() prepareTabBar()
prepareTabBarItems() prepareTabBarItems()
prepareContainer()
prepareViewControllers() prepareViewControllers()
} }
} }
...@@ -219,30 +230,36 @@ fileprivate extension TabBarController { ...@@ -219,30 +230,36 @@ fileprivate extension TabBarController {
} }
fileprivate extension TabBarController { fileprivate extension TabBarController {
/// Layout the container view. /// Layout the container.
func layoutContainer() { func layoutContainer() {
let p = tabBar.height tabBar.width = view.width
let y = view.height - p
switch tabBarAlignment { switch displayStyle {
case .top: case .partial:
container.y = p let p = tabBar.height
container.height = y let y = view.height - p
case .bottom:
container.y = 0 switch tabBarAlignment {
container.height = y case .top:
case .hidden: container.y = p
container.y = 0 container.height = y
container.height = view.height case .bottom:
container.y = 0
container.height = y
case .hidden:
container.y = 0
container.height = view.height
}
container.width = view.width
case .full:
container.frame = view.bounds
} }
container.width = view.width
} }
/// Layout the TabBar. /// Layout the tabBar.
func layoutTabBar() { func layoutTabBar() {
let y = view.height - tabBar.height
tabBar.width = view.width tabBar.width = view.width
switch tabBarAlignment { switch tabBarAlignment {
...@@ -251,7 +268,7 @@ fileprivate extension TabBarController { ...@@ -251,7 +268,7 @@ fileprivate extension TabBarController {
tabBar.y = 0 tabBar.y = 0
case .bottom: case .bottom:
tabBar.isHidden = false tabBar.isHidden = false
tabBar.y = y tabBar.y = view.height - tabBar.height
case .hidden: case .hidden:
tabBar.isHidden = true tabBar.isHidden = true
} }
......
...@@ -49,22 +49,9 @@ open class ToolbarController: StatusBarController { ...@@ -49,22 +49,9 @@ open class ToolbarController: StatusBarController {
open override func layoutSubviews() { open override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()
layoutToolbar()
let y = Application.shouldStatusBarBeHidden || statusBar.isHidden ? 0 : statusBar.height layoutContainer()
layoutRootViewController()
toolbar.y = y
toolbar.width = view.width
switch displayStyle {
case .partial:
let h = y + toolbar.height
container.y = h
container.height = view.height - h
case .full:
container.frame = view.bounds
}
rootViewController.view.frame = container.bounds
} }
open override func prepare() { open override func prepare() {
...@@ -76,15 +63,40 @@ open class ToolbarController: StatusBarController { ...@@ -76,15 +63,40 @@ open class ToolbarController: StatusBarController {
} }
} }
extension ToolbarController { fileprivate extension ToolbarController {
/// Prepares the statusBar. /// Prepares the statusBar.
fileprivate func prepareStatusBar() { func prepareStatusBar() {
shouldHideStatusBarOnRotation = false shouldHideStatusBarOnRotation = false
} }
/// Prepares the toolbar. /// Prepares the toolbar.
fileprivate func prepareToolbar() { func prepareToolbar() {
toolbar.depthPreset = .depth1 toolbar.depthPreset = .depth1
view.addSubview(toolbar) view.addSubview(toolbar)
} }
} }
fileprivate extension ToolbarController {
/// Layout the toolbar.
func layoutToolbar() {
toolbar.y = Application.shouldStatusBarBeHidden || statusBar.isHidden ? 0 : statusBar.height
toolbar.width = view.width
}
/// Layout the container.
func layoutContainer() {
switch displayStyle {
case .partial:
let h = toolbar.y + toolbar.height
container.y = h
container.height = view.height - h
case .full:
container.frame = view.bounds
}
}
/// Layout the rootViewController.
func layoutRootViewController() {
rootViewController.view.frame = container.bounds
}
}
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