Skip to content

Commit acb7958

Browse files
drchenjosefigueroa168
authored andcommitted
[TopAppBar] Fix top app bar snapping issue
Unlike other child views of AppBarLayout, CollapsingToolbarLayout will shift its top boundary to consume the window insets as well. Therefore we need to shift the top boundary back when calculating snapping positions to have a consistent logic with other views. This CL also simplifies the calculation so the origin of the y-coordinate used in the calculation will always be the top of the AppBarLayout. PiperOrigin-RevId: 413750156
1 parent b8f2dd5 commit acb7958

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

lib/java/com/google/android/material/appbar/AppBarLayout.java

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,11 +1526,10 @@ public void onAnimationUpdate(@NonNull ValueAnimator animator) {
15261526
}
15271527

15281528
private int getChildIndexOnOffset(@NonNull T abl, final int offset) {
1529-
final int ablTopInset = abl.getTopInset() + abl.getPaddingTop();
15301529
for (int i = 0, count = abl.getChildCount(); i < count; i++) {
15311530
View child = abl.getChildAt(i);
1532-
int top = child.getTop() - ablTopInset;
1533-
int bottom = child.getBottom() - ablTopInset;
1531+
int top = child.getTop();
1532+
int bottom = child.getBottom();
15341533

15351534
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
15361535
if (checkFlag(lp.getScrollFlags(), LayoutParams.SCROLL_FLAG_SNAP_MARGINS)) {
@@ -1547,18 +1546,29 @@ private int getChildIndexOnOffset(@NonNull T abl, final int offset) {
15471546
}
15481547

15491548
private void snapToChildIfNeeded(CoordinatorLayout coordinatorLayout, @NonNull T abl) {
1550-
final int offset = getTopBottomOffsetForScrollingSibling();
1549+
final int topInset = abl.getTopInset() + abl.getPaddingTop();
1550+
// The "baseline" of scrolling is the top of the first child. We "add" insets and paddings
1551+
// to the scrolling amount to align offsets and views with the same y-coordinate. (The origin
1552+
// is at the top of the AppBarLayout, so all the coordinates are with negative values.)
1553+
final int offset = getTopBottomOffsetForScrollingSibling() - topInset;
15511554
final int offsetChildIndex = getChildIndexOnOffset(abl, offset);
15521555
if (offsetChildIndex >= 0) {
15531556
final View offsetChild = abl.getChildAt(offsetChildIndex);
15541557
final LayoutParams lp = (LayoutParams) offsetChild.getLayoutParams();
15551558
final int flags = lp.getScrollFlags();
1556-
final int ablTopInset = abl.getTopInset() + abl.getPaddingTop();
15571559

15581560
if ((flags & LayoutParams.FLAG_SNAP) == LayoutParams.FLAG_SNAP) {
15591561
// We're set the snap, so animate the offset to the nearest edge
1560-
int snapTop = -offsetChild.getTop() + ablTopInset;
1561-
int snapBottom = -offsetChild.getBottom() + ablTopInset;
1562+
int snapTop = -offsetChild.getTop();
1563+
int snapBottom = -offsetChild.getBottom();
1564+
1565+
// If the child is set to fit system windows, its top will include the inset area, we need
1566+
// to minus the inset from snapTop to make the calculation consistent.
1567+
if (offsetChildIndex == 0
1568+
&& ViewCompat.getFitsSystemWindows(abl)
1569+
&& ViewCompat.getFitsSystemWindows(offsetChild)) {
1570+
snapTop -= abl.getTopInset();
1571+
}
15621572

15631573
if (checkFlag(flags, LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED)) {
15641574
// If the view is set only exit until it is collapsed, we'll abide by that
@@ -1581,13 +1591,19 @@ private void snapToChildIfNeeded(CoordinatorLayout coordinatorLayout, @NonNull T
15811591
snapBottom -= lp.bottomMargin;
15821592
}
15831593

1584-
final int newOffset = offset < (snapBottom + snapTop) / 2 ? snapBottom : snapTop;
1594+
// Excludes insets and paddings from the offset. (Offsets use the top of child views as
1595+
// the origin.)
1596+
final int newOffset = calculateSnapOffset(offset, snapBottom, snapTop) + topInset;
15851597
animateOffsetTo(
15861598
coordinatorLayout, abl, clamp(newOffset, -abl.getTotalScrollRange(), 0), 0);
15871599
}
15881600
}
15891601
}
15901602

1603+
private int calculateSnapOffset(int value, int bottom, int top) {
1604+
return value < (bottom + top) / 2 ? bottom : top;
1605+
}
1606+
15911607
private static boolean checkFlag(final int flags, final int check) {
15921608
return (flags & check) == check;
15931609
}

0 commit comments

Comments
 (0)