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

Design and Implementation of Custom Layout on Android

Design and Implementation of Custom Layout on Android

Basics for creating custom layout extending ViewGroup.
Example layout implementation (FloatingLayout)

https://github.com/yhpark/FloatingLayout

* Presented at Google DevFest W Seoul 2013

Yeonghoon Park

March 02, 2013
Tweet

More Decks by Yeonghoon Park

Other Decks in Programming

Transcript

  1. Measure (implementing onMeasure) Measure child views childView.measure(int widthMeasureSpec, int heightMeasureSpec)

    Measure itself (using MeasureSpecs) setMeasuredDimension(int measuredWidth, int measuredHeight) MUST be called (or an Exception will be thrown)
  2. MeasureSpec int - (MMMMSSSSSSSSSSSSSSSSSSSSSSSSSSSS) mode AT_MOST - The child can

    be as large as it wants up to the specified size. EXACTLY - The parent has determined an exact size for the child. The child is going to be given those bounds regardless of how big it wants to be. UNSPECIFIED - The parent has not imposed any constraint on the child. It can be whatever size it wants. size (px)
  3. Measure ex) LinearLayout (match_parent, wrap_content) height = paddingTop + paddingBottom

    + max(child height + child marginTop + child marginBottom)
  4. Measure ex) LinearLayout (match_parent, wrap_content) height = paddingTop + paddingBottom

    + max(child height + child marginTop + child marginBottom) paddingLeft
  5. Measure ex) LinearLayout (match_parent, wrap_content) height = paddingTop + paddingBottom

    + max(child height + child marginTop + child marginBottom) paddingLeft child marginLeft
  6. Measure ex) LinearLayout (match_parent, wrap_content) height = paddingTop + paddingBottom

    + max(child height + child marginTop + child marginBottom) paddingLeft foo child.measuredWidth child marginLeft
  7. Measure ex) LinearLayout (match_parent, wrap_content) height = paddingTop + paddingBottom

    + max(child height + child marginTop + child marginBottom) paddingLeft foo child.measuredWidth child marginLeft child marginRight
  8. Measure ex) LinearLayout (match_parent, wrap_content) height = paddingTop + paddingBottom

    + max(child height + child marginTop + child marginBottom) paddingLeft foo child.measuredWidth child marginLeft child marginLeft child marginRight
  9. Measure ex) LinearLayout (match_parent, wrap_content) height = paddingTop + paddingBottom

    + max(child height + child marginTop + child marginBottom) paddingLeft foo child.measuredWidth child marginLeft child marginLeft bar child.measuredWidth child marginRight
  10. Measure ex) LinearLayout (match_parent, wrap_content) height = paddingTop + paddingBottom

    + max(child height + child marginTop + child marginBottom) paddingLeft foo child.measuredWidth child marginLeft child marginLeft bar child.measuredWidth child marginRight child marginRight
  11. Measure ex) LinearLayout (match_parent, wrap_content) height = paddingTop + paddingBottom

    + max(child height + child marginTop + child marginBottom) paddingLeft foo child.measuredWidth child marginLeft child marginLeft bar child.measuredWidth child marginRight child marginRight paddingRight
  12. Measure ex) LinearLayout (match_parent, wrap_content) height = paddingTop + paddingBottom

    + max(child height + child marginTop + child marginBottom) paddingLeft foo child.measuredWidth child marginLeft child marginLeft bar child.measuredWidth child marginRight child marginRight paddingRight s
  13. Measure ex) LinearLayout (match_parent, wrap_content) height = paddingTop + paddingBottom

    + max(child height + child marginTop + child marginBottom) paddingLeft foo child.measuredWidth child marginLeft child marginLeft bar child.measuredWidth child marginRight child marginRight paddingRight lorem ipsum... AT_MOST(s) s
  14. Measure ex) LinearLayout (wrap_content, wrap_content) height = paddingTop + paddingBottom

    + max(child height + child marginTop + child marginBottom)
  15. Measure helper methods for measuring child (in ViewGroup) measureChild(View child,

    int parentWidthMeasureSpec, int parentHeightMeasureSpec) measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed)
  16. Layout (implementing onLayout) Layout child views child.layout(int l, int t,

    int r, int b) Layout itself layout(l,t,r,b) will be called from its parent.
  17. Layout layout(int l, int t, int r, int b) or

    layout(x, y, x + measuredWidth, y + measuredHeight)
  18. Layout Gravity ex) LinearLayout.java 1449 final int majorGravity = mGravity

    & Gravity.VERTICAL_GRAVITY_MASK; 1450 final int minorGravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK; 1451 1452 switch (majorGravity) { 1453 case Gravity.BOTTOM: 1454 // mTotalLength contains the padding already 1455 childTop = mPaddingTop + mBottom - mTop - mTotalLength; 1456 break; 1457 1458 // mTotalLength contains the padding already 1459 case Gravity.CENTER_VERTICAL: 1460 childTop = mPaddingTop + (mBottom - mTop - mTotalLength) / 2; 1461 break; 1462 1463 case Gravity.TOP: 1464 default: 1465 childTop = mPaddingTop; 1466 break; 1467 } ... layout(...)
  19. FloatingLayout Layout Logic [A BBB CC ] [ ] [

    ] [ ] (width fixed) EEEE FFFFFF D
  20. FloatingLayout Layout Logic [A BBB CC ] [ ] [

    ] [ ] (width fixed) EEEE FFFFFF GG D
  21. FloatingLayout onMeasure (xM||xS, yM||yS) Measure children with... width AT_MOST(xS -

    paddings) (floor++ when space is not enough) height AT_MOST(yS - heightUsed - paddings)
  22. FloatingLayout setMeasuredDimension() Height if yM == AT_MOST usedY if yM

    == EXACTLY yS Width xM == AT_MOST Max(child.measuredWidth) xM == EXACTLY setMeasuredDimension(xS)
  23. FloatingLayoutV2 Upgrade Support gravity horizontal LEFT / CENTER_HORIZONTAL / RIGHT

    / FILL_HORIZONTAL(justified) vertical TOP / CENTER_VERTICAL / BOTTOM / FILL_VERTICAL
  24. case: center FloatingLayoutV2 A B C floorContentWidthSum left left =

    paddingLeft + (measuredWidth - paddingLeft - paddingRight - floorContentWidthSum) / 2
  25. case: fill_horizontal FloatingLayoutV2 A B C emptySplit emptySplit = (measuredWidth

    - paddingLeft - paddingRight - floorContentWidthSum) / ((children count on current floor) - 1) emptySplit
  26. finally Several use cases @ Kakao Ӕࢿ confined use case

    ! not that hard! (no gravity support?)