Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Practical Autolayout

Practical Autolayout

This presentation was part of the CocoaHeadsBE session on Nov 27th, 2014 at the iCapps offices in Antwerp, Belgium.

You can find the examples here: https://github.com/Inferis/Practical-AutoLayout

1fad3e8e639182432b882758e986275f?s=128

Tom Adriaenssen

November 27, 2014
Tweet

Transcript

  1. Prac%cal'Autolayout CocoaHeadsBE+Nov+2014 Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 1

  2. Me • Tom$Adriaenssen • Lead&iOS&Dev&at& • @Inferis&(Twi6er,&app.net) • h6p:/ /inferis.org

    Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 2
  3. Prac%cal'Autolayout • Libraries • Upda,ng/Constraints • Intrins,c/Content/Size • Alignment/Rects •

    Baseline/alignment • Priori,es Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 3
  4. Libraries • !"provided*APIs*are*cumbersome • Wrapper*libraries*make*your*life*easier • declara9ve*vs*impera9ve • more*descrip9ve Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014

    4
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. Masonry UIEdgeInsets 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
  12. 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
  13. KeepLayout // aligns are the same regardless of order viewOne.keepLeftAlign(viewTwo)

    == viewTwo.keepLeftAlign(viewOne) // left offset from 1 to 2 is right offset from 2 to 1 viewOne.keepLeftOffset(viewTwo) == viewTwo.keepRightOffset(viewOne) // array attributes NSArray *views = @[ viewOne, viewTwo, viewThree ]; [views keepWidthsEqual]; [views keepHorizontalOffsets:20]; [views keepTopAligned]; Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 13
  14. 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
  15. 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
  16. 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
  17. Cartography layout(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
  18. Libraries Considera*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&fine Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 18
  19. Upda%ng(Constraints Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 19

  20. 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
  21. Upda%ng(Constraints Example AutoLayoutAnimation.xcodeproj Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 21

  22. Intrins'c)Content)Size Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 22

  23. 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
  24. 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

  25. Intrins'c)Content)Size • you%can%use%constraints%to%provide%an%intrins1c%content%size%for% containers Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 25

  26. Intrins'c)Content)Size Example IntrinsticContentSize.xcodeproj Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 26

  27. Alignment)Rects Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 27

  28. 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
  29. 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

  30. Alignment)Rects Example AutoLayoutAlignmentRects.xcodeproj AlignmentRectExamples.xcodeproj Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 30

  31. Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 31

  32. Baseline(alignment Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 32

  33. 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
  34. Baseline(alignment • viewForBaselineLayout"works"only"on"iOS • for"OSX"use"baselineOffsetFromBottom: var baselineOffsetFromBottom: CGFloat { get

    } Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 34
  35. Baseline(alignment Some%issues • dynamically*changing*this*view*is*not*possible • have*to*remove*and*re6add*a*baseline*constraint • buggy Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 35

  36. Baseline(alignment Example AutolayoutBaselineAlignment.xcodeproj Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 36

  37. Priori%es Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 37

  38. 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
  39. Pi#alls'&'Tips Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 39

  40. 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
  41. 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

  42. 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

  43. Tips Autoresizing,masks • when&crea*ng&views&in&code,&set& translatesAutoresizingMaskIntoConstraints&to&NO. • UIKit&will&not&add&equivalent&constraints&for&the& autoresizingMask&of&the&view • these&(very&likely)&will&clash&with&your&own&constraints

    • or,&clear&autoresizing&mask Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 43
  44. Tips Think&rela+onal,&not&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
  45. 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
  46. Thanks! Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 46

  47. Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 47

  48. Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 48

  49. Examples Can$be$found$here: h"ps:/ /github.com/Inferis/Prac7cal9AutoLayout Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 49