[Shape] Restore alpha06 corner animation behavior #4995
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Fix corner morph animation regression in MaterialButtonGroup introduced after commit ea9d250.
Problem
After ea9d250, corner morph animations in MaterialButtonGroup are interrupted during state changes (pressed, focused, etc.).
Root cause:
In
MaterialShapeDrawable.onBoundsChange(), animations are now always skipped:This causes
springAnimatedCornerSizesto be immediately set to target values, interrupting any ongoing animations.Reproduction:
Why MaterialButtonGroup Cannot Fix This
I initially attempted to fix this in MaterialButtonGroup by:
setShapeAppearance()callsHowever, all approaches failed because:
The critical issue:
onBoundsChange()is called by the Android framework after state changesskipAnimation=truehardcoded, there's no way for MaterialButtonGroup to preserve animationsonBoundsChange()Why bounds change during state changes:
onBoundsChange()is still calledSolution
The fix must be in MaterialShapeDrawable to distinguish between:
Restore the
boundsIsEmptyflag approach from alpha06:Why this works:
boundsIsEmpty=true→ Skip (fast initialization)boundsIsEmpty=false→ Animate (smooth UX)Alternative Approaches Considered
❌ Option 1: Fix in MaterialButtonGroup
Tried: Cache shapes, prevent redundant updates
Failed:
onBoundsChange()always overrides withskipAnimation=true❌ Option 2: Track actual bounds changes
Tried: Compare
previousBoundsto detect real size changesFailed: Bounds may change slightly during state transitions (ripple, elevation)
✅ Option 3: Restore boundsIsEmpty logic (this PR)
Works: Distinguishes initial layout from subsequent calls at the source
Implementation
boundsIsEmptyflag to track initial layoutonBoundsChange()to skip animation only on first non-empty boundsTesting
Changes
Modified:
lib/java/com/google/android/material/shape/MaterialShapeDrawable.javaboundsIsEmptyflagonBoundsChange()animation skip logicFixes #4990
Discussion
@pekingme I understand the intent of ea9d250 was to improve performance by skipping animations during bounds changes. However, this also affects state-only changes where animation should be preserved.
Would you be open to this refinement that maintains the performance benefit for initial layout while allowing animations for state transitions?