SlideShare a Scribd company logo
jano@jano.com.es
LayoutAuto
LayoutAuto
Layout
bounds
center }frame
transform
autoresizingMask
Layout
frame.origin = center - (bounds.size / 2.0)
center = frame.origin + (bounds.size / 2.0)
frame.size = bounds.size
bounds
center }frame
transform
autoresizingMask
Layout
frame.origin = center - (bounds.size / 2.0)
center = frame.origin + (bounds.size / 2.0)
frame.size = bounds.size
Layout
AutoLayout
AutoLayout
LayoutAutoLayout
LayoutAutoLayout
descriptive
constraint-based
pixel-perfect
modular
view1.attribute1 RELATION multiplier * view2.attribute2 + constant
button.center.y = 1 * superview.center.y + 0
! [NSLayout
! constrain
! attribute
! relatedBy
! toItem: s
! attribute
! multiplie
! constant:
What do I need to know?
What do I need to know?
UIView properties
alignmentRectInsets
constraints
contentSize
compression
hugging
translatesAutoresizingMaskIntoConstraints
What do I need to know?
UIView properties
Interface Builder > VFL > API
What do I need to know?
UIView properties
Interface Builder > VFL > API
UIViewController lifecycle
What do I need to know?
UIView properties
Interface Builder > VFL > API
Animation
UIView Properties
constraints
Layout
Content
Autosizing
NSLayoutConstraint
NSContentSizeLayoutConstraint
NSAutoresizingMaskLayoutConstraint
constraints
view1.attribute1 RELATION multiplier * view2.attribute2 + constant
NSLayoutAttributeLeft
NSLayoutAttributeRight
NSLayoutAttributeTop
NSLayoutAttributeBottom
NSLayoutAttributeLeading
NSLayoutAttributeTrailing
NSLayoutAttributeWidth
NSLayoutAttributeHeight
NSLayoutAttributeCenterX
NSLayoutAttributeCenterY
NSLayoutAttributeBaseline
NSLayoutAttributeNotAnAttribute
NSLayoutRelationEqual
NSLayoutRelationGreaterThanOrEqual
NSLayoutRelationLessThanOrEqual
constraints
! [NSLayoutConstraint
! constraintWithItem: button
! attribute: NSLayoutAttributeCenterX
! relatedBy: NSLayoutRelationEqual
! toItem: superview
! attribute: NSLayoutAttributeCenterX
! multiplier: 1.0
! constant: 0.0]
constraints
view1.attribute1 RELATION multiplier * view2.attribute2 + constant
! constraint = [NSLayoutConstraint
! constraintWithItem: view
! attribute: NSLayoutAttributeWidth
! relatedBy: NSLayoutRelationEqual
! toItem: nil
! attribute: NSLayoutAttributeNotAnAttribute
! multiplier: 1.0
! constant: 100.0];
[view addConstraint: constraint];
! constraint = [NSLayoutConstraint
! constraintWithItem: view
! attribute: NSLayoutAttributeWidth
! relatedBy: NSLayoutRelationEqual
! toItem: nil
! attribute: NSLayoutAttributeNotAnAttribute
! multiplier: 1.0
! constant: 80.0];
[view addConstraint: constraint];
size=100x80
CONSTRAINT_SIZE(view,100,80);
constraints
view1.attribute1 RELATION multiplier * view2.attribute2 + constant
linear equations
Cassowary Linear Arithmetic
Constraint Solving Algorithm
Pro tip: Use local flat hierarchies.
constraints
view1.attribute1 RELATION multiplier * view2.attribute2 + constant
http://pilky.me/view/36
constraints
view1.attribute1 RELATION multiplier * view2.attribute2 + constant
http://pilky.me/view/36
constraints
Screw-ups
invisible view {
{crash
{undefined
Size not set
Invalid
Ambiguous
Unsatisfiable
Unsatisfiable
Invalid
Ambiguous
view.hasAmbiguousLayout
view.exerciseAmbiguityInLayout
for (UIView *view in self.subviews) {
if ([view hasAmbiguousLayout]){
NSLog(@"<%@:0x%0x>", view.description, (int)self);
}
}
instrinsicContentSize
Suggested size for the view.
- (CGSize) intrinsicContentSize {
return mySize;
}
[self invalidateIntrinsicContentSize];
UIImage *img = UIImage imageNamed:@"Icon.png"];
UIImageView *iv = [[UIImageView alloc] initWithImage:img];
NSLog(@"%@", NSStringFromCGSize(iv.intrinsicContentSize));
Alignment rectangle
UIView
- (UIEdgeInsets)alignmentRectInsets
- (CGRect)frameForAlignmentRect:(CGRect)alignmentRect
- (CGRect)alignmentRectForFrame:(CGRect)frame
Show rect lines:
Hug & compress
Hugging resists stretching
Compression resists shrinking
UILayoutConstraintAxis axis = UILayoutConstraintAxisHorizontal;
UILayoutPriority p = UILayoutPriorityDefaultHigh;
[button setContentCompressionResistancePriority:p forAxis:axis];
[button setContentHuggingPriority:p forAxis:axis];
UIView properties
Interface Builder > VFL > API
Animation
Interface Builder
Interface Builder
Interface Builder
Interface Builder
Interface Builder
Interface Builder
IB > VFL > API
Constraints colors
IB can’t create ambiguous layouts
Add a constraint before deleting another
Preserve intrinsic size
Don’t optimize until everything is in place
UIView properties
Interface Builder > VFL > API
Animation
Visual Format Language
VFL
[NSLayoutConstraint
! constraintsWithVisualFormat:@"H:|-[buttonA]-|"
! options:0
! metrics:nil
! views:@{ @"buttonA" : buttonA }];
VFL
H V [view] | - @ ()
[NSLayoutConstraint
! constraintsWithVisualFormat:@"H:|-[buttonA]-|"
! options:0
! metrics:nil
! views:@{ @"buttonA" : buttonA }];
VFL
[NSLayoutConstraint
! constraintsWithVisualFormat:@"H:|-[buttonA]-|"
! options:0
! metrics:nil
! views:@{ @"buttonA" : buttonA }];
NSLayoutFormatAlignAllLeft
NSLayoutFormatAlignAllRight
NSLayoutFormatAlignAllTop
NSLayoutFormatAlignAllBottom
NSLayoutFormatAlignAllLeading
NSLayoutFormatAlignAllTrailing
NSLayoutFormatAlignAllCenterX
NSLayoutFormatAlignAllCenterY
NSLayoutFormatAlignAllBaseline
NSLayoutFormatAlignmentMask
NSLayoutFormatDirectionLeadingToTrailing
NSLayoutFormatDirectionLeftToRight
NSLayoutFormatDirectionRightToLeft
NSLayoutFormatDirectionMask
NSLayoutFormatOptions
VFL
[NSLayoutConstraint
! constraintsWithVisualFormat:@"H:|-[buttonA]-distance-|"
! options:0
! metrics: @{ @"distance": @50 }
! views:@{ @"buttonA" : buttonA }];
VFL
[NSLayoutConstraint
! constraintsWithVisualFormat:@"H:|-[buttonA]-distance-|"
! options:0
! metrics: @{ @"distance": @50 }
! views:@{ @"buttonA" : buttonA }];
VFL
[NSLayoutConstraint
! constraintsWithVisualFormat:@"H:|-[buttonA]-distance-|"
! options:0
! metrics: @{ @"distance": @50 }
! views:NSDictionaryOfVariableBindings(buttonA)];
VFL
H V [view] | - @ ()
Autolayout
Autolayout
Autolayout
Autolayout
Autolayout
H:[view1][view2]
H:[view1]-[view2]
H:[view1]-30-[view2]
H:[view1]-(==30)-[view2]
H:|[view1]-[view2]|
H:|-[view1]-(>=0)-[view2]-|
H:|-[view1(>=125,<=250)]-(>=0)-[view2]-|
H:[view1(>=view2)][view2]
H:[button(100@20)]
H:|[view1]-(>=50@30)-[view2]|
H:|-[view1(==view2)]-[view2]-|
H:[view1(view2)]
...
100x100 Square
- (void)viewDidLoad
{
[super viewDidLoad];
self.blueView.translatesAutoresizingMaskIntoConstraints = NO;
[self.blueView setContentHuggingPriority:UILayoutPriorityDefaultHigh
forAxis:UILayoutConstraintAxisHorizontal];
[self.blueView setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh
forAxis:UILayoutConstraintAxisVertical];
[self.blueView removeConstraints:self.blueView.constraints];
[self.blueView.superview removeConstraints:self.blueView.superview.constraints];
NSArray *constraints = @[ @"H:[blueView(100)]", @"V:[blueView(100)]"];
NSDictionary *views = @{@"blueView":self.blueView};
for (NSString *format in constraints)
{
[self.view addConstraints:
[NSLayoutConstraint
constraintsWithVisualFormat: format
options: 0
metrics: nil
views: views]];
}
}
UIView properties
Interface Builder > VFL > API
Animation
UIView API
UIView API
Opting in to Constraint-Based Layout
+ requiresConstraintBasedLayout
– translatesAutoresizingMaskIntoConstraints
– setTranslatesAutoresizingMaskIntoConstraints:
Managing Constraints
– constraints
– addConstraint:
– addConstraints:
– removeConstraint:
– removeConstraints:
Measuring in Constraint-Based Layout
– systemLayoutSizeFittingSize
– intrinsicContentSize
– invalidateIntrinsicContentSize
– contentCompressionResistancePriorityForAxis:
– setContentCompressionResistancePriority:forAxis:
– contentHuggingPriorityForAxis:
– setContentHuggingPriority:forAxis:
UIView API
Aligning Views with Constraint-Based Layout
– alignmentRectForFrame:
– frameForAlignmentRect:
– alignmentRectInsets
– viewForBaselineLayout
Triggering Constraint-Based Layout
– needsUpdateConstraints
– setNeedsUpdateConstraints
– updateConstraints
– updateConstraintsIfNeeded
Debugging Constraint-Based Layout
– constraintsAffectingLayoutForAxis:
– hasAmbiguousLayout
– exerciseAmbiguityInLayout
CALayer API
CALayer
– layoutIfNeeded
UIViewController
viewDidLoad
- autolayout-
viewDidLayoutSubviews
viewDidAppear
[self.view layoutIfNeeded]
UIView properties
Interface Builder > VFL > API
Animation
Animation
Animation
#238: Animate the constant
constant
self.someConstraint.constant = 10.0;
[UIView animateWithDuration:0.25 animations:^{
[self.view layoutIfNeeded];
}];
Animation
#238: Animate the constant.
#238: Call layoutIfNeeded in a block.
layoutIfNeeded
- (BOOL)continueTrackingWithTouch:(UITouch *)touch
withEvent:(UIEvent *)event
{
! CGPoint touchPoint = [touch locationInView:self];
! [UIView animateWithDuration:0.1f animations:^(){
! ! NSLayoutConstraint *constraint =
! ! [trackView constraintNamed:THUMB_POSITION_TAG];
! ! constraint.constant = touchPoint.x;
! ! [trackView layoutIfNeeded];
! }];
! return YES;
}
Animation
#238: Animate the constant.
#238: Call layoutIfNeeded in a block.
Animate layers instead of views.
Layer animation
// jumpy
[UIView animateWithDuration:0.3 delay:0
options:UIViewAnimationOptionAutoreverse
animations:^{
v.transform = CGAffineTransformMakeScale(1.1, 1.1);
} completion:^(BOOL finished) {
v.transform = CGAffineTransformIdentity;
}];
// smooth
CABasicAnimation* ba = [CABasicAnimation
animationWithKeyPath:@"transform"];
ba.autoreverses = YES;
ba.duration = 0.3;
ba.toValue = [NSValue
valueWithCATransform3D:CATransform3DMakeScale(1.1, 1.1, 1)];
[v.layer addAnimation:ba forKey:nil];
Animation
#238: Animate the constant.
#238: Call layoutIfNeeded in a block.
Animate layers instead of views.
Drop constraints, use autosizing masks.
Animation
#238: Animate the constant
#238: Call layoutIfNeeded in a block
Animate layers instead of views.
Drop constraints, use autosizing masks.
Use a container view.
Animation
#238: Animate the constant.
#238: Call layoutIfNeeded in a block.
Animate layers instead of views.
Drop constraints, use autosizing masks.
Use a container view.
Use constraints that don’t interfere.
Animation
#238: Animate the constant.
#238: Call layoutIfNeeded in a block.
Animate layers instead of views.
Drop constraints, use autosizing masks.
Use a container view.
Use constraints that don’t interfere.
Set frame in viewDidLayoutSubviews.
Animating Rotations
Fading in/out during rotation
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)to
duration:(NSTimeInterval)duration
{
! // fade away old layout
! [UIView animateWithDuration:duration animations:^{
! for (UIView *view in @[settingsView, creditsView])
! view.alpha = 0.0f;
! }];
}
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)from
{
! // update the layout for the new orientation
! [self updateViewConstraints];
! [self.view layoutIfNeeded];
! // fade in the new layout
! [UIView animateWithDuration:0.3f animations:^{
! for (UIView *view in @[settingsView, creditsView])
! view.alpha = 1.0f;
! }];
}
Update and animate changes
- (void) willAnimateRotationToInterfaceOrientation:
(UIInterfaceOrientation)to
duration:(NSTimeInterval)duration
{
! [UIView animateWithDuration:duration animations:^{
! ! [self updateViewConstraints];
! ! [self.view layoutIfNeeded];
! }];
}
Calling updates
UIDeviceOrientation newOrientation;
- (void) updateViewConstraints
{
! [super updateViewConstraints];
! [self.view removeConstraints:self.view.constraints];
! if (newOrientation==UIDeviceOrientationPortrait){
! ! // ...
! }
}
- (void) willRotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
{
! newOrientation = toInterfaceOrientation;
! [self updateViewConstraints];
}
References
#202 WWDC 2012: Introduction to Auto Layout for iOS and OS X
#228 WWDC 2012: Best Practices for Mastering Auto Layout
#232 WWDC 2012: Auto Layout by Example
#406 WWDC ’13 Taking Control of Auto Layout in Xcode 5
Cocoa Auto Layout Guide
iOS Auto Layout Demystified
$16

More Related Content

PPT
Autolayout in iOS
Singh Pushpendra
 
PDF
Autolayout primer
Inferis
 
PDF
iOS Layout Overview
Make School
 
PDF
Learn swiftla animations
Raghav Mangrola
 
PPT
Android Ui
Jetti Chowdary
 
PDF
Android custom views
christoforosnalmpantis
 
PDF
Auto layout
Yan-Ming Chiou
 
Autolayout in iOS
Singh Pushpendra
 
Autolayout primer
Inferis
 
iOS Layout Overview
Make School
 
Learn swiftla animations
Raghav Mangrola
 
Android Ui
Jetti Chowdary
 
Android custom views
christoforosnalmpantis
 
Auto layout
Yan-Ming Chiou
 

Viewers also liked (7)

PDF
AutoLayout y Size Classes
NSCoder Mexico
 
PDF
Understanding Auto Layout
Henrique Morbin
 
PDF
iOSプログラミングでAutoLayoutを数式のように記述する
Hisakuni Fujimoto
 
PDF
iOS AutoLayout
MinHyeok Kim
 
PPT
Introduction to Auto-layout : iOS/Mac
Mindfire Solutions
 
PDF
Auto Layout Under Control @ Pragma conference 2013
Giuseppe Arici
 
PDF
Desigining for auto_layout
Josh Burton
 
AutoLayout y Size Classes
NSCoder Mexico
 
Understanding Auto Layout
Henrique Morbin
 
iOSプログラミングでAutoLayoutを数式のように記述する
Hisakuni Fujimoto
 
iOS AutoLayout
MinHyeok Kim
 
Introduction to Auto-layout : iOS/Mac
Mindfire Solutions
 
Auto Layout Under Control @ Pragma conference 2013
Giuseppe Arici
 
Desigining for auto_layout
Josh Burton
 
Ad

Similar to Autolayout (20)

PDF
Ui perfomance
Cleveroad
 
KEY
Opening iOS App 開發者交流會
Michael Pan
 
KEY
CocoaHeads Toulouse - Guillaume Cerquant - UIView
CocoaHeads France
 
PPTX
Android Oreo
Siddharth Yadav
 
PPTX
Making it fit - DroidCon Paris 18 june 2013
Paris Android User Group
 
PDF
Макс Грибов — Использование SpriteKit в неигровых приложениях
CocoaHeads
 
PDF
What’s new in Android JetPack
Hassan Abid
 
PDF
Auto Layout
Julian Król
 
PDF
IOS APPs Revision
Muhammad Amin
 
PDF
iOS 上 self-sizing cell 的過去、現在、與未來
Jeff Lin
 
PDF
Optimize CollectionView Scrolling
Andrea Prearo
 
PDF
Lviv MD Day 2015 Костянтин Бичков "iOS Autolayouts – це добре!"
Lviv Startup Club
 
PDF
Introduction to Android Wear
Peter Friese
 
PDF
Heroku pop-behind-the-sense
Ben Lin
 
PDF
MOPCON 2014 - Best software architecture in app development
anistar sung
 
PDF
Exploring CameraX from JetPack
Hassan Abid
 
PDF
A Guide to Creating a Great Custom Tailwind Sidebar
RonDosh
 
PPTX
Android Custom views
Matej Vukosav
 
PPTX
Adaptive UI - 解像度の異なるデバイスや画面の向きに対応する 最適なレイアウトへ -
Yuji Hato
 
PDF
Massimo Artizzu - The tricks of Houdini: a magic wand for the future of CSS -...
Codemotion
 
Ui perfomance
Cleveroad
 
Opening iOS App 開發者交流會
Michael Pan
 
CocoaHeads Toulouse - Guillaume Cerquant - UIView
CocoaHeads France
 
Android Oreo
Siddharth Yadav
 
Making it fit - DroidCon Paris 18 june 2013
Paris Android User Group
 
Макс Грибов — Использование SpriteKit в неигровых приложениях
CocoaHeads
 
What’s new in Android JetPack
Hassan Abid
 
Auto Layout
Julian Król
 
IOS APPs Revision
Muhammad Amin
 
iOS 上 self-sizing cell 的過去、現在、與未來
Jeff Lin
 
Optimize CollectionView Scrolling
Andrea Prearo
 
Lviv MD Day 2015 Костянтин Бичков "iOS Autolayouts – це добре!"
Lviv Startup Club
 
Introduction to Android Wear
Peter Friese
 
Heroku pop-behind-the-sense
Ben Lin
 
MOPCON 2014 - Best software architecture in app development
anistar sung
 
Exploring CameraX from JetPack
Hassan Abid
 
A Guide to Creating a Great Custom Tailwind Sidebar
RonDosh
 
Android Custom views
Matej Vukosav
 
Adaptive UI - 解像度の異なるデバイスや画面の向きに対応する 最適なレイアウトへ -
Yuji Hato
 
Massimo Artizzu - The tricks of Houdini: a magic wand for the future of CSS -...
Codemotion
 
Ad

More from Jorge Ortiz (12)

PDF
Fiscalidad en el app store 2014
Jorge Ortiz
 
PDF
Fiscalidad en el app store 2014
Jorge Ortiz
 
PDF
Automatización de interfaces e introducción a bdd
Jorge Ortiz
 
PDF
Ui design patterns
Jorge Ortiz
 
PDF
Multipeer Connectivity Framework
Jorge Ortiz
 
PDF
iBeacons
Jorge Ortiz
 
PDF
Kata tdd
Jorge Ortiz
 
PDF
Crashlitycs
Jorge Ortiz
 
PDF
¿Cuánto cuesta una app?
Jorge Ortiz
 
KEY
Runtime
Jorge Ortiz
 
PPTX
Aplicaciones para iphone accesibles
Jorge Ortiz
 
PDF
Introduccion a core plot
Jorge Ortiz
 
Fiscalidad en el app store 2014
Jorge Ortiz
 
Fiscalidad en el app store 2014
Jorge Ortiz
 
Automatización de interfaces e introducción a bdd
Jorge Ortiz
 
Ui design patterns
Jorge Ortiz
 
Multipeer Connectivity Framework
Jorge Ortiz
 
iBeacons
Jorge Ortiz
 
Kata tdd
Jorge Ortiz
 
Crashlitycs
Jorge Ortiz
 
¿Cuánto cuesta una app?
Jorge Ortiz
 
Runtime
Jorge Ortiz
 
Aplicaciones para iphone accesibles
Jorge Ortiz
 
Introduccion a core plot
Jorge Ortiz
 

Recently uploaded (20)

PDF
Security features in Dell, HP, and Lenovo PC systems: A research-based compar...
Principled Technologies
 
PDF
Brief History of Internet - Early Days of Internet
sutharharshit158
 
PDF
Unlocking the Future- AI Agents Meet Oracle Database 23ai - AIOUG Yatra 2025.pdf
Sandesh Rao
 
PDF
Doc9.....................................
SofiaCollazos
 
PDF
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
PPTX
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
PPTX
Agile Chennai 18-19 July 2025 | Emerging patterns in Agentic AI by Bharani Su...
AgileNetwork
 
PDF
AI-Cloud-Business-Management-Platforms-The-Key-to-Efficiency-Growth.pdf
Artjoker Software Development Company
 
PDF
How ETL Control Logic Keeps Your Pipelines Safe and Reliable.pdf
Stryv Solutions Pvt. Ltd.
 
PDF
Automating ArcGIS Content Discovery with FME: A Real World Use Case
Safe Software
 
PDF
Accelerating Oracle Database 23ai Troubleshooting with Oracle AHF Fleet Insig...
Sandesh Rao
 
PDF
SparkLabs Primer on Artificial Intelligence 2025
SparkLabs Group
 
PDF
GDG Cloud Munich - Intro - Luiz Carneiro - #BuildWithAI - July - Abdel.pdf
Luiz Carneiro
 
PDF
Responsible AI and AI Ethics - By Sylvester Ebhonu
Sylvester Ebhonu
 
PDF
Using Anchore and DefectDojo to Stand Up Your DevSecOps Function
Anchore
 
PPTX
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
PDF
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
PPTX
Introduction to Flutter by Ayush Desai.pptx
ayushdesai204
 
PDF
Trying to figure out MCP by actually building an app from scratch with open s...
Julien SIMON
 
PDF
How Open Source Changed My Career by abdelrahman ismail
a0m0rajab1
 
Security features in Dell, HP, and Lenovo PC systems: A research-based compar...
Principled Technologies
 
Brief History of Internet - Early Days of Internet
sutharharshit158
 
Unlocking the Future- AI Agents Meet Oracle Database 23ai - AIOUG Yatra 2025.pdf
Sandesh Rao
 
Doc9.....................................
SofiaCollazos
 
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
OA presentation.pptx OA presentation.pptx
pateldhruv002338
 
Agile Chennai 18-19 July 2025 | Emerging patterns in Agentic AI by Bharani Su...
AgileNetwork
 
AI-Cloud-Business-Management-Platforms-The-Key-to-Efficiency-Growth.pdf
Artjoker Software Development Company
 
How ETL Control Logic Keeps Your Pipelines Safe and Reliable.pdf
Stryv Solutions Pvt. Ltd.
 
Automating ArcGIS Content Discovery with FME: A Real World Use Case
Safe Software
 
Accelerating Oracle Database 23ai Troubleshooting with Oracle AHF Fleet Insig...
Sandesh Rao
 
SparkLabs Primer on Artificial Intelligence 2025
SparkLabs Group
 
GDG Cloud Munich - Intro - Luiz Carneiro - #BuildWithAI - July - Abdel.pdf
Luiz Carneiro
 
Responsible AI and AI Ethics - By Sylvester Ebhonu
Sylvester Ebhonu
 
Using Anchore and DefectDojo to Stand Up Your DevSecOps Function
Anchore
 
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
Introduction to Flutter by Ayush Desai.pptx
ayushdesai204
 
Trying to figure out MCP by actually building an app from scratch with open s...
Julien SIMON
 
How Open Source Changed My Career by abdelrahman ismail
a0m0rajab1
 

Autolayout