practical auto layout

49
Prac%cal Autolayout CocoaHeadsBE Nov 2014 Prac%cal Autolayout - © Tom Adriaenssen, 2014 1

Upload: inferis

Post on 17-Jul-2015

656 views

Category:

Technology


2 download

TRANSCRIPT

Prac%cal'AutolayoutCocoaHeadsBE+Nov+2014

Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 1

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

Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 19

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

Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 22

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

Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 27

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

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

Baseline(alignment

Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 32

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

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

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'&'Tips

Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 39

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&not&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,&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

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

Thanks!

Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 46

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

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

Examples

Can$be$found$here:

h"ps://github.com/Inferis/Prac7cal9AutoLayout

Prac%cal'Autolayout'-'©'Tom'Adriaenssen,'2014 49