Download - Practical auto layout
Me
• Tom$Adriaenssen
• Lead&iOS&Dev&at&
• @Inferis&(Twi6er,&app.net)
• h6p://inferis.org
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 2
Prac%cal'Autolayout• Libraries
• Upda,ng/Constraints
• Intrins,c/Content/Size
• Alignment/Rects
• Baseline/alignment
• Priori,es
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 3
Libraries
• !"provided*APIs*are*cumbersome
• Wrapper*libraries*make*your*life*easier
• declara9ve*vs*impera9ve
• more*descrip9ve
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 4
Libraries• PureLayout+(Objec've)C,,CocoaPod)
• FLKLayout+(Objec've)C,,CocoaPod)
• Masonry+(Objec've)C,,CocoaPod)
• KeepLayout+(Objec've)C,,CocoaPod)
• Lyt+(Objec've)C,,CocoaPod)
• Cartography+(Swi5)
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 5
PureLayout
• Defines'categories'(auto*)'on'UIView/
NSView'&'NSArray
• Code'only,'no'stringAbased'DSL
• Support'for'prioriFes'via'blocks
• Originally'UIView+AutoLayout
• Github:'hNps://github.com/smileyborg/
PureLayout
• CocoaPod:
pod 'PureLayout'
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 6
PureLayout[self.blueView autoCenterInSuperview];[self.blueView autoSetDimensionsToSize:CGSizeMake(50.0, 50.0)];
s// Red view is positioned at the bottom right corner of the blue view, with the same width, and a height of 40 pt[self.redView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.blueView];[self.redView autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:self.blueView];[self.redView autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:self.blueView];[self.redView autoSetDimension:ALDimensionHeight toSize:40.0];
[@[self.redView, self.yellowView] autoSetViewsDimension:ALDimensionHeight toSize:50.0];[@[self.blueView, self.greenView] autoSetViewsDimension:ALDimensionHeight toSize:70.0];
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 7
FLKAutoLayout
• Category*on*UIView
• uses*predicates*for*priori5es*and*rela5ons
• Code*&*string9based*DSL*(predicates)
• Github:*hDps://github.com/floriankugler/FLKAutoLayout
• CocoaPod:
pod 'FLKAutoLayout'
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 8
FLKAutoLayout// align the first label with its superview[labels[0] alignTop:@"20" leading:@"20" toView:labels[0].superview];// give it a minimum width of 200 and a maximum width of 300[labels[0] constrainWidth:@">=200,<=300"];// now constrain all labels to this size[UIView alignLeadingAndTrailingEdgesOfViews:labels];// space the labels out vertically with 10 points in between[UIView spaceOutViewsVertically:labels predicate:@"10"];
// now let's take care of the text fields.// the first one has a fixed space of 20 to its label[textFields[0] constrainLeadingSpaceToView:labels[0] predicate:@"20"];// constrain the right edge to its superview with 20 points padding[textFields[0] alignTrailingEdgeWithView:textFields[0].superview predicate:@"20"];
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 9
Masonry
• Custom(layout(DSL
• define(constraints(in(mas_makeConstraints:(block
• Code(only,(no(string:based(DSL
• Github:(h>ps://github.com/Masonry/Masonry
• CocoaPod:
pod 'Masonry'
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 10
MasonryUIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);
[view1 mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(superview.mas_top).with.offset(padding.top); //with is an optional semantic filler make.left.equalTo(superview.mas_left).with.offset(padding.left); make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom); make.right.equalTo(superview.mas_right).with.offset(-padding.right);}];
// or even shorter[view1 mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(superview).with.insets(padding);}];
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 11
KeepLayout
• use%keep*%a*ributes%on%UIView/NSView%
to%define%layout
• Also%works%on%arrays%of%views
• Code%only,%no%stringBbased%DSL
• Github:%h*ps://github.com/iMarLnKiss/
KeepLayout
• CocoaPod:
pod 'KeepLayout'
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 12
KeepLayout// aligns are the same regardless of orderviewOne.keepLeftAlign(viewTwo) == viewTwo.keepLeftAlign(viewOne)
// left offset from 1 to 2 is right offset from 2 to 1viewOne.keepLeftOffset(viewTwo) == viewTwo.keepRightOffset(viewOne)
// array attributesNSArray *views = @[ viewOne, viewTwo, viewThree ];[views keepWidthsEqual];[views keepHorizontalOffsets:20];[views keepTopAligned];
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 13
Lyt
• Defines'categories'(lyt_*)'on'UIView/NSView
• Code'only,'no'string?based'DSL
• No'support'for'prioriEes'or'relaEons
• Github:'hIps://github.com/robotmedia/Lyt
• CocoaPod:
pod 'Lyt'
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 14
Lyt[view lyt_centerInParent];
// instead of
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:view.superview attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0];
NSLayoutConstraint *centerYConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:view.superview attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0];
[view.superview addConstraints:@[centerXConstraint, centerYConstraint]];
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 15
Cartography
• Swi%!
• Leverages.custom.operators.for.a.declara8ve.API
• Code.only
• Github:.hCps://github.com/robb/Cartography
• No.CocoaPod.yet
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 16
Cartographylayout(view1, view2) { view1, view2 in view1.width == (view1.superview!.width - 50) * 0.5 view2.width == view1.width - 50 view1.height == 40 view2.height == view1.height view1.centerX == view1.superview!.centerX view2.centerX == view1.centerX
view1.top >= view1.superview!.top + 20 view2.top == view1.bottom + 20}
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 17
LibrariesConsidera*ons
• does&the&library&give&you&access&to&the&created&constraints&for&modifica7ons
• do&you&prefer&string&based&DSLs,&code&only&or&a&mix?
• mostly&useful&in&larger&projects&where&you&have&to&manually&create&constraints
• for&simple&cases/projects&the&na7ve&APIs&might&do&finePrac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 18
Upda%ng(Constraints
• Don't"update"constraints"all"over"the"place
• "update"="add"/"delete
• changing"constants"is"no"problem
• use"updateConstraints"or"updateViewConstraints
• you"can"create"constraints"on"beforehand,"but"add"or"remove"them"in"updateConstraints
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 20
Upda%ng(Constraints
ExampleAutoLayoutAnimation.xcodeproj
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 21
Intrins'c)Content)Size
func intrinsicContentSize() -> CGSize
• only&for&"leaf"&views
• tells&the&layout&system&that&there&is&some&content&it&doesn’t&na7vely&understand&in&a&view
• provides&to&the&layout&system&the&intrinsic&size&of&that&content
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 23
Intrins'c)Content)Size
• return'UIViewNoIntrinsicMetric'if'you'don't'know'the'size'for'an'axis
• when'content'changes'the'intrins7c'content'size,'call'invalidateIntrinsicContentSize()
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 24
Intrins'c)Content)Size• you%can%use%constraints%to%provide%an%intrins1c%content%size%for%containers
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 25
Intrins'c)Content)Size
ExampleIntrinsticContentSize.xcodeproj
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 26
Alignment)Rects• Autolayout)does)not)work)on)frames,)but)on)alignment)rects
• For)most)views,)these)are)the)same)by)default
• a)powerful)tool)to)decouple)a)view’s)layout)alignment)edges)from)its)visual)appearance
• consider:
• intrinis>c)content)size)should)be)based)of)alignment)rects,)not)frames
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 28
Alignment)Rects
• bu$on'with'ornaments'(eg'badge)'▶️'larger'alignment'rect
• align'to'smaller'view'content'▶️'smaller'alignment'rect
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 29
Alignment)Rects
ExampleAutoLayoutAlignmentRects.xcodeprojAlignmentRectExamples.xcodeproj
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 30
Baseline(alignment
func viewForBaselineLayout() -> UIView?
• by$default,$AutoLayout$aligns$view$by$baseline$using$the$bo7om$of$the$view
• can$specify$any$child$view$of$view
• autolayout$will$use$this$view$for$baseline$aligment
• view$aligned$on$bo7om$of$view$returned$by$this$method
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 33
Baseline(alignment
• viewForBaselineLayout"works"only"on"iOS
• for"OSX"use"baselineOffsetFromBottom:
var baselineOffsetFromBottom: CGFloat { get }
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 34
Baseline(alignmentSome%issues
• dynamically*changing*this*view*is*not*possible
• have*to*remove*and*re6add*a*baseline*constraint
• buggy
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 35
Baseline(alignment
ExampleAutolayoutBaselineAlignment.xcodeproj
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 36
Priori%es• Using'priori+es'is'the'key'in'powerful'AutoLayout
• Define'mul+ple'constraints'on'the'same'a<ribute'with'different'priori+es
• if'possible'all'will'be'matched,'otherwise'those'with'lower'priori+es'are'dropped
• use'in'combina+on'with'hugging'priority'and'compression'priority
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 38
Pi#alls• constraints*are*cumula/ve
• constraints*do*not*override*each*other
• adding*a*second*width*constraint*does*not*remove*or*override*a*previous*one
• remove*first*one*manually
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 40
Pi#alls• be$careful$with$default$priori2es
• eg:$pinning$with$insets$7>$what$if$external$view$is$too$small$to$fit$insets?
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 41
Tips• constraints*can*cross*view*hierarchy
• add*constraint*from*view*to*superview*of*superview
• only*if*scope*of*view*hierarchy*uses*autolayout!*(no*custom*framese8ng*inbetween)
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 42
TipsAutoresizing,masks
• when&crea*ng&views&in&code,&set&translatesAutoresizingMaskIntoConstraints&to&NO.
• UIKit&will¬&add&equivalent&constraints&for&the&autoresizingMask&of&the&view
• these&(very&likely)&will&clash&with&your&own&constraints
• or,&clear&autoresizing&maskPrac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 43
TipsThink&rela+onal,¬&absolute
• some&mes'absolute'values'are'necessary
• most'of'the'&me'you'want'views'to'size'according'to'content
• content'is'(probably)'not'fixed
• views'are'o>en'not'the'sizes'you'expect'(iPhone6/6+!)
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 44
Tips• Autolayout)is)not)a)holy)grail
• Autolayout)seems)"easy")but)is)tricky)to)get)right
• frame)based)layout)is)o8en)faster)and)more)finetuned
• when)doing)frame)based)layout,)do)it)correctly
• in)layoutSubviews
• don't)confuse)bounds)and)frame
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 45
Examples
Can$be$found$here:
h"ps://github.com/Inferis/Prac7cal9AutoLayout
Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 49