am 4a4fd6b1: am f564ee15: am 72524118: Merge "Snackbar fixes" into lmp-mr1-ub-dev

* commit '4a4fd6b12a21d9efe6f60ef79efb148ae18c7972':
  Snackbar fixes

GitOrigin-RevId=6df3c7360396f7a41484eb7f41891ff7683da721

PiperOrigin-RevId: 140548341
This commit is contained in:
Chris Banes 2016-11-30 01:15:18 +00:00 committed by Travis Collins
parent 214eb4cd26
commit 92a00eaad0
3 changed files with 90 additions and 21 deletions

View File

@ -182,8 +182,8 @@ package android.support.design.widget {
method public void dismiss();
method public int getDuration();
method public android.view.View getView();
method public static android.support.design.widget.Snackbar make(android.view.ViewGroup, java.lang.CharSequence, int);
method public static android.support.design.widget.Snackbar make(android.view.ViewGroup, int, int);
method public static android.support.design.widget.Snackbar make(android.view.View, java.lang.CharSequence, int);
method public static android.support.design.widget.Snackbar make(android.view.View, int, int);
method public android.support.design.widget.Snackbar setAction(int, android.view.View.OnClickListener);
method public android.support.design.widget.Snackbar setAction(java.lang.CharSequence, android.view.View.OnClickListener);
method public android.support.design.widget.Snackbar setDuration(int);

View File

@ -23,6 +23,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.design.R;
import android.support.v4.view.ViewCompat;
@ -33,8 +34,10 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -116,15 +119,24 @@ public class Snackbar {
}
/**
* Make a Snackbar to display a message.
* Make a Snackbar to display a message
*
* @param parent The parent to add Snackbars to.
* <p>Snackbar will try and find a parent view to hold Snackbar's view from the value given
* to {@code view}. Snackbar will walk up the view tree trying to find a suitable parent,
* which is defined as a {@link CoordinatorLayout} or the window decor's content view,
* whichever comes first.
*
* <p>Having a {@link CoordinatorLayout} in your view hierarchy allows Snackbar to enable
* certain features, such as swipe-to-dismiss and automatically moving of widgets like
* {@link FloatingActionButton}.
*
* @param view The view to find a parent from.
* @param text The text to show. Can be formatted text.
* @param duration How long to display the message. Either {@link #LENGTH_SHORT} or {@link
* #LENGTH_LONG}
*/
public static Snackbar make(ViewGroup parent, CharSequence text, @Duration int duration) {
Snackbar snackbar = new Snackbar(parent);
public static Snackbar make(View view, CharSequence text, @Duration int duration) {
Snackbar snackbar = new Snackbar(findSuitableParent(view));
snackbar.setText(text);
snackbar.setDuration(duration);
return snackbar;
@ -133,13 +145,51 @@ public class Snackbar {
/**
* Make a Snackbar to display a message.
*
* @param parent The parent to add Snackbars to.
* @param resId The resource id of the string resource to use. Can be formatted text.
* <p>Snackbar will try and find a parent view to hold Snackbar's view from the value given
* to {@code view}. Snackbar will walk up the view tree trying to find a suitable parent,
* which is defined as a {@link CoordinatorLayout} or the window decor's content view,
* whichever comes first.
*
* <p>Having a {@link CoordinatorLayout} in your view hierarchy allows Snackbar to enable
* certain features, such as swipe-to-dismiss and automatically moving of widgets like
* {@link FloatingActionButton}.
*
* @param view The view to find a parent from.
* @param resId The resource id of the string resource to use. Can be formatted text.
* @param duration How long to display the message. Either {@link #LENGTH_SHORT} or {@link
* #LENGTH_LONG}
*/
public static Snackbar make(ViewGroup parent, int resId, @Duration int duration) {
return make(parent, parent.getResources().getText(resId), duration);
public static Snackbar make(View view, int resId, @Duration int duration) {
return make(view, view.getResources().getText(resId), duration);
}
@Nullable
private static ViewGroup findSuitableParent(View view) {
ViewGroup fallback = null;
do {
if (view instanceof CoordinatorLayout) {
// We've found a CoordinatorLayout, use it
return (ViewGroup) view;
} else if (view instanceof FrameLayout) {
if (view.getId() == android.R.id.content) {
// If we've hit the decor content view, then we didn't find a CoL in the
// hierarchy, so use it.
return (ViewGroup) view;
} else {
// It's not the content view but we'll use it as our fallback
fallback = (ViewGroup) view;
}
}
if (view != null) {
// Else, we will loop and crawl up the view hierarchy and try to find a parent
final ViewParent parent = view.getParent();
view = parent instanceof View ? (View) parent : null;
}
} while (view != null);
// If we reach here then we didn't find a CoL or a suitable content view so we'll fallback
return fallback;
}
/**

View File

@ -20,6 +20,8 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.lang.ref.WeakReference;
/**
* Manages {@link Snackbar}s.
*/
@ -84,11 +86,12 @@ class SnackbarManager {
mNextSnackbar = new SnackbarRecord(duration, callback);
}
if (mCurrentSnackbar != null) {
// If the new Snackbar isn't in position 0, we'll cancel the current one and wait
// in line
cancelSnackbarLocked(mCurrentSnackbar);
if (mCurrentSnackbar != null && cancelSnackbarLocked(mCurrentSnackbar)) {
// If we currently have a Snackbar, try and cancel it and wait in line
return;
} else {
// Clear out the current snackbar
mCurrentSnackbar = null;
// Otherwise, just show it now
showNextSnackbarLocked();
}
@ -151,33 +154,49 @@ class SnackbarManager {
}
private static class SnackbarRecord {
private Callback callback;
private final WeakReference<Callback> callback;
private int duration;
SnackbarRecord(int duration, Callback callback) {
this.callback = callback;
this.callback = new WeakReference<>(callback);
this.duration = duration;
}
boolean isSnackbar(Callback callback) {
return callback != null && this.callback.get() == callback;
}
}
private void showNextSnackbarLocked() {
if (mNextSnackbar != null) {
mCurrentSnackbar = mNextSnackbar;
mCurrentSnackbar.callback.show();
mNextSnackbar = null;
final Callback callback = mCurrentSnackbar.callback.get();
if (callback != null) {
callback.show();
} else {
// The callback doesn't exist any more, clear out the Snackbar
mCurrentSnackbar = null;
}
}
}
private void cancelSnackbarLocked(SnackbarRecord record) {
record.callback.dismiss();
private boolean cancelSnackbarLocked(SnackbarRecord record) {
final Callback callback = record.callback.get();
if (callback != null) {
callback.dismiss();
return true;
}
return false;
}
private boolean isCurrentSnackbar(Callback callback) {
return mCurrentSnackbar != null && mCurrentSnackbar.callback == callback;
return mCurrentSnackbar != null && mCurrentSnackbar.isSnackbar(callback);
}
private boolean isNextSnackbar(Callback callback) {
return mNextSnackbar != null && mNextSnackbar.callback == callback;
return mNextSnackbar != null && mNextSnackbar.isSnackbar(callback);
}
private void scheduleTimeoutLocked(SnackbarRecord r) {