Skip to content

[AppBarLayout] Introduce expand api #1986

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 89 additions & 21 deletions lib/java/com/google/android/material/appbar/AppBarLayout.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,8 @@ public class AppBarLayout extends LinearLayout implements CoordinatorLayout.Atta

static final int PENDING_ACTION_NONE = 0x0;
static final int PENDING_ACTION_EXPANDED = 0x1;
static final int PENDING_ACTION_COLLAPSED = 1 << 1;
static final int PENDING_ACTION_ANIMATE_ENABLED = 1 << 2;
static final int PENDING_ACTION_FORCE = 1 << 3;
static final int PENDING_ACTION_ANIMATE_ENABLED = 1 << 1;
static final int PENDING_ACTION_FORCE = 1 << 2;

/**
* Interface definition for a callback to be invoked when an {@link AppBarLayout}'s vertical
Expand Down Expand Up @@ -174,6 +173,23 @@ public interface OnOffsetChangedListener extends BaseOnOffsetChangedListener<App

private int pendingAction = PENDING_ACTION_NONE;

/**
* Hide all the children whose scroll behavior is 'scroll'.
*/
public static final int EXPAND_NONE = 0;

/**
* Show the children like entering scroll.
*/
public static final int EXPAND_ENTERED = -1;

/**
* Show all the children.
*/
public static final int EXPAND_ALL = -2;

private int pendingExpandedHeight = EXPAND_NONE;

@Nullable private WindowInsetsCompat lastInsets;

private List<BaseOnOffsetChangedListener> listeners;
Expand Down Expand Up @@ -542,6 +558,40 @@ public void setElevation(float elevation) {
MaterialShapeUtils.setElevation(this, elevation);
}

/**
* Expand this {@link AppBarLayout} to the given height, animating if it has already been
* laid out.
*
* <p>As with {@link AppBarLayout}'s scrolling, this method relies on this layout being a direct
* child of a {@link CoordinatorLayout}.
*
* @param height the height, either an exact value, {@link #EXPAND_NONE}, {@link #EXPAND_ENTERED}, {@link #EXPAND_ALL}
*/
public void expand(int height) {
expand(height, ViewCompat.isLaidOut(this));
}

/**
* Expand this {@link AppBarLayout} to the given height.
*
* <p>As with {@link AppBarLayout}'s scrolling, this method relies on this layout being a direct
* child of a {@link CoordinatorLayout}.
*
* @param height the height, either an exact value, {@link #EXPAND_NONE}, {@link #EXPAND_ENTERED}, {@link #EXPAND_ALL}
* @param animate Whether to animate to the new state
*/
public void expand(int height, boolean animate) {
expand(height, animate, false);
}

private void expand(int height, boolean animate, boolean force) {
pendingAction = PENDING_ACTION_EXPANDED
| (animate ? PENDING_ACTION_ANIMATE_ENABLED : 0)
| (force ? PENDING_ACTION_FORCE : 0);
pendingExpandedHeight = height;
requestLayout();
}

/**
* Sets whether this {@link AppBarLayout} is expanded or not, animating if it has already been
* laid out.
Expand Down Expand Up @@ -573,11 +623,8 @@ public void setExpanded(boolean expanded, boolean animate) {
}

private void setExpanded(boolean expanded, boolean animate, boolean force) {
pendingAction =
(expanded ? PENDING_ACTION_EXPANDED : PENDING_ACTION_COLLAPSED)
| (animate ? PENDING_ACTION_ANIMATE_ENABLED : 0)
| (force ? PENDING_ACTION_FORCE : 0);
requestLayout();
final int height = expanded ? EXPAND_ALL : EXPAND_NONE;
expand(height, animate, force);
}

@Override
Expand Down Expand Up @@ -982,6 +1029,10 @@ void resetPendingAction() {
pendingAction = PENDING_ACTION_NONE;
}

int getPendingExpandedHeight() {
return pendingExpandedHeight;
}

@VisibleForTesting
final int getTopInset() {
return lastInsets != null ? lastInsets.getSystemWindowInsetTop() : 0;
Expand Down Expand Up @@ -1546,19 +1597,8 @@ public boolean onLayoutChild(
setHeaderTopBottomOffset(parent, abl, offset);
} else if (pendingAction != PENDING_ACTION_NONE) {
final boolean animate = (pendingAction & PENDING_ACTION_ANIMATE_ENABLED) != 0;
if ((pendingAction & PENDING_ACTION_COLLAPSED) != 0) {
final int offset = -abl.getUpNestedPreScrollRange();
if (animate) {
animateOffsetTo(parent, abl, offset, 0);
} else {
setHeaderTopBottomOffset(parent, abl, offset);
}
} else if ((pendingAction & PENDING_ACTION_EXPANDED) != 0) {
if (animate) {
animateOffsetTo(parent, abl, 0, 0);
} else {
setHeaderTopBottomOffset(parent, abl, 0);
}
if ((pendingAction & PENDING_ACTION_EXPANDED) != 0) {
processExpand(parent, abl, animate);
}
}

Expand All @@ -1584,6 +1624,34 @@ public boolean onLayoutChild(
return handled;
}

private void processExpand(CoordinatorLayout parent, T abl, boolean animate) {
final int height = abl.getPendingExpandedHeight();
int offset = 0;
if (height > 0) {
offset = Math.min(0, -abl.getUpNestedPreScrollRange() + height);
} else {
switch(height) {
case EXPAND_NONE:
offset = -abl.getUpNestedPreScrollRange();
break;
case EXPAND_ENTERED:
offset = -abl.getUpNestedPreScrollRange() + abl.getDownNestedPreScrollRange();
break;
case EXPAND_ALL:
offset = 0;
break;
default:
// invalid height
break;
}
}
if (animate) {
animateOffsetTo(parent, abl, offset, 0);
} else {
setHeaderTopBottomOffset(parent, abl, offset);
}
}

private void updateAccessibilityActions(
CoordinatorLayout coordinatorLayout, @NonNull T appBarLayout) {
ViewCompat.removeAccessibilityAction(coordinatorLayout, ACTION_SCROLL_FORWARD.getId());
Expand Down