Custom Views
The Android custom-view lifecycle — onMeasure, onLayout, onDraw, and MeasureSpec.
3 questions
JuniorDesignOccasionalKeep a custom View at a fixed 4:3 aspect ratio for any parent width
Keep a custom View at a fixed 4:3 aspect ratio for any parent width
Override onMeasure: take the parent width from the width MeasureSpec, set the height to width * 3 / 4, then call setMeasuredDimension. The no-code alternative is ConstraintLayout with app:layout_constraintDimensionRatio="4:3".
Common mistakes
- ✗Hard-coding a pixel height instead of deriving it from the measured width
- ✗Calling
setMeasuredDimensionwith the rawMeasureSpecvalues without computing the ratio - ✗Trying to enforce the ratio in
onDraworonLayoutrather thanonMeasure
Follow-up questions
- →How do you read the size and mode out of a width
MeasureSpec? - →What changes if the parent passes an
EXACTLYheight instead ofAT_MOST?
SeniorDesignOccasionalDesign a tag-list View that wraps a priority-ordered list of text tags into at most TWO lines. Rules: tags are laid out in priority order (highest first); the layout fills at most two lines; if a tag does not fit on the current line, you skip it and try the NEXT tag that does fit; and if a tag would only fit on the next line but a later tag could still fit on the CURRENT line, you place that later tag on the current line first (lower-priority tags bubble up to fill gaps). Example input order: ["How", "About", "This", "And", "Even something quite like this", "Eh?"]. Describe how you implement this as a custom ViewGroup — what you do in onMeasure and onLayout, how you pack tags greedily across the two rows with the bubble-up rule, and how you decide a tag's width (a coarse text-length comparison is acceptable). You may ignore the bubble-up refinement in a first cut.
Design a tag-list View that wraps a priority-ordered list of text tags into at most TWO lines. Rules: tags are laid out in priority order (highest first); the layout fills at most two lines; if a tag does not fit on the current line, you skip it and try the NEXT tag that does fit; and if a tag would only fit on the next line but a later tag could still fit on the CURRENT line, you place that later tag on the current line first (lower-priority tags bubble up to fill gaps). Example input order: ["How", "About", "This", "And", "Even something quite like this", "Eh?"]. Describe how you implement this as a custom ViewGroup — what you do in onMeasure and onLayout, how you pack tags greedily across the two rows with the bubble-up rule, and how you decide a tag's width (a coarse text-length comparison is acceptable). You may ignore the bubble-up refinement in a first cut.
Custom ViewGroup: in onMeasure, measure each child, then greedily pack tags by priority into two rows — take a tag if it fits the current row, else try later tags that still fit before moving on, stopping after two rows. Report size via setMeasuredDimension; in onLayout place each packed child at its row/x.
Common mistakes
- ✗Reaching for a stock layout manager that cannot enforce the two-line cap plus the bubble-up rule
- ✗Stopping at the first non-fitting tag instead of trying later tags that still fit the row
- ✗Doing the packing in
onDrawrather thanonMeasure/onLayout
Follow-up questions
- →How do you keep the greedy two-row packing within
onMeasure's expected single pass? - →How would a non-monospaced font change your coarse text-length width estimate?
MiddleDesignRareTwo single-line text fields side by side — shrink the first when both don't fit
Two single-line text fields side by side — shrink the first when both don't fit
Lay out two single-line fields left-to-right; when both don't fit, shrink the FIRST. Use a ConstraintLayout chain with layout_constrainedWidth and ellipsize=end, favouring the second's width. Or a custom onMeasure that measures the second field first, then gives the leftover width to the first.
Common mistakes
- ✗Splitting width with equal weights, which truncates both fields instead of only the first
- ✗Measuring the first field before the second, so the first claims the space the second needs
- ✗Forgetting
ellipsize, so the overflowing field is clipped without an ellipsis
Follow-up questions
- →In a custom
onMeasure, how do you reserve the second field's width before measuring the first? - →What
ellipsizeandmaxLinessettings keep each field on a single line?