Created
October 13, 2018 07:00
-
-
Save dgyesbreghs/27c304170cd9e293c38ccb67f18b95fa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// UIView+LayoutConstraints.h | |
// UIView+LayoutConstraints | |
// | |
// Created by Dylan Gyesbreghs on 02/02/2018. | |
// | |
#import <PureLayout.h> | |
typedef NS_ENUM(NSInteger, ALAnchor) { | |
ALAnchorLeft = NSLayoutAttributeLeft, // the left edge of the view | |
ALAnchorRight = NSLayoutAttributeRight, // the right edge of the view | |
ALAnchorTop = NSLayoutAttributeTop, // the top edge of the view | |
ALAnchorBottom = NSLayoutAttributeBottom, // the bottom edge of the view | |
ALAnchorLeading = NSLayoutAttributeLeading, // the leading edge of the view (left edge for left-to-right languages like English, right edge for right-to-left languages like Arabic) | |
ALAnchorTrailing = NSLayoutAttributeTrailing // the trailing edge of the view (right edge for left-to-right languages like English, left edge for right-to-left languages like Arabic) | |
}; | |
static inline ALEdge convertAnchor(ALAnchor anchor) { | |
switch (anchor) { | |
case ALAnchorLeft: | |
return ALEdgeLeft; | |
case ALAnchorRight: | |
return ALEdgeRight; | |
case ALAnchorTop: | |
return ALEdgeTop; | |
case ALAnchorBottom: | |
return ALEdgeBottom; | |
case ALAnchorLeading: | |
return ALEdgeLeading; | |
case ALAnchorTrailing: | |
return ALEdgeTrailing; | |
} | |
} | |
@interface UIView (LayoutConstraints) | |
//** Pins the left and right edge depending on the orientation so everything is correct for iPhone X | |
- (void)createLandscapePhoneConstraintWithArray:(NSMutableArray *)constraints; | |
#pragma mark - Superview Helpers | |
/** Pins the given edge of the view to the same edge of the superview with an inset. */ | |
- (NSLayoutConstraint *)autoPinAnchorToSuperviewAnchor:(ALAnchor)anchor withConstant:(CGFloat)constant; | |
/** Pins the edges of the view to the edges of its superview with edge insets zero. */ | |
- (NSArray *)autoPinAnchorsToSuperviewAnchors; | |
/** Pins 3 of the 4 edges of the view to the edges of its superview with the given edge insets, excluding one edge. */ | |
- (NSArray *)autoPinAnchorsToSuperviewAnchorsWithExcludingAnchor:(ALAnchor)anchor; | |
/** Pins the edges of the view to the edges of its superview with the given edge insets. */ | |
- (NSArray *)autoPinAnchorsToSuperviewAnchorsWithInsets:(UIEdgeInsets)insets; | |
/** Pins 3 of the 4 edges of the view to the edges of its superview with the given edge insets, excluding one edge. */ | |
- (NSArray *)autoPinAnchorsToSuperviewAnchorsWithInsets:(UIEdgeInsets)insets excludingAnchor:(ALAnchor)anchor; | |
#pragma mark - Dimensions Helpers | |
/** Sets the view to a specific size. */ | |
- (NSArray *)autoSetDimensionsToSize:(CGSize)size; | |
/** Sets the given dimension of the view to a specific size. */ | |
- (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size; | |
/** Matches a dimension of the view to a given dimension of another view. */ | |
- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension ofView:(UIView *)peerView; | |
///** Matches a dimension of the view to a given dimension of another view with an offset. */ | |
- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension ofView:(UIView *)peerView withOffset:(CGFloat)offset; | |
/** Return the layoutGuide for the correct iOS Version | |
< iOS 11 -> Margin Area Guide | |
>= iOS 11 -> Safe Area Guide | |
*/ | |
- (UILayoutGuide *)layoutGuide; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// UIView+LayoutConstraints.m | |
// UIView+LayoutConstraints | |
// | |
// Created by Dylan Gyesbreghs on 02/02/2018. | |
// | |
#import "UIView+LayoutConstraints.h" | |
@implementation UIView (LayoutConstraints) | |
- (void)createLandscapePhoneConstraintWithArray:(NSMutableArray *)constraints { | |
if (constraints == nil) { | |
constraints = [NSMutableArray arrayWithCapacity:2]; | |
} | |
[NSLayoutConstraint deactivateConstraints:constraints]; | |
[constraints removeAllObjects]; | |
if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeRight) { | |
[constraints addObjectsFromArray:@[[self autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:0],[self autoPinAnchorToSuperviewAnchor:ALAnchorLeft withConstant:0]]]; | |
} else if ([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft){ | |
[constraints addObjectsFromArray:@[[self autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:0],[self autoPinAnchorToSuperviewAnchor:ALAnchorRight withConstant:0]]]; | |
} else { | |
[constraints addObjectsFromArray:@[[self autoPinAnchorToSuperviewAnchor:ALAnchorRight withConstant:0], [self autoPinAnchorToSuperviewAnchor:ALAnchorLeft withConstant:0]]]; | |
} | |
} | |
#pragma mark - Superview Helpers | |
- (NSLayoutConstraint *)autoPinAnchorToSuperviewAnchor:(ALAnchor)anchor withConstant:(CGFloat)constant; | |
{ | |
if (![self respondsToSelector:@selector(safeAreaLayoutGuide)]) { | |
return [self autoPinEdgeToSuperviewEdge:convertAnchor(anchor) withInset:constant]; | |
} | |
NSLayoutConstraint *constraint; | |
if (anchor == ALAnchorBottom || anchor == ALAnchorRight || anchor == ALAnchorTrailing) { | |
// The bottom, right, and trailing insets (and relations, if an inequality) are inverted to become offsets | |
constant = -constant; | |
} | |
UILayoutGuide *layoutGuide = self.superview.layoutGuide; | |
switch (anchor) { | |
case ALAnchorTop: | |
constraint = [self.topAnchor constraintEqualToAnchor:layoutGuide.topAnchor | |
constant:constant]; | |
break; | |
case ALAnchorBottom: | |
constraint = [self.bottomAnchor constraintEqualToAnchor:layoutGuide.bottomAnchor | |
constant:constant]; | |
break; | |
case ALAnchorLeading: | |
constraint = [self.leadingAnchor constraintEqualToAnchor:layoutGuide.leadingAnchor | |
constant:constant]; | |
break; | |
case ALAnchorTrailing: | |
constraint = [self.trailingAnchor constraintEqualToAnchor:layoutGuide.trailingAnchor | |
constant:constant]; | |
break; | |
case ALAnchorLeft: | |
constraint = [self.leftAnchor constraintEqualToAnchor:layoutGuide.leftAnchor | |
constant:constant]; | |
break; | |
case ALAnchorRight: | |
constraint = [self.rightAnchor constraintEqualToAnchor:layoutGuide.rightAnchor | |
constant:constant]; | |
break; | |
} | |
constraint.active = YES; | |
return constraint; | |
} | |
- (NSArray *)autoPinAnchorsToSuperviewAnchors | |
{ | |
return [self autoPinAnchorsToSuperviewAnchorsWithInsets:UIEdgeInsetsZero]; | |
} | |
- (NSArray *)autoPinAnchorsToSuperviewAnchorsWithExcludingAnchor:(ALAnchor)anchor | |
{ | |
return [self autoPinAnchorsToSuperviewAnchorsWithInsets:UIEdgeInsetsZero excludingAnchor:anchor]; | |
} | |
- (NSArray *)autoPinAnchorsToSuperviewAnchorsWithInsets:(UIEdgeInsets)insets | |
{ | |
NSMutableArray *constraints = [NSMutableArray new]; | |
[constraints addObject:[self autoPinAnchorToSuperviewAnchor:ALAnchorTop withConstant:insets.top]]; | |
[constraints addObject:[self autoPinAnchorToSuperviewAnchor:ALAnchorLeading withConstant:insets.left]]; | |
[constraints addObject:[self autoPinAnchorToSuperviewAnchor:ALAnchorBottom withConstant:insets.bottom]]; | |
[constraints addObject:[self autoPinAnchorToSuperviewAnchor:ALAnchorTrailing withConstant:insets.right]]; | |
return constraints; | |
} | |
- (NSArray *)autoPinAnchorsToSuperviewAnchorsWithInsets:(UIEdgeInsets)insets excludingAnchor:(ALAnchor)anchor | |
{ | |
NSMutableArray *constraints = [NSMutableArray new]; | |
if (anchor != ALAnchorTop) { | |
[constraints addObject:[self autoPinAnchorToSuperviewAnchor:ALAnchorTop withConstant:insets.top]]; | |
} | |
if (anchor != ALAnchorLeading && anchor != ALAnchorLeft) { | |
[constraints addObject:[self autoPinAnchorToSuperviewAnchor:ALAnchorLeading withConstant:insets.left]]; | |
} | |
if (anchor != ALAnchorBottom) { | |
[constraints addObject:[self autoPinAnchorToSuperviewAnchor:ALAnchorBottom withConstant:insets.bottom]]; | |
} | |
if (anchor != ALAnchorTrailing && anchor != ALAnchorRight) { | |
[constraints addObject:[self autoPinAnchorToSuperviewAnchor:ALAnchorTrailing withConstant:insets.right]]; | |
} | |
return constraints; | |
} | |
#pragma mark - Dimensions | |
- (NSArray *)autoSetDimensionsToSize:(CGSize)size | |
{ | |
NSMutableArray *constraints = [NSMutableArray new]; | |
[constraints addObject:[self autoSetDimension:ALDimensionWidth toSize:size.width]]; | |
[constraints addObject:[self autoSetDimension:ALDimensionHeight toSize:size.height]]; | |
return constraints; | |
} | |
- (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size | |
{ | |
NSLayoutConstraint *constraint; | |
switch (dimension) { | |
case ALDimensionWidth: | |
constraint = [self.widthAnchor constraintEqualToConstant:size]; | |
break; | |
case ALDimensionHeight: | |
constraint = [self.heightAnchor constraintEqualToConstant:size]; | |
break; | |
} | |
constraint.active = YES; | |
return constraint; | |
} | |
- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension ofView:(UIView *)peerView | |
{ | |
return [self autoMatchDimension:dimension ofView:peerView withOffset:0]; | |
} | |
- (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension ofView:(UIView *)peerView withOffset:(CGFloat)offset | |
{ | |
NSLayoutConstraint *constraint; | |
switch (dimension) { | |
case ALDimensionWidth: | |
constraint = [self.widthAnchor constraintEqualToAnchor:peerView.layoutGuide.widthAnchor | |
constant:offset]; | |
break; | |
case ALDimensionHeight: | |
constraint = [self.heightAnchor constraintEqualToAnchor:peerView.layoutGuide.heightAnchor | |
constant:offset]; | |
break; | |
} | |
constraint.active = YES; | |
return constraint; | |
} | |
- (UILayoutGuide *)layoutGuide | |
{ | |
if (@available(iOS 11, *)) { | |
return self.safeAreaLayoutGuide; | |
} | |
return self.layoutMarginsGuide; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment