Slide 1

Slide 1 text

HUYEN TUE DAO @QUEENCODEMONKEY COOL CONSTRAINT LAYOUT

Slide 2

Slide 2 text

COOL THINGS ABOUT CONSTRAINT LAYOUT COOL THINGS TO DO WITH CONSTRAINT LAYOUT

Slide 3

Slide 3 text

WHAT IS THE CONSTRAINT LAYOUT?

Slide 4

Slide 4 text

RELATIONSHIPS BETWEEN VIEWS RELATIVE LAYOUT++ + (≈LINEARLAYOUT) EXPRESSIVE PERFORMANT

Slide 5

Slide 5 text

UNBUNDLED SUPPORTS API 9+ UI BUILDER USABLE WITH XML ONLY

Slide 6

Slide 6 text

HOW DOES IT WORK?

Slide 7

Slide 7 text

CONSTRAINTS EQUATIONS SOLVER 7 HOW DOES IT WORK?

Slide 8

Slide 8 text

HOW DOES IT WORK? CONSTRAINTS EQUATIONS SOLVER POSITION FIXED WRAP CONTENT MATCH CONSTRAINT RATIO EDGE CENTER BASELINE DIMENSION OTHER 8 GUIDELINES CHAINS CONSTRAINT SET

Slide 9

Slide 9 text

CONSTRAINTS EQUATIONS SOLVER LINEAR SYSTEM OF EQUATIONS/INEQUALITIES 9 HOW DOES IT WORK? 11 + … + 1n = 11 + … + 1n ≤ 11 + … + 1n ≥

Slide 10

Slide 10 text

CONSTRAINTS EQUATIONS SOLVER CASSOWARY LINEAR ARITHMETIC CONSTRAINT SOLVING ALGORITHM VIEW BOUNDS 10 HOW DOES IT WORK?

Slide 11

Slide 11 text

CONSTRAINTLAYOUT, INSIDE AND OUT: PART 2 DAVE SMITH

Slide 12

Slide 12 text

LET’S TAKE A QUICK TOUR

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

CONSTRAINT LAYOUT CHEAT SHEET

Slide 15

Slide 15 text

SOURCE TARGET EDGE CONSTRAINT 
 app:layout_constraintLeft_toLeftOf="parent" 
 app:layout_constraint_toOf=“a_view"

Slide 16

Slide 16 text

CENTER CONSTRAINT 
 app:layout_constraintHorizontal_bias="0.75"

Slide 17

Slide 17 text

BASELINE CONSTRAINT app:layout_constraintBaseline_toBaselineOf="@+id/view"

Slide 18

Slide 18 text

SIZE CONSTRAINTS

Slide 19

Slide 19 text

GUIDELINES

Slide 20

Slide 20 text


 
 


Slide 21

Slide 21 text

SO WHAT CAN WE DO WITH CONSTRAINT LAYOUT?

Slide 22

Slide 22 text

public class SquareImageView extends ImageView { @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
 final int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
 setMeasuredDimension(size, size);
 }

Slide 23

Slide 23 text

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text


 H,16:10 app:layout_constraintDimensionRatio=“@string/hero_ratio"

Slide 26

Slide 26 text

IS IT REALLY BETTER THAN RELATIVE LAYOUT?

Slide 27

Slide 27 text

STYLING ANDROID CONSTRAINTLAYOUT PART 6

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

private fun updateManualAnchors() {
 val size = anchorMinSize + seekBar.progress
 val halfSize = Math.round(size * 0.5f)
 val horizontalMargin = resources.getDimensionPixelSize(R.dimen.content_margin_horizontal) - halfSize
 val verticalMargin = resources.getDimensionPixelSize(R.dimen.alignment_rectangle_margin_vertical) - halfSize
 updateManualAnchor(frameAnchorTop, size, verticalMargin, 0, 0, 0)
 updateManualAnchor(frameAnchorStart, size, 0, horizontalMargin, 0, 0)
 updateManualAnchor(frameAnchorBottom, size, 0, 0, verticalMargin, 0)
 updateManualAnchor(frameAnchorEnd, size, 0, 0, 0, horizontalMargin)
 }
 
 private fun updateManualAnchor(anchor: View, size: Int,
 marginTop: Int, marginStart: Int,
 marginBottom: Int, marginEnd: Int) {
 val layoutParams = anchor.layoutParams as FrameLayout.LayoutParams layoutParams.width = size
 layoutParams.height = size
 layoutParams.topMargin = marginTop
 layoutParams.bottomMargin = marginBottom
 layoutParams.marginStart = marginStart
 layoutParams.marginEnd = marginEnd anchor.layoutParams = layoutParams
 } WITH CONSTRAINTLAYOUT JUST CHANGE THE SIZE…

Slide 30

Slide 30 text

WHAT WAS THAT ABOUT LINEAR LAYOUT?

Slide 31

Slide 31 text

CHAINS. CHAINS. CHAINS. FROM CONSTRAINTLAYOUT DOCUMENTATION

Slide 32

Slide 32 text

SPREAD INSIDE CHAIN

Slide 33

Slide 33 text

33 WEIGHTED CHAIN

Slide 34

Slide 34 text

34 PACKED CHAIN

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

A CONSTRAINT LAYOUT SPECIAL CONSTRAINT SET

Slide 37

Slide 37 text

CONSTRAINT SET CREATE/SAVE/APPLY CREATE MANUALLY CLONE A LAYOUT FILE CLONE A CONSTRAINT LAYOUT AWESOME WITH TRANSITIONS DEFINE SET OF CONSTRAINTS PROGRAMMATICALLY

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

// Inflate initial layout as usual. setContentView(R.layout.activity_constraintset_01) // Get references to controls
 constraintLayout = findViewById(R.id.constraint_layout) as ConstraintLayout
 
 // Load ConstraintSets.
 constraintSet01.clone(constraintLayout)
 constraintSet02.clone(this, R.layout.activity_constraintset_02) …some time later… // Toggle ConstraintSets. TransitionManager.beginDelayedTransition(constraintLayout)
 if (original) constraintSet02.applyTo(constraintLayout)
 else constraintSet01.applyTo(constraintLayout)
 original = !original 39

Slide 40

Slide 40 text

YES, LIST ITEMS CAN BE CONSTRAINT LAYOUTS

Slide 41

Slide 41 text

CONSTRAINT SET IN LIEU OF CUSTOM VIEWGROUP

Slide 42

Slide 42 text

CUSTOM VIEW GROUPS GENERALIZED, REUSABLE LAYOUTS PERFORMANT COMPOSITE LAYOUTS LAYOUT IS LOW-LEVEL (X, Y) EVEN SIMPLE ONES = MUCH CODE ADVANCED LAYOUTS… WOAH

Slide 43

Slide 43 text

@Override
 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
 MarginLayoutParams layoutParams = (MarginLayoutParams) icon.getLayoutParams();
 
 // Figure out the x-coordinate and y-coordinate of the icon.
 int x = getPaddingLeft() + layoutParams.leftMargin;
 int y = getPaddingTop() + layoutParams.topMargin;
 
 // Layout the icon.
 icon.layout(x, y, x + icon.getMeasuredWidth(), y + icon.getMeasuredHeight());
 
 // Calculate the x-coordinate of the title: icon's right coordinate +
 // the icon's right margin.
 x += icon.getMeasuredWidth() + layoutParams.rightMargin;
 
 // Add in the title's left margin.
 layoutParams = (MarginLayoutParams) titleView.getLayoutParams();
 x += layoutParams.leftMargin;
 
 // Calculate the y-coordinate of the title: this ViewGroup's top padding +
 // the title's top margin
 y = getPaddingTop() + layoutParams.topMargin;
 
 // Layout the title.
 titleView.layout(x, y, x + titleView.getMeasuredWidth(), y + titleView.getMeasuredHeight());
 
 // The subtitle has the same x-coordinate as the title. So no more calculating there.
 
 // Calculate the y-coordinate of the subtitle: the title's bottom coordinate +
 // the title's bottom margin.
 y += titleView.getMeasuredHeight() + layoutParams.bottomMargin;
 layoutParams = (MarginLayoutParams) subtitleView.getLayoutParams();
 
 // Add in the subtitle's top margin.
 y += layoutParams.topMargin;
 
 // Layout the subtitle.
 subtitleView.layout(x, y,
 x + subtitleView.getMeasuredWidth(), y + subtitleView.getMeasuredHeight());
 } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Measure icon. measureChildWithMargins(icon, widthMeasureSpec, 0, heightMeasureSpec, 0); // Figure out how much width the icon used. MarginLayoutParams lp = (MarginLayoutParams) icon.getLayoutParams(); int widthUsed = icon.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; int heightUsed = 0; // Measure title measureChildWithMargins( titleView, // Pass width constraints and width already used. widthMeasureSpec, widthUsed, // Pass height constraints and height already used. heightMeasureSpec, heightUsed ); // Measure the Subtitle. measureChildWithMargins( subtitleView, // Pass width constraints and width already used. widthMeasureSpec, widthUsed, // Pass height constraints and height already used. heightMeasureSpec, titleView.getMeasuredHeight()); // Calculate this view's measured width and height. // Figure out how much total space the icon used. int iconWidth = icon.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; int iconHeight = icon.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; lp = (MarginLayoutParams) titleView.getLayoutParams(); // Figure out how much total space the title used. int titleWidth = titleView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; int titleHeight = titleView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; lp = (MarginLayoutParams) subtitleView.getLayoutParams(); // Figure out how much total space the subtitle used. int subtitleWidth = subtitleView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; int subtitleHeight = subtitleView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; // The width taken by the children + padding. int width = getPaddingTop() + getPaddingBottom() + iconWidth + Math.max(titleWidth, subtitleWidth); // The height taken by the children + padding. int height = getPaddingTop() + getPaddingBottom() + Math.max(iconHeight, titleHeight + subtitleHeight); // Reconcile the measured dimensions with the this view's constraints and // set the final measured width and height. setMeasuredDimension( resolveSize(width, widthMeasureSpec), resolveSize(height, heightMeasureSpec) ); }

Slide 44

Slide 44 text

CONSTRAINT SET IN LIEU OF CUSTOM VIEWGROUP

Slide 45

Slide 45 text

private fun addRow(view: View) {
 constraintLayout.addView(view)
 
 val id = view.id
 constraintSet.constrainWidth(id, MATCH_CONSTRAINT)
 constraintSet.constrainHeight(id, rowHeight)
 
 // Constrain new view vertically.
 val target = if (lastRowId  PARENT_ID) TOP else BOTTOM
 constraintSet.connect(id, TOP, lastRowId, target) // Constrain new view horizontally.
 constraintSet.connect(id, START, PARENT_ID, START)
 constraintSet.connect(id, END, PARENT_ID, END)
 
 // Toggle elevation to elevate last added view.
 constraintSet.setElevation(id, resources.getDimension(R.dimen.elevation))
 constraintSet.setElevation(lastViewId, 0f)
 
 // Apply constraints.
 constraintSet.applyTo(constraintLayout) 45

Slide 46

Slide 46 text

private fun addRowItem(view: View) {
 …
 constraintLayout.addView(view)
 
 val id = view.id
 
 // Initialize width and height of new view.
 constraintSet.constrainWidth(id, MATCH_CONSTRAINT)
 constraintSet.constrainHeight(id, rowHeight)
 
 // Constrain new view vertically.
 val target = if (lastRowId  PARENT_ID) TOP else BOTTOM
 constraintSet.connect(id, TOP, lastRowId, target) 46

Slide 47

Slide 47 text

// Update current row.
 currentRowIds.add(id)
 // Re-create horizontal chain with other row items.
 constraintSet.createHorizontalChainRtl(
 PARENT_ID, START,
 PARENT_ID, END,
 currentRowIds.toIntArray(), FloatArray(currentRow.size, { 1f }),
 CHAIN_SPREAD_INSIDE)
 
 // Toggle elevation to elevate last added view.
 constraintSet.setElevation(id, resources.getDimension(R.dimen.elevation))
 constraintSet.setElevation(lastViewId, 0f)
 
 // Apply constraints.
 constraintSet.applyTo(constraintLayout) 47

Slide 48

Slide 48 text

SERIOUSLY COOL THINGS IN CONSTRAINT LAYOUT

Slide 49

Slide 49 text

ANDROID DEVELOPERS BACKSTAGE EPISODE 50: CONSTRAINT LAYOUT

Slide 50

Slide 50 text

CONSTRAINTLAYOUT CREW JOHN HOFORD @JOHNHOFORD NICOLAS ROARD @CAMAELON

Slide 51

Slide 51 text

THANK YOU! SPEAKERDECK.COM/QUEENCODEMONKEY YOUTUBE.COM/ANDROIDDIALOGS RANDOMLYTYPING.COM HUYEN TUE DAO @QUEENCODEMONKEY QUEENCODEMONKEY/PRESENTATION-COOL-CONSTRAINTLAYOUT

Slide 52

Slide 52 text

REFERENCES 52 CONSTRAINT LAYOUT APIS DOCUMENTATION https://developer.android.com/reference/android/support/constraint/package-summary.html BUILD A RESPONSIVE UI WITH CONSTRAINTLAYOUT developer.android.com/training/constraint-layout/index.html ANDROID DEVELOPERS BACKSTAGE: EPISODE 50: CONSTRAINT LAYOUT androidbackstage.blogspot.com/2016/06/episode-50-constraint-layout.html USING CONSTRAINTLAYOUT TO DESIGN YOUR VIEWS | CODE LABS codelabs.developers.google.com/codelabs/constraint-layout/index.html ANDROID LAYOUTS: A NEW WORLD | GOOGLE I/O 2016 https://youtu.be/sO9aX87hq9c CONSTRAINTLAYOUT https://speakerdeck.com/writtmeyer/constraintlayout-1 ADVANCED CONSTRAINTLAYOUT http://cfp.devoxx.us/2017/talk/XOD-8930/Advanced_ConstraintLayout

Slide 53

Slide 53 text

REFERENCES 53 CONSTRAINTLAYOUT – PART 1 blog.stylingandroid.com/constraintlayout-part-1/ CONSTRAINTLAYOUT, INSIDE AND OUT: PART 1 http://wiresareobsolete.com/2016/07/constraintlayout-part-1/ SOME THOUGHTS ON ANDROID’S NEW CONSTRAINTLAYOUT AND ANDROID STUDIO’S NEW DESIGN EDITOR http://www.grokkingandroid.com/thoughts-on-constraintlayout-and-design-editor/ BUILD A UI WITH LAYOUT EDITOR developer.android.com/studio/write/layout-editor.html WHAT'S NEW IN ANDROID DEVELOPMENT TOOLS | GOOGLE I/O 2016 https://youtu.be/csaXml4xtN8 THE EXPERTS' GUIDE TO ANDROID DEVELOPMENT TOOLS | GOOGLE I/O 2016 https://youtu.be/hHnTIMjd1Y8 JOHN HOFORD & NICOLAS ROARD : CONSTRAINTLAYOUT | ANDROID DIALOGS https://youtu.be/hHnTIMjd1Y8