Commit cecb946a by Daniel Dahan

MaterialLayout now supports sibling alignment

parent 50ae46f4
...@@ -63,13 +63,6 @@ ...@@ -63,13 +63,6 @@
location = "group:Programmatic/ImageCardView/ImageCardView.xcodeproj"> location = "group:Programmatic/ImageCardView/ImageCardView.xcodeproj">
</FileRef> </FileRef>
</Group> </Group>
<Group
location = "container:"
name = "StackView">
<FileRef
location = "group:Programmatic/StackView/StackView.xcodeproj">
</FileRef>
</Group>
</Group> </Group>
<Group <Group
location = "container:" location = "container:"
......
...@@ -25,7 +25,8 @@ class ViewController: UIViewController { ...@@ -25,7 +25,8 @@ class ViewController: UIViewController {
prepareView() prepareView()
// Examples of using MaterialLayout. // Examples of using MaterialLayout.
prepareAlignCollectionToParentHorizontallyExample() prepareAlignToParentHorizontallyExample()
// prepareAlignToParentVerticallyExample()
} }
/** /**
...@@ -37,40 +38,105 @@ class ViewController: UIViewController { ...@@ -37,40 +38,105 @@ class ViewController: UIViewController {
} }
/** /**
:name: prepareAlignCollectionToParentHorizontallyExample :name: prepareAlignToParentHorizontallyExample
:description: General usage example. :description: Laying out views horizontally with equal width.
*/ */
private func prepareAlignCollectionToParentHorizontallyExample() { private func prepareAlignToParentHorizontallyExample() {
let view1: MaterialView = MaterialView() let label1: UILabel = UILabel()
view1.translatesAutoresizingMaskIntoConstraints = false label1.translatesAutoresizingMaskIntoConstraints = false
view1.backgroundColor = MaterialColor.blueGrey.base label1.backgroundColor = MaterialColor.red.base
view.addSubview(view1) label1.text = "A"
label1.textAlignment = .Center
view.addSubview(label1)
let view2: MaterialView = MaterialView() let label2: UILabel = UILabel()
view2.translatesAutoresizingMaskIntoConstraints = false label2.translatesAutoresizingMaskIntoConstraints = false
view2.backgroundColor = MaterialColor.blueGrey.darken1 label2.backgroundColor = MaterialColor.green.base
view.addSubview(view2) label2.text = "B"
label2.textAlignment = .Center
view.addSubview(label2)
let view3: MaterialView = MaterialView() let label3: UILabel = UILabel()
view3.translatesAutoresizingMaskIntoConstraints = false label3.translatesAutoresizingMaskIntoConstraints = false
view3.backgroundColor = MaterialColor.blueGrey.darken2 label3.backgroundColor = MaterialColor.blue.base
view.addSubview(view3) label3.text = "C"
label3.textAlignment = .Center
view.addSubview(label3)
let view4: MaterialView = MaterialView() let label4: UILabel = UILabel()
view4.translatesAutoresizingMaskIntoConstraints = false label4.translatesAutoresizingMaskIntoConstraints = false
view4.backgroundColor = MaterialColor.blueGrey.darken3 label4.backgroundColor = MaterialColor.yellow.base
view.addSubview(view4) label4.text = "D"
label4.textAlignment = .Center
view.addSubview(label4)
let view5: MaterialView = MaterialView() let children: Array<UIView> = [label1, label2, label3, label4]
view5.translatesAutoresizingMaskIntoConstraints = false
view5.backgroundColor = MaterialColor.blueGrey.darken4
view.addSubview(view5)
// let children: Array<UIView> = [view1, view2, view3, view4, view5] // Align the labels horizontally with an equal width.
// MaterialLayout.alignChildrenToParentHorizontally(view, children: children, left: 10, right: 10, options: [NSLayoutFormatOptions.AlignAllCenterX]) MaterialLayout.alignToParentHorizontally(view, children: children, left: 30, right: 30, spacing: 30)
// for v in children {
// MaterialLayout.height(view, child: v, height: 100) // Individually set the labels' vertical alignment.
// } // If this is left out, the intrinsic value is used for the view.
for v in children {
MaterialLayout.alignToParentVertically(view, child: v, top: 100, bottom: 100)
}
// Print out the dimensions of the labels.
for v in children {
v.layoutIfNeeded()
print(v.frame)
}
}
/**
:name: prepareAlignToParentVerticallyExample
:description: Laying out views vertically with equal height.
*/
private func prepareAlignToParentVerticallyExample() {
let label1: UILabel = UILabel()
label1.translatesAutoresizingMaskIntoConstraints = false
label1.backgroundColor = MaterialColor.red.base
label1.text = "A"
label1.textAlignment = .Center
view.addSubview(label1)
let label2: UILabel = UILabel()
label2.translatesAutoresizingMaskIntoConstraints = false
label2.backgroundColor = MaterialColor.green.base
label2.text = "B"
label2.textAlignment = .Center
view.addSubview(label2)
let label3: UILabel = UILabel()
label3.translatesAutoresizingMaskIntoConstraints = false
label3.backgroundColor = MaterialColor.blue.base
label3.text = "C"
label3.textAlignment = .Center
view.addSubview(label3)
let label4: UILabel = UILabel()
label4.translatesAutoresizingMaskIntoConstraints = false
label4.backgroundColor = MaterialColor.yellow.base
label4.text = "D"
label4.textAlignment = .Center
view.addSubview(label4)
let children: Array<UIView> = [label1, label2, label3, label4]
// Align the labels vertically with an equal height.
MaterialLayout.alignToParentVertically(view, children: children, top: 100, bottom: 100, spacing: 100)
// Individually set the labels' horizontal alignment.
// If this is left out, the intrinsic value is used for the view.
for v in children {
MaterialLayout.alignToParentHorizontally(view, child: v, left: 100, right: 100)
}
// Print out the dimensions of the labels.
for v in children {
v.layoutIfNeeded()
print(v.frame)
}
} }
} }
...@@ -43,7 +43,53 @@ class ViewController: UIViewController { ...@@ -43,7 +43,53 @@ class ViewController: UIViewController {
:description: General usage example. :description: General usage example.
*/ */
private func prepareGeneralStackViewExample() { private func prepareGeneralStackViewExample() {
let materialStackView: UIStackView = UIStackView()
materialStackView.distribution = .
view.addSubview(materialStackView)
materialStackView.translatesAutoresizingMaskIntoConstraints = false
MaterialLayout.alignToParent(view, child: materialStackView)
materialStackView.addArrangedSubview(createEntry())
materialStackView.addArrangedSubview(createEntry())
materialStackView.addArrangedSubview(createEntry())
}
private func createEntry() -> CardView {
let cardView: CardView = CardView()
// Title label.
let titleLabel: UILabel = UILabel()
titleLabel.text = "Welcome Back!"
titleLabel.textColor = MaterialColor.blue.darken1
titleLabel.font = RobotoFont.mediumWithSize(20)
cardView.titleLabel = titleLabel
// Detail label
let detailLabel: UILabel = UILabel()
detailLabel.text = "It’s been a while, have you read any new books lately?"
detailLabel.numberOfLines = 0
cardView.detailLabel = detailLabel
// Yes button.
let btn1: FlatButton = FlatButton()
btn1.pulseColor = MaterialColor.blue.lighten1
btn1.pulseFill = true
btn1.pulseScale = false
btn1.setTitle("YES", forState: .Normal)
btn1.setTitleColor(MaterialColor.blue.darken1, forState: .Normal)
// No button.
let btn2: FlatButton = FlatButton()
btn2.pulseColor = MaterialColor.blue.lighten1
btn2.pulseFill = true
btn2.pulseScale = false
btn2.setTitle("NO", forState: .Normal)
btn2.setTitleColor(MaterialColor.blue.darken1, forState: .Normal)
// Add buttons to left side.
cardView.leftButtons = [btn1, btn2]
return cardView
} }
} }
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:StackView.xcodeproj">
</FileRef>
</Workspace>
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'MK' s.name = 'MK'
s.version = '1.24.10' s.version = '1.24.11'
s.license = { :type => "AGPL-3.0", :file => "LICENSE" } s.license = { :type => "AGPL-3.0", :file => "LICENSE" }
s.summary = 'Beautiful Material Design in Swift.' s.summary = 'Beautiful Material Design in Swift.'
s.homepage = 'http://materialkit.io' s.homepage = 'http://materialkit.io'
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
9608ABCD1C190B8B0000BB93 /* StackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9608ABCC1C190B8B0000BB93 /* StackView.swift */; };
963832421B88DFD80015F710 /* MaterialKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 963832361B88DFD80015F710 /* MaterialKit.framework */; }; 963832421B88DFD80015F710 /* MaterialKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 963832361B88DFD80015F710 /* MaterialKit.framework */; };
9638325A1B88E31A0015F710 /* MaterialKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 963832581B88E31A0015F710 /* MaterialKitTests.swift */; }; 9638325A1B88E31A0015F710 /* MaterialKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 963832581B88E31A0015F710 /* MaterialKitTests.swift */; };
96D88C1E1C1328D800B91418 /* CaptureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D88BF51C1328D800B91418 /* CaptureView.swift */; }; 96D88C1E1C1328D800B91418 /* CaptureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96D88BF51C1328D800B91418 /* CaptureView.swift */; };
...@@ -93,7 +92,6 @@ ...@@ -93,7 +92,6 @@
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
9608ABCC1C190B8B0000BB93 /* StackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackView.swift; sourceTree = "<group>"; };
963832361B88DFD80015F710 /* MaterialKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MaterialKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 963832361B88DFD80015F710 /* MaterialKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MaterialKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
963832411B88DFD80015F710 /* MaterialKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MaterialKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 963832411B88DFD80015F710 /* MaterialKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MaterialKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
963832581B88E31A0015F710 /* MaterialKitTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaterialKitTests.swift; sourceTree = "<group>"; }; 963832581B88E31A0015F710 /* MaterialKitTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaterialKitTests.swift; sourceTree = "<group>"; };
...@@ -159,14 +157,6 @@ ...@@ -159,14 +157,6 @@
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
9608ABCB1C190B7C0000BB93 /* Stack */ = {
isa = PBXGroup;
children = (
9608ABCC1C190B8B0000BB93 /* StackView.swift */,
);
name = Stack;
sourceTree = "<group>";
};
9638322C1B88DFD80015F710 = { 9638322C1B88DFD80015F710 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
...@@ -214,7 +204,6 @@ ...@@ -214,7 +204,6 @@
96D88C4A1C13294200B91418 /* Type */, 96D88C4A1C13294200B91418 /* Type */,
96D88C491C13292700B91418 /* Capture */, 96D88C491C13292700B91418 /* Capture */,
96D88C471C1328F500B91418 /* Font */, 96D88C471C1328F500B91418 /* Font */,
9608ABCB1C190B7C0000BB93 /* Stack */,
); );
path = Sources; path = Sources;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -531,7 +520,6 @@ ...@@ -531,7 +520,6 @@
96D88C331C1328D800B91418 /* MaterialLabel.swift in Sources */, 96D88C331C1328D800B91418 /* MaterialLabel.swift in Sources */,
96D88C281C1328D800B91418 /* MaterialAnimation.swift in Sources */, 96D88C281C1328D800B91418 /* MaterialAnimation.swift in Sources */,
96D88C451C1328D800B91418 /* RobotoFont.swift in Sources */, 96D88C451C1328D800B91418 /* RobotoFont.swift in Sources */,
9608ABCD1C190B8B0000BB93 /* StackView.swift in Sources */,
96D88C1F1C1328D800B91418 /* CardView.swift in Sources */, 96D88C1F1C1328D800B91418 /* CardView.swift in Sources */,
96D88C2C1C1328D800B91418 /* MaterialColor.swift in Sources */, 96D88C2C1C1328D800B91418 /* MaterialColor.swift in Sources */,
96D88C301C1328D800B91418 /* MaterialEdgeInsets.swift in Sources */, 96D88C301C1328D800B91418 /* MaterialEdgeInsets.swift in Sources */,
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>FMWK</string> <string>FMWK</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.24.10</string> <string>1.24.11</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
......
...@@ -335,9 +335,9 @@ public class MaterialButton : UIButton { ...@@ -335,9 +335,9 @@ public class MaterialButton : UIButton {
} }
/** /**
:name: animation :name: animate
*/ */
public func animation(animation: CAAnimation) { public func animate(animation: CAAnimation) {
animation.delegate = self animation.delegate = self
if let a: CABasicAnimation = animation as? CABasicAnimation { if let a: CABasicAnimation = animation as? CABasicAnimation {
a.fromValue = (nil == layer.presentationLayer() ? layer : layer.presentationLayer() as! CALayer).valueForKeyPath(a.keyPath!) a.fromValue = (nil == layer.presentationLayer() ? layer : layer.presentationLayer() as! CALayer).valueForKeyPath(a.keyPath!)
......
...@@ -225,9 +225,9 @@ public class MaterialLayer : CAShapeLayer { ...@@ -225,9 +225,9 @@ public class MaterialLayer : CAShapeLayer {
} }
/** /**
:name: animation :name: animate
*/ */
public func animation(animation: CAAnimation) { public func animate(animation: CAAnimation) {
animation.delegate = self animation.delegate = self
if let a: CABasicAnimation = animation as? CABasicAnimation { if let a: CABasicAnimation = animation as? CABasicAnimation {
a.fromValue = valueForKeyPath(a.keyPath!) a.fromValue = valueForKeyPath(a.keyPath!)
......
...@@ -45,39 +45,39 @@ public struct MaterialLayout { ...@@ -45,39 +45,39 @@ public struct MaterialLayout {
MaterialLayout.height(parent, child: child, height: height) MaterialLayout.height(parent, child: child, height: height)
} }
// /** /**
// :name: alignChildrenToParentHorizontally :name: alignToParentHorizontally
// */ */
// public static func alignChildrenToParentHorizontally(parent: UIView, children: Array<UIView>, left: CGFloat = 0, right: CGFloat = 0, minimumInteritemSpacing: CGFloat = 0, options: NSLayoutFormatOptions = []) { public static func alignToParentHorizontally(parent: UIView, children: Array<UIView>, left: CGFloat = 0, right: CGFloat = 0, spacing: CGFloat = 0, options: NSLayoutFormatOptions = []) {
// if 0 < children.count { if 0 < children.count {
// var format: String = "H:" var format: String = "H:|-(left)-"
// var i: Int = 1 var i: Int = 1
// var views: Dictionary<String, UIView> = Dictionary<String, UIView>() var views: Dictionary<String, UIView> = Dictionary<String, UIView>()
// for v in children { for v in children {
// let k: String = "view\(i++)" let k: String = "view\(i++)"
// views[k] = v views[k] = v
// format += i > children.count ? "[\(k)]" : "[\(k)]" format += i > children.count ? "[\(k)(==view1)]-(right)-|" : "[\(k)(==view1)]-(spacing)-"
// } }
// print(format) parent.addConstraints(constraint(format, options: options, metrics: ["left" : left, "right": right, "spacing": spacing], views: views))
// parent.addConstraints(constraint(format, options: options, metrics: ["left" : left, "right": right, "minimumInteritemSpacing": minimumInteritemSpacing], views: views)) }
// } }
// }
// /**
// /** :name: alignToParentVertically
// :name: alignChildrenToParentVertically */
// */ public static func alignToParentVertically(parent: UIView, children: Array<UIView>, top: CGFloat = 0, bottom: CGFloat = 0, spacing: CGFloat = 0, options: NSLayoutFormatOptions = []) {
// public static func alignChildrenToParentVertically(parent: UIView, children: Array<UIView>, top: CGFloat = 0, bottom: CGFloat = 0, minimumLineSpacing: CGFloat = 0, options: NSLayoutFormatOptions = []) { if 0 < children.count {
// if 0 < children.count { var format: String = "V:|-(top)-"
// var format: String = "V:|-(left)-" var i: Int = 1
// var i: Int = 1 var views: Dictionary<String, UIView> = Dictionary<String, UIView>()
// var views: Dictionary<String, UIView> = Dictionary<String, UIView>() for v in children {
// for v in children { let k: String = "view\(i++)"
// views["view\(i++)"] = v views[k] = v
// format += i == children.count ? "[view\(i++)]-(right)-|" : "[view\(i++)]-(>=minimumLineSpacing)-" format += i > children.count ? "[\(k)(==view1)]-(bottom)-|" : "[\(k)(==view1)]-(spacing)-"
// } }
// parent.addConstraints(constraint(format, options: options, metrics: ["top" : top, "bottom": bottom, "minimumLineSpacing": minimumLineSpacing], views: views)) parent.addConstraints(constraint(format, options: options, metrics: ["top" : top, "bottom": bottom, "spacing": spacing], views: views))
// } }
// } }
/** /**
:name: alignToParentHorizontally :name: alignToParentHorizontally
......
...@@ -336,9 +336,9 @@ public class MaterialView : UIView { ...@@ -336,9 +336,9 @@ public class MaterialView : UIView {
} }
/** /**
:name: animation :name: animate
*/ */
public func animation(animation: CAAnimation) { public func animate(animation: CAAnimation) {
animation.delegate = self animation.delegate = self
if let a: CABasicAnimation = animation as? CABasicAnimation { if let a: CABasicAnimation = animation as? CABasicAnimation {
a.fromValue = (nil == layer.presentationLayer() ? layer : layer.presentationLayer() as! CALayer).valueForKeyPath(a.keyPath!) a.fromValue = (nil == layer.presentationLayer() ? layer : layer.presentationLayer() as! CALayer).valueForKeyPath(a.keyPath!)
......
//
// Copyright (C) 2015 CosmicMind, Inc. <http://cosmicmind.io> and other CosmicMind contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program located at the root of the software package
// in a file called LICENSE. If not, see <http://www.gnu.org/licenses/>.
//
import UIKit
@available(iOS 9.0, *)
public class StackView : UIStackView {
/**
:name: init
*/
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
prepareView()
}
/**
:name: init
*/
public override init(frame: CGRect) {
super.init(frame: frame)
prepareView()
}
/**
:name: init
*/
public convenience init() {
self.init(frame: CGRectNull)
}
/**
:name: prepareView
*/
private func prepareView() {
}
}
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