Commit b254e22d by Daniel Dahan

updated layout mathematics for TabBarController and ChipBarController

parent 4d61e3f8
......@@ -265,6 +265,7 @@ open class Bar: View {
autoresizingMask = .flexibleWidth
interimSpacePreset = .interimSpace3
contentEdgeInsetsPreset = .square1
prepareContentView()
}
}
......
......@@ -156,10 +156,10 @@ open class ChipBar: Bar {
/// A preset wrapper around chipItems contentEdgeInsets.
open var chipItemsContentEdgeInsetsPreset: EdgeInsetsPreset {
get {
return scrollView.grid.contentEdgeInsetsPreset
return contentView.grid.contentEdgeInsetsPreset
}
set(value) {
scrollView.grid.contentEdgeInsetsPreset = value
contentView.grid.contentEdgeInsetsPreset = value
}
}
......@@ -167,20 +167,20 @@ open class ChipBar: Bar {
@IBInspectable
open var chipItemsContentEdgeInsets: EdgeInsets {
get {
return scrollView.grid.contentEdgeInsets
return contentView.grid.contentEdgeInsets
}
set(value) {
scrollView.grid.contentEdgeInsets = value
contentView.grid.contentEdgeInsets = value
}
}
/// A preset wrapper around chipItems interimSpace.
open var chipItemsInterimSpacePreset: InterimSpacePreset {
get {
return scrollView.grid.interimSpacePreset
return contentView.grid.interimSpacePreset
}
set(value) {
scrollView.grid.interimSpacePreset = value
contentView.grid.interimSpacePreset = value
}
}
......@@ -188,10 +188,10 @@ open class ChipBar: Bar {
@IBInspectable
open var chipItemsInterimSpace: InterimSpace {
get {
return scrollView.grid.interimSpace
return contentView.grid.interimSpace
}
set(value) {
scrollView.grid.interimSpace = value
contentView.grid.interimSpace = value
}
}
......@@ -213,116 +213,17 @@ open class ChipBar: Bar {
return
}
var lc = 0
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()
layoutScrollView()
}
open override func prepare() {
super.prepare()
contentEdgeInsetsPreset = .square2
interimSpacePreset = .interimSpace6
interimSpacePreset = .interimSpace3
contentEdgeInsetsPreset = .square1
chipItemsInterimSpacePreset = .interimSpace4
chipItemsContentEdgeInsetsPreset = .square2
chipItemsContentEdgeInsets.left = 0
chipItemsContentEdgeInsets.right = 0
prepareContentView()
prepareScrollView()
......@@ -363,6 +264,39 @@ 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.
@objc
func handle(chipItem: ChipItem) {
......
......@@ -75,19 +75,9 @@ open class ChipBarController: TransitionController {
open override func layoutSubviews() {
super.layoutSubviews()
chipBar.width = view.width
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
layoutChipBar()
layoutContainer()
layoutRootViewController()
}
open override func prepare() {
......@@ -103,3 +93,54 @@ fileprivate extension ChipBarController {
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 {
/// A preset wrapper around tabItems contentEdgeInsets.
open var tabItemsContentEdgeInsetsPreset: EdgeInsetsPreset {
get {
return scrollView.grid.contentEdgeInsetsPreset
return contentView.grid.contentEdgeInsetsPreset
}
set(value) {
scrollView.grid.contentEdgeInsetsPreset = value
contentView.grid.contentEdgeInsetsPreset = value
}
}
......@@ -126,20 +126,20 @@ open class TabBar: Bar {
@IBInspectable
open var tabItemsContentEdgeInsets: EdgeInsets {
get {
return scrollView.grid.contentEdgeInsets
return contentView.grid.contentEdgeInsets
}
set(value) {
scrollView.grid.contentEdgeInsets = value
contentView.grid.contentEdgeInsets = value
}
}
/// A preset wrapper around tabItems interimSpace.
open var tabItemsInterimSpacePreset: InterimSpacePreset {
get {
return scrollView.grid.interimSpacePreset
return contentView.grid.interimSpacePreset
}
set(value) {
scrollView.grid.interimSpacePreset = value
contentView.grid.interimSpacePreset = value
}
}
......@@ -147,10 +147,10 @@ open class TabBar: Bar {
@IBInspectable
open var tabItemsInterimSpace: InterimSpace {
get {
return scrollView.grid.interimSpace
return contentView.grid.interimSpace
}
set(value) {
scrollView.grid.interimSpace = value
contentView.grid.interimSpace = value
}
}
......@@ -216,109 +216,7 @@ open class TabBar: Bar {
return
}
var lc = 0
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()
layoutScrollView()
layoutLine()
}
......@@ -387,6 +285,37 @@ 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.
func layoutLine() {
guard 0 < tabItems.count else {
......
......@@ -65,6 +65,17 @@ extension 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.
@IBInspectable
open let tabBar = TabBar()
......@@ -150,9 +161,9 @@ open class TabBarController: UIViewController {
open func prepare() {
view.backgroundColor = .white
view.contentScaleFactor = Screen.scale
prepareContainer()
prepareTabBar()
prepareTabBarItems()
prepareContainer()
prepareViewControllers()
}
}
......@@ -219,30 +230,36 @@ fileprivate extension TabBarController {
}
fileprivate extension TabBarController {
/// Layout the container view.
/// Layout the container.
func layoutContainer() {
let p = tabBar.height
let y = view.height - p
tabBar.width = view.width
switch tabBarAlignment {
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
switch displayStyle {
case .partial:
let p = tabBar.height
let y = view.height - p
switch tabBarAlignment {
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
}
container.width = view.width
}
/// Layout the TabBar.
/// Layout the tabBar.
func layoutTabBar() {
let y = view.height - tabBar.height
tabBar.width = view.width
switch tabBarAlignment {
......@@ -251,7 +268,7 @@ fileprivate extension TabBarController {
tabBar.y = 0
case .bottom:
tabBar.isHidden = false
tabBar.y = y
tabBar.y = view.height - tabBar.height
case .hidden:
tabBar.isHidden = true
}
......
......@@ -49,22 +49,9 @@ open class ToolbarController: StatusBarController {
open override func layoutSubviews() {
super.layoutSubviews()
let y = Application.shouldStatusBarBeHidden || statusBar.isHidden ? 0 : statusBar.height
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
layoutToolbar()
layoutContainer()
layoutRootViewController()
}
open override func prepare() {
......@@ -76,15 +63,40 @@ open class ToolbarController: StatusBarController {
}
}
extension ToolbarController {
fileprivate extension ToolbarController {
/// Prepares the statusBar.
fileprivate func prepareStatusBar() {
func prepareStatusBar() {
shouldHideStatusBarOnRotation = false
}
/// Prepares the toolbar.
fileprivate func prepareToolbar() {
func prepareToolbar() {
toolbar.depthPreset = .depth1
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