Commit 92f6000c by Daniel Dahan

added MaterialDevice model detection and updated NavigationBar example project

parent 96148cc4
......@@ -57,6 +57,11 @@ class ViewController: UIViewController {
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.
private func prepareView() {
view.backgroundColor = MaterialColor.white
......@@ -100,17 +105,12 @@ class ViewController: UIViewController {
navigationBar = NavigationBar()
navigationBar.backgroundColor = MaterialColor.blue.base
navigationBar.tintColor = MaterialColor.white
view.addSubview(navigationBar)
let item: UINavigationItem = UINavigationItem()
item.titleLabel = titleLabel
item.leftControls = [menuButton]
item.rightControls = [switchControl, searchButton]
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 {
}
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.
public static var type: MaterialDeviceType {
switch UIDevice.currentDevice().userInterfaceIdiom {
......
......@@ -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
contents from bleeding past the view's frame. If an image is set using
......@@ -237,129 +251,102 @@ public class NavigationBar : UINavigationBar {
super.layoutSubviews()
if let item: UINavigationItem = topItem {
layoutNavigationItem(item)
sizeNavigationItem(item)
}
}
public override func pushNavigationItem(item: UINavigationItem, animated: Bool) {
super.pushNavigationItem(item, animated: animated)
layoutNavigationItem(item)
}
/**
Lays out the UINavigationItem.
- Parameter item: A UINavigationItem to layout.
*/
internal func layoutNavigationItem(item: UINavigationItem) {
public func layoutNavigationItem(item: UINavigationItem) {
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
// leftControls
if let v: Array<UIControl> = item.leftControls {
var n: Array<UIBarButtonItem> = Array<UIBarButtonItem>()
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.intrinsicContentSize().width, h - contentInset.top - contentInset.bottom) : CGSizeMake(c.intrinsicContentSize().width, h - contentInset.top - contentInset.bottom)
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
spacer.width = inset + contentInset.left
n.append(spacer)
item.leftBarButtonItems = n.reverse()
}
let titleView: UIView = UIView()
titleView.grid.views = []
titleView.backgroundColor = nil
titleView.grid.axis.direction = .Vertical
if nil == item.titleView {
item.titleView = UIView(frame: CGRectMake(0, contentInset.top, MaterialDevice.width < MaterialDevice.height ? MaterialDevice.height : MaterialDevice.width, h - contentInset.top - contentInset.bottom))
item.titleView!.backgroundColor = nil
item.titleView!.grid.axis.direction = .Vertical
}
item.titleView!.grid.views = []
// TitleView alignment.
if let t: UILabel = item.titleLabel {
t.backgroundColor = MaterialColor.red.accent1
titleView.addSubview(t)
titleView.grid.views?.append(t)
t.grid.rows = 1
item.titleView!.addSubview(t)
item.titleView!.grid.views?.append(t)
if let d: UILabel = item.detailLabel {
d.backgroundColor = MaterialColor.red.accent3
titleView.addSubview(d)
titleView.grid.views?.append(d)
if 32 >= height || nil == item.detailLabel {
t.font = t.font?.fontWithSize(20)
item.titleView!.grid.axis.rows = 1
} else if let d: UILabel = item.detailLabel {
d.grid.rows = 1
d.font = d.font.fontWithSize(12)
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 {
titleView.addSubview(d)
titleView.grid.views?.append(d)
d.grid.rows = 1
item.titleView!.addSubview(d)
item.titleView!.grid.axis.rows = 1
item.titleView!.grid.views?.append(d)
}
// rightControls
if let v: Array<UIControl> = item.rightControls {
var n: Array<UIBarButtonItem> = Array<UIBarButtonItem>()
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.intrinsicContentSize().width, h - contentInset.top - contentInset.bottom) : CGSizeMake(c.intrinsicContentSize().width, h - contentInset.top - contentInset.bottom)
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
spacer.width = inset + contentInset.left
n.append(spacer)
item.rightBarButtonItems = n.reverse()
}
item.titleView = titleView
}
/**
Sizes out the UINavigationItem.
- Parameter item: A UINavigationItem to layout.
*/
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
// TitleView alignment.
if let t: UILabel = item.titleLabel {
t.grid.rows = 1
if 32 >= h || nil == item.detailLabel {
t.font = t.font?.fontWithSize(20)
titleView.grid.axis.rows = 1
item.detailLabel?.hidden = true
} else if let d: UILabel = item.detailLabel {
t.font = t.font.fontWithSize(17)
d.font = d.font.fontWithSize(12)
d.grid.rows = 1
d.hidden = false
titleView.grid.axis.rows = 2
}
} else if let d: UIView = item.detailView {
d.grid.rows = 1
titleView.grid.axis.rows = 1
}
titleView.grid.reloadLayout()
}
// rightControls
if let v: Array<UIControl> = item.rightControls {
for c in v {
if let b: UIButton = c as? UIButton {
b.contentEdgeInsets.top = 0
b.contentEdgeInsets.bottom = 0
}
print(c.intrinsicContentSize())
c.bounds.size = c is MaterialSwitch ? CGSizeMake(backButton.intrinsicContentSize().width, h - 4) : CGSizeMake(c.intrinsicContentSize().width, h - 4)
}
}
item.titleView!.grid.reloadLayout()
}
/**
......@@ -398,10 +385,9 @@ public class NavigationBar : UINavigationBar {
private var NavigationItemKey: UInt8 = 0
public class NavigationItem {
/// Portrait Inset.
public var portraitInset: CGFloat = -16
/// Inset.
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
/// Detail View.
......@@ -433,7 +419,7 @@ public extension UINavigationItem {
}
}
/// Portrait Inset.
/// Portrait inset.
public var portraitInset: CGFloat {
get {
return item.portraitInset
......@@ -443,7 +429,7 @@ public extension UINavigationItem {
}
}
/// Landscape Inset.
/// Landscape inset.
public var landscapeInset: CGFloat {
get {
return item.landscapeInset
......@@ -502,4 +488,4 @@ public extension UINavigationItem {
item.rightControls = value
}
}
}
}
\ No newline at end of file
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