Skip to content

Commit

Permalink
support Size Class
Browse files Browse the repository at this point in the history
  • Loading branch information
marty-suzuki committed Dec 10, 2015
1 parent 671661b commit e6939d9
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 27 deletions.
2 changes: 1 addition & 1 deletion MisterFusion.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Pod::Spec.new do |s|
s.name = "MisterFusion"
s.version = "0.6.0"
s.version = "0.7.0"
s.summary = "MisterFusion makes more easier to use AutoLayout in Swift & Objective-C code."

s.homepage = "https://github.com/szk-atmosphere/MisterFusion"
Expand Down
65 changes: 51 additions & 14 deletions MisterFusion/MisterFusion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ public class MisterFusion: NSObject {
private let multiplier: CGFloat?
private let constant: CGFloat?
private let priority: UILayoutPriority?
private let horizontalSizeClass: UIUserInterfaceSizeClass?
private let verticalSizeClass: UIUserInterfaceSizeClass?

init(item: UIView?, attribute: NSLayoutAttribute?, relatedBy: NSLayoutRelation?, toItem: UIView?, toAttribute: NSLayoutAttribute?, multiplier: CGFloat?, constant: CGFloat?, priority: UILayoutPriority?) {
init(item: UIView?, attribute: NSLayoutAttribute?, relatedBy: NSLayoutRelation?, toItem: UIView?, toAttribute: NSLayoutAttribute?, multiplier: CGFloat?, constant: CGFloat?, priority: UILayoutPriority?, horizontalSizeClass: UIUserInterfaceSizeClass?, verticalSizeClass: UIUserInterfaceSizeClass?) {
self.item = item
self.attribute = attribute
self.relatedBy = relatedBy
Expand All @@ -27,6 +29,8 @@ public class MisterFusion: NSObject {
self.multiplier = multiplier
self.constant = constant
self.priority = priority
self.horizontalSizeClass = horizontalSizeClass
self.verticalSizeClass = verticalSizeClass
super.init()
}

Expand Down Expand Up @@ -78,51 +82,75 @@ public class MisterFusion: NSObject {
return me |=| $0
}
}

public var HorizontalSizeClass: UIUserInterfaceSizeClass -> MisterFusion? {
return { [weak self] in
guard let me = self else { return nil }
return me <-> $0
}
}

public var VerticalSizeClass: UIUserInterfaceSizeClass -> MisterFusion? {
return { [weak self] in
guard let me = self else { return nil }
return me <|> $0
}
}
}

infix operator |==| { associativity left precedence 100 }
public func |==| (left: MisterFusion, right: MisterFusion) -> MisterFusion {
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: .Equal, toItem: right.item, toAttribute: right.attribute, multiplier: nil, constant: nil, priority: nil)
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: .Equal, toItem: right.item, toAttribute: right.attribute, multiplier: nil, constant: nil, priority: nil, horizontalSizeClass: nil, verticalSizeClass: nil)
}

infix operator |<=| { associativity left precedence 100 }
public func |<=| (left: MisterFusion, right: MisterFusion) -> MisterFusion {
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: .LessThanOrEqual, toItem: right.item, toAttribute: right.attribute, multiplier: nil, constant: nil, priority: nil)
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: .LessThanOrEqual, toItem: right.item, toAttribute: right.attribute, multiplier: nil, constant: nil, priority: nil, horizontalSizeClass: nil, verticalSizeClass: nil)
}

infix operator |>=| { associativity left precedence 100 }
public func |>=| (left: MisterFusion, right: MisterFusion) -> MisterFusion {
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: .GreaterThanOrEqual, toItem: right.item, toAttribute: right.attribute, multiplier: nil, constant: nil, priority: nil)
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: .GreaterThanOrEqual, toItem: right.item, toAttribute: right.attribute, multiplier: nil, constant: nil, priority: nil, horizontalSizeClass: nil, verticalSizeClass: nil)
}

infix operator |+| { associativity left precedence 100 }
public func |+| (left: MisterFusion, right: CGFloat) -> MisterFusion {
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: left.relatedBy, toItem: left.toItem, toAttribute: left.toAttribute, multiplier: left.multiplier, constant: right, priority: left.priority)
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: left.relatedBy, toItem: left.toItem, toAttribute: left.toAttribute, multiplier: left.multiplier, constant: right, priority: left.priority, horizontalSizeClass: left.horizontalSizeClass, verticalSizeClass: left.verticalSizeClass)
}

infix operator |-| { associativity left precedence 100 }
public func |-| (left: MisterFusion, right: CGFloat) -> MisterFusion {
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: left.relatedBy, toItem: left.toItem, toAttribute: left.toAttribute, multiplier: left.multiplier, constant: -right, priority: left.priority)
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: left.relatedBy, toItem: left.toItem, toAttribute: left.toAttribute, multiplier: left.multiplier, constant: -right, priority: left.priority, horizontalSizeClass: left.horizontalSizeClass, verticalSizeClass: left.verticalSizeClass)
}

infix operator |*| { associativity left precedence 100 }
public func |*| (left: MisterFusion, right: CGFloat) -> MisterFusion {
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: left.relatedBy, toItem: left.toItem, toAttribute: left.toAttribute, multiplier: right, constant: left.constant, priority: left.priority)
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: left.relatedBy, toItem: left.toItem, toAttribute: left.toAttribute, multiplier: right, constant: left.constant, priority: left.priority, horizontalSizeClass: left.horizontalSizeClass, verticalSizeClass: left.verticalSizeClass)
}

infix operator |/| { associativity left precedence 100 }
public func |/| (left: MisterFusion, right: CGFloat) -> MisterFusion {
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: left.relatedBy, toItem: left.toItem, toAttribute: left.toAttribute, multiplier: 1 / right, constant: left.constant, priority: left.priority)
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: left.relatedBy, toItem: left.toItem, toAttribute: left.toAttribute, multiplier: 1 / right, constant: left.constant, priority: left.priority, horizontalSizeClass: left.horizontalSizeClass, verticalSizeClass: left.verticalSizeClass)
}

infix operator |<>| { associativity left precedence 100 }
public func |<>| (left: MisterFusion, right: UILayoutPriority) -> MisterFusion {
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: left.relatedBy, toItem: left.toItem, toAttribute: left.toAttribute, multiplier: left.multiplier, constant: left.constant, priority: right)
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: left.relatedBy, toItem: left.toItem, toAttribute: left.toAttribute, multiplier: left.multiplier, constant: left.constant, priority: right, horizontalSizeClass: left.horizontalSizeClass, verticalSizeClass: left.verticalSizeClass)
}

infix operator |=| { associativity left precedence 100 }
public func |=| (left: MisterFusion, right: CGFloat) -> MisterFusion {
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: .Equal, toItem: nil, toAttribute: .NotAnAttribute, multiplier: left.multiplier, constant: right, priority: left.priority)
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: .Equal, toItem: nil, toAttribute: .NotAnAttribute, multiplier: left.multiplier, constant: right, priority: left.priority, horizontalSizeClass: left.horizontalSizeClass, verticalSizeClass: left.verticalSizeClass)
}

infix operator <-> { associativity left precedence 100 }
public func <-> (left: MisterFusion, right: UIUserInterfaceSizeClass) -> MisterFusion {
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: .Equal, toItem: nil, toAttribute: .NotAnAttribute, multiplier: left.multiplier, constant: left.constant, priority: left.priority, horizontalSizeClass: right, verticalSizeClass: left.verticalSizeClass)
}

infix operator <|> { associativity left precedence 100 }
public func <|> (left: MisterFusion, right: UIUserInterfaceSizeClass) -> MisterFusion {
return MisterFusion(item: left.item, attribute: left.attribute, relatedBy: .Equal, toItem: nil, toAttribute: .NotAnAttribute, multiplier: left.multiplier, constant: left.constant, priority: left.priority, horizontalSizeClass: left.horizontalSizeClass, verticalSizeClass: right)
}

extension UIView {
Expand Down Expand Up @@ -177,11 +205,20 @@ extension UIView {
public var CenterYWithinMargins: MisterFusion { return createMisterFusion(.CenterYWithinMargins) }

private func createMisterFusion(attribute: NSLayoutAttribute) -> MisterFusion {
return MisterFusion(item: self, attribute: attribute, relatedBy: nil, toItem: nil, toAttribute: nil, multiplier: nil, constant: nil, priority: nil)
return MisterFusion(item: self, attribute: attribute, relatedBy: nil, toItem: nil, toAttribute: nil, multiplier: nil, constant: nil, priority: nil, horizontalSizeClass: nil, verticalSizeClass: nil)
}

public func addLayoutConstraint(misterFusion: MisterFusion) -> NSLayoutConstraint {
public func addLayoutConstraint(misterFusion: MisterFusion) -> NSLayoutConstraint? {
let item: UIView = misterFusion.item ?? self
let traitCollection = UIApplication.sharedApplication().keyWindow?.traitCollection
if let horizontalSizeClass = misterFusion.horizontalSizeClass
where horizontalSizeClass != traitCollection?.horizontalSizeClass {
return nil
}
if let verticalSizeClass = misterFusion.verticalSizeClass
where verticalSizeClass != traitCollection?.verticalSizeClass {
return nil
}
let attribute: NSLayoutAttribute = misterFusion.attribute ?? .NotAnAttribute
let relatedBy: NSLayoutRelation = misterFusion.relatedBy ?? .Equal
let toAttribute: NSLayoutAttribute = misterFusion.toAttribute ?? attribute
Expand All @@ -195,14 +232,14 @@ extension UIView {
}

public func addLayoutConstraints(misterFusions: [MisterFusion]) -> [NSLayoutConstraint] {
return misterFusions.map { addLayoutConstraint($0) }
return misterFusions.map { addLayoutConstraint($0) }.filter { $0 != nil }.map { $0! }
}

public func addLayoutConstraints(misterFusions: MisterFusion...) -> [NSLayoutConstraint] {
return addLayoutConstraints(misterFusions)
}

public func addLayoutSubview(subview: UIView, andConstraint misterFusion: MisterFusion) -> NSLayoutConstraint {
public func addLayoutSubview(subview: UIView, andConstraint misterFusion: MisterFusion) -> NSLayoutConstraint? {
addSubview(subview)
subview.translatesAutoresizingMaskIntoConstraints = false
return addLayoutConstraint(misterFusion)
Expand Down
21 changes: 18 additions & 3 deletions MisterFusionSample/MisterFusionSample/MFViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
@interface MFViewController ()
@property (strong, nonatomic) UIView *greenView;
@property (strong, nonatomic) NSLayoutConstraint *greenViewBottomConstraint;

@property (strong, nonatomic) UIView *whiteView;
@property (strong, nonatomic) UIView *redView;
@property (strong, nonatomic) NSLayoutConstraint *whiteViewHeightConstraint;
@end

@implementation MFViewController
Expand All @@ -31,6 +35,7 @@ - (void)viewDidLoad {
[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0f constant:10.0f],
[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:0.5f constant:-15.0f]
]];
self.redView = redView;

UIView *yellowView = [UIView new];
yellowView.backgroundColor = [UIColor yellowColor];
Expand All @@ -57,12 +62,14 @@ - (void)viewDidLoad {

UIView *whiteView = [UIView new];
whiteView.backgroundColor = [UIColor whiteColor];
[redView addLayoutSubview:whiteView andConstraints:@[
self.whiteViewHeightConstraint = [redView addLayoutSubview:whiteView andConstraints:@[
whiteView.Bottom.Constant(-10.0f),
whiteView.Right.Constant(-10.0f),
whiteView.Left.Constant(10.0f),
whiteView.Height.NotRelatedConstant(100.0f)
]];
whiteView.Height.NotRelatedConstant(100.0f).VerticalSizeClass(UIUserInterfaceSizeClassRegular),
whiteView.Height.NotRelatedConstant(50.0f).VerticalSizeClass(UIUserInterfaceSizeClassCompact)
]].FirstAttribute(NSLayoutAttributeHeight).firstObject;
self.whiteView = whiteView;
}

- (void)viewDidAppear:(BOOL)animated {
Expand All @@ -74,6 +81,14 @@ - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[self.redView removeConstraint:self.whiteViewHeightConstraint];
self.whiteViewHeightConstraint = [self.redView addLayoutConstraints:@[
self.whiteView.Height.NotRelatedConstant(100.0f).VerticalSizeClass(UIUserInterfaceSizeClassRegular),
self.whiteView.Height.NotRelatedConstant(50.0f).VerticalSizeClass(UIUserInterfaceSizeClassCompact)
]].FirstAttribute(NSLayoutAttributeHeight).firstObject;
}

-(void)stretchAnmation {
self.greenViewBottomConstraint.constant = 0.0f;
Expand Down
24 changes: 20 additions & 4 deletions MisterFusionSample/MisterFusionSample/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ class ViewController: UIViewController {
private var greenView: UIView?
private var greenViewBottomConstraint: NSLayoutConstraint?

private var whiteView: UIView?
private var redView: UIView?
private var whiteViewHeightConstraint: NSLayoutConstraint?

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
Expand All @@ -28,6 +32,7 @@ class ViewController: UIViewController {
NSLayoutConstraint(item: redView, attribute: .Left, relatedBy: .Equal, toItem: view, attribute: .Left, multiplier: 1, constant: 10),
NSLayoutConstraint(item: redView, attribute: .Height, relatedBy: .Equal, toItem: view, attribute: .Height, multiplier: 0.5, constant: -15),
])
self.redView = redView

let yellowView = UIView()
yellowView.backgroundColor = .yellowColor()
Expand All @@ -54,12 +59,14 @@ class ViewController: UIViewController {

let whiteView = UIView()
whiteView.backgroundColor = .whiteColor()
redView.addLayoutSubview(whiteView, andConstraints:
whiteViewHeightConstraint = redView.addLayoutSubview(whiteView, andConstraints:
whiteView.Bottom |-| 10,
whiteView.Right |-| 10,
whiteView.Left |+| 10,
whiteView.Height |=| 100
)
whiteView.Height |=| 100 <|> .Regular,
whiteView.Height |=| 50 <|> .Compact
).firstAttribute(.Height).first
self.whiteView = whiteView
}

override func viewDidAppear(animated: Bool) {
Expand All @@ -71,7 +78,16 @@ class ViewController: UIViewController {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}


override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
guard let whiteView = whiteView, redView = redView, whiteViewHeightConstraint = whiteViewHeightConstraint else { return }
redView.removeConstraint(whiteViewHeightConstraint)
self.whiteViewHeightConstraint = redView.addLayoutConstraints(
whiteView.Height |=| 100 <|> .Regular,
whiteView.Height |=| 50 <|> .Compact
).firstAttribute(.Height).first
}

func stretchAnmation() {
greenViewBottomConstraint?.constant = 0
UIView.animateWithDuration(2, animations: {
Expand Down
Loading

0 comments on commit e6939d9

Please sign in to comment.