Commit 92f6000c by Daniel Dahan

added MaterialDevice model detection and updated NavigationBar example project

parent 96148cc4
...@@ -57,6 +57,11 @@ class ViewController: UIViewController { ...@@ -57,6 +57,11 @@ class ViewController: UIViewController {
prepareNavigationBar() prepareNavigationBar()
} }
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
navigationBar.frame = CGRectMake(0, 0, view.bounds.width, MaterialDevice.landscape ? .iPad == MaterialDevice.type ? 64 : navigationBar.intrinsicContentSize().height : 64)
}
/// General preparation statements. /// General preparation statements.
private func prepareView() { private func prepareView() {
view.backgroundColor = MaterialColor.white view.backgroundColor = MaterialColor.white
...@@ -100,17 +105,12 @@ class ViewController: UIViewController { ...@@ -100,17 +105,12 @@ class ViewController: UIViewController {
navigationBar = NavigationBar() navigationBar = NavigationBar()
navigationBar.backgroundColor = MaterialColor.blue.base navigationBar.backgroundColor = MaterialColor.blue.base
navigationBar.tintColor = MaterialColor.white navigationBar.tintColor = MaterialColor.white
view.addSubview(navigationBar)
let item: UINavigationItem = UINavigationItem() let item: UINavigationItem = UINavigationItem()
item.titleLabel = titleLabel item.titleLabel = titleLabel
item.leftControls = [menuButton] item.leftControls = [menuButton]
item.rightControls = [switchControl, searchButton] item.rightControls = [switchControl, searchButton]
navigationBar.pushNavigationItem(item, animated: true) navigationBar.pushNavigationItem(item, animated: true)
view.addSubview(navigationBar)
navigationBar.translatesAutoresizingMaskIntoConstraints = false
MaterialLayout.alignFromTop(view, child: navigationBar)
MaterialLayout.alignToParentHorizontally(view, child: navigationBar)
} }
} }
...@@ -38,6 +38,45 @@ public enum MaterialDeviceType { ...@@ -38,6 +38,45 @@ public enum MaterialDeviceType {
} }
public struct MaterialDevice { public struct MaterialDevice {
/// Gets the model name for the device.
public static var model: String {
var systemInfo: utsname = utsname()
uname(&systemInfo)
let machineMirror: Mirror = Mirror(reflecting: systemInfo.machine)
let identifier: String = machineMirror.children.reduce("") { (identifier, element) in
guard let value = element.value as? Int8 where value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
switch identifier {
case "iPod5,1": return "iPod Touch 5"
case "iPod7,1": return "iPod Touch 6"
case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4"
case "iPhone4,1": return "iPhone 4s"
case "iPhone5,1", "iPhone5,2": return "iPhone 5"
case "iPhone5,3", "iPhone5,4": return "iPhone 5c"
case "iPhone6,1", "iPhone6,2": return "iPhone 5s"
case "iPhone7,2": return "iPhone 6"
case "iPhone7,1": return "iPhone 6 Plus"
case "iPhone8,1": return "iPhone 6s"
case "iPhone8,2": return "iPhone 6s Plus"
case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4": return "iPad 2"
case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad 3"
case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad 4"
case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air"
case "iPad5,3", "iPad5,4": return "iPad Air 2"
case "iPad2,5", "iPad2,6", "iPad2,7": return "iPad Mini"
case "iPad4,4", "iPad4,5", "iPad4,6": return "iPad Mini 2"
case "iPad4,7", "iPad4,8", "iPad4,9": return "iPad Mini 3"
case "iPad5,1", "iPad5,2": return "iPad Mini 4"
case "iPad6,7", "iPad6,8": return "iPad Pro"
case "AppleTV5,3": return "Apple TV"
case "i386", "x86_64": return "Simulator"
default: return identifier
}
}
/// Retrieves the current device type. /// Retrieves the current device type.
public static var type: MaterialDeviceType { public static var type: MaterialDeviceType {
switch UIDevice.currentDevice().userInterfaceIdiom { switch UIDevice.currentDevice().userInterfaceIdiom {
......
...@@ -58,6 +58,20 @@ public class NavigationBar : UINavigationBar { ...@@ -58,6 +58,20 @@ public class NavigationBar : UINavigationBar {
} }
} }
/// A preset for contentInset.
public var contentInsetPreset: MaterialEdgeInset = .None {
didSet {
contentInset = MaterialEdgeInsetToValue(contentInsetPreset)
}
}
/// A UIEdgeInsets value for insetting the content.
public var contentInset: UIEdgeInsets = MaterialEdgeInsetToValue(.None) {
didSet {
layoutSubviews()
}
}
/** /**
This property is the same as clipsToBounds. It crops any of the view's This property is the same as clipsToBounds. It crops any of the view's
contents from bleeding past the view's frame. If an image is set using contents from bleeding past the view's frame. If an image is set using
...@@ -237,129 +251,102 @@ public class NavigationBar : UINavigationBar { ...@@ -237,129 +251,102 @@ public class NavigationBar : UINavigationBar {
super.layoutSubviews() super.layoutSubviews()
if let item: UINavigationItem = topItem { if let item: UINavigationItem = topItem {
layoutNavigationItem(item) layoutNavigationItem(item)
sizeNavigationItem(item)
} }
} }
public override func pushNavigationItem(item: UINavigationItem, animated: Bool) {
super.pushNavigationItem(item, animated: animated)
layoutNavigationItem(item)
}
/** /**
Lays out the UINavigationItem. Lays out the UINavigationItem.
- Parameter item: A UINavigationItem to layout. - Parameter item: A UINavigationItem to layout.
*/ */
internal func layoutNavigationItem(item: UINavigationItem) { public func layoutNavigationItem(item: UINavigationItem) {
prepareItem(item) prepareItem(item)
// We only want to work with the intrinsic height. let h: CGFloat = intrinsicContentSize().height
let inset: CGFloat = MaterialDevice.landscape ? item.landscapeInset : item.portraitInset let inset: CGFloat = MaterialDevice.landscape ? item.landscapeInset : item.portraitInset
// leftControls // leftControls
if let v: Array<UIControl> = item.leftControls { if let v: Array<UIControl> = item.leftControls {
var n: Array<UIBarButtonItem> = Array<UIBarButtonItem>() var n: Array<UIBarButtonItem> = Array<UIBarButtonItem>()
for c in v { for c in v {
n.append(UIBarButtonItem(customView: c)) if let b: UIButton = c as? UIButton {
} b.contentEdgeInsets.top = 0
b.contentEdgeInsets.bottom = 0
// The spacer moves the UIBarButtonItems to the edge of the UINavigationBar.
let spacer: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .FixedSpace, target: nil, action: nil)
spacer.width = inset
n.append(spacer)
item.leftBarButtonItems = n.reverse()
}
let titleView: UIView = UIView()
titleView.grid.views = []
titleView.backgroundColor = nil
titleView.grid.axis.direction = .Vertical
// TitleView alignment.
if let t: UILabel = item.titleLabel {
t.backgroundColor = MaterialColor.red.accent1
titleView.addSubview(t)
titleView.grid.views?.append(t)
if let d: UILabel = item.detailLabel {
d.backgroundColor = MaterialColor.red.accent3
titleView.addSubview(d)
titleView.grid.views?.append(d)
}
} else if let d: UIView = item.detailView {
titleView.addSubview(d)
titleView.grid.views?.append(d)
} }
c.bounds.size = c is MaterialSwitch ? CGSizeMake(backButton.intrinsicContentSize().width, h - contentInset.top - contentInset.bottom) : CGSizeMake(c.intrinsicContentSize().width, h - contentInset.top - contentInset.bottom)
// rightControls
if let v: Array<UIControl> = item.rightControls {
var n: Array<UIBarButtonItem> = Array<UIBarButtonItem>()
for c in v {
n.append(UIBarButtonItem(customView: c)) n.append(UIBarButtonItem(customView: c))
} }
// The spacer moves the UIBarButtonItems to the edge of the UINavigationBar. // The spacer moves the UIBarButtonItems to the edge of the UINavigationBar.
let spacer: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .FixedSpace, target: nil, action: nil) let spacer: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .FixedSpace, target: nil, action: nil)
spacer.width = inset spacer.width = inset + contentInset.left
n.append(spacer) n.append(spacer)
item.rightBarButtonItems = n.reverse() item.leftBarButtonItems = n.reverse()
}
item.titleView = titleView
} }
/** if nil == item.titleView {
Sizes out the UINavigationItem. item.titleView = UIView(frame: CGRectMake(0, contentInset.top, MaterialDevice.width < MaterialDevice.height ? MaterialDevice.height : MaterialDevice.width, h - contentInset.top - contentInset.bottom))
- Parameter item: A UINavigationItem to layout. item.titleView!.backgroundColor = nil
*/ item.titleView!.grid.axis.direction = .Vertical
internal func sizeNavigationItem(item: UINavigationItem) {
let h: CGFloat = height
// leftControls
if let v: Array<UIControl> = item.leftControls {
for c in v {
if let b: UIButton = c as? UIButton {
b.contentEdgeInsets.top = 0
b.contentEdgeInsets.bottom = 0
}
c.bounds.size = c is MaterialSwitch ? CGSizeMake(backButton.bounds.width, h - 4) : CGSizeMake(c.intrinsicContentSize().width, h - 4)
} }
}
if let titleView: UIView = item.titleView {
titleView.frame.size.height = h - 4 item.titleView!.grid.views = []
// TitleView alignment. // TitleView alignment.
if let t: UILabel = item.titleLabel { if let t: UILabel = item.titleLabel {
t.grid.rows = 1 t.grid.rows = 1
if 32 >= h || nil == item.detailLabel {
item.titleView!.addSubview(t)
item.titleView!.grid.views?.append(t)
if 32 >= height || nil == item.detailLabel {
t.font = t.font?.fontWithSize(20) t.font = t.font?.fontWithSize(20)
titleView.grid.axis.rows = 1
item.detailLabel?.hidden = true item.titleView!.grid.axis.rows = 1
} else if let d: UILabel = item.detailLabel { } else if let d: UILabel = item.detailLabel {
t.font = t.font.fontWithSize(17)
d.font = d.font.fontWithSize(12)
d.grid.rows = 1 d.grid.rows = 1
d.hidden = false d.font = d.font.fontWithSize(12)
titleView.grid.axis.rows = 2
t.font = t.font.fontWithSize(17)
item.titleView!.addSubview(d)
item.titleView!.grid.axis.rows = 2
item.titleView!.grid.views?.append(d)
} }
} else if let d: UIView = item.detailView { } else if let d: UIView = item.detailView {
d.grid.rows = 1 d.grid.rows = 1
titleView.grid.axis.rows = 1
}
titleView.grid.reloadLayout() item.titleView!.addSubview(d)
item.titleView!.grid.axis.rows = 1
item.titleView!.grid.views?.append(d)
} }
// rightControls // rightControls
if let v: Array<UIControl> = item.rightControls { if let v: Array<UIControl> = item.rightControls {
var n: Array<UIBarButtonItem> = Array<UIBarButtonItem>()
for c in v { for c in v {
if let b: UIButton = c as? UIButton { if let b: UIButton = c as? UIButton {
b.contentEdgeInsets.top = 0 b.contentEdgeInsets.top = 0
b.contentEdgeInsets.bottom = 0 b.contentEdgeInsets.bottom = 0
} }
print(c.intrinsicContentSize()) c.bounds.size = c is MaterialSwitch ? CGSizeMake(backButton.intrinsicContentSize().width, h - contentInset.top - contentInset.bottom) : CGSizeMake(c.intrinsicContentSize().width, h - contentInset.top - contentInset.bottom)
c.bounds.size = c is MaterialSwitch ? CGSizeMake(backButton.intrinsicContentSize().width, h - 4) : CGSizeMake(c.intrinsicContentSize().width, h - 4) n.append(UIBarButtonItem(customView: c))
} }
// The spacer moves the UIBarButtonItems to the edge of the UINavigationBar.
let spacer: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .FixedSpace, target: nil, action: nil)
spacer.width = inset + contentInset.left
n.append(spacer)
item.rightBarButtonItems = n.reverse()
} }
item.titleView!.grid.reloadLayout()
} }
/** /**
...@@ -398,10 +385,9 @@ public class NavigationBar : UINavigationBar { ...@@ -398,10 +385,9 @@ public class NavigationBar : UINavigationBar {
private var NavigationItemKey: UInt8 = 0 private var NavigationItemKey: UInt8 = 0
public class NavigationItem { public class NavigationItem {
/// Portrait Inset. /// Inset.
public var portraitInset: CGFloat = -16 public var portraitInset: CGFloat = .iPad == MaterialDevice.type || "iPhone 6s Plus" == MaterialDevice.model || "iPhone 6 Plus" == MaterialDevice.model ? -20 : -16
/// Landscape Inset.
public var landscapeInset: CGFloat = -20 public var landscapeInset: CGFloat = -20
/// Detail View. /// Detail View.
...@@ -433,7 +419,7 @@ public extension UINavigationItem { ...@@ -433,7 +419,7 @@ public extension UINavigationItem {
} }
} }
/// Portrait Inset. /// Portrait inset.
public var portraitInset: CGFloat { public var portraitInset: CGFloat {
get { get {
return item.portraitInset return item.portraitInset
...@@ -443,7 +429,7 @@ public extension UINavigationItem { ...@@ -443,7 +429,7 @@ public extension UINavigationItem {
} }
} }
/// Landscape Inset. /// Landscape inset.
public var landscapeInset: CGFloat { public var landscapeInset: CGFloat {
get { get {
return item.landscapeInset return item.landscapeInset
......
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