Snackbar.java revision de0cc188c28f8c19ef5e737e9cd22492b07250c8
1b7f9224b1495db47eb8fd813b5912250e900770aChris Banes/* 2b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Copyright (C) 2015 The Android Open Source Project 3b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 4b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 5b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * you may not use this file except in compliance with the License. 6b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * You may obtain a copy of the License at 7b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 8b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * http://www.apache.org/licenses/LICENSE-2.0 9b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 10b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Unless required by applicable law or agreed to in writing, software 11b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * distributed under the License is distributed on an "AS IS" BASIS, 12b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * See the License for the specific language governing permissions and 14b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * limitations under the License. 15b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 16b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 17b7f9224b1495db47eb8fd813b5912250e900770aChris Banespackage android.support.design.widget; 18b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 19b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.content.Context; 204112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banesimport android.content.res.ColorStateList; 21b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.content.res.TypedArray; 22b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.os.Build; 23b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.os.Handler; 24b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.os.Looper; 25b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.os.Message; 265bb1f5d910c81ed2a31c687583bd90baccc972acChris Banesimport android.support.annotation.ColorInt; 27b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.support.annotation.IntDef; 28de0cc188c28f8c19ef5e737e9cd22492b07250c8Tor Norbyeimport android.support.annotation.IntRange; 295bb1f5d910c81ed2a31c687583bd90baccc972acChris Banesimport android.support.annotation.NonNull; 30b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.support.annotation.StringRes; 31b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.support.design.R; 32b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.support.v4.view.ViewCompat; 33b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.support.v4.view.ViewPropertyAnimatorListenerAdapter; 34b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.text.TextUtils; 35b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.util.AttributeSet; 36b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.view.LayoutInflater; 37b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.view.MotionEvent; 38b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.view.View; 39b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.view.ViewGroup; 40c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banesimport android.view.ViewParent; 41b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.view.animation.Animation; 42b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.view.animation.AnimationUtils; 435cf1a7e04097b7e116c118cfa823a4cdb48f38a1Chris Banesimport android.widget.Button; 44c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banesimport android.widget.FrameLayout; 45b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.widget.LinearLayout; 46b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport android.widget.TextView; 47b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 48b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport java.lang.annotation.Retention; 49b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport java.lang.annotation.RetentionPolicy; 50b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 51b7f9224b1495db47eb8fd813b5912250e900770aChris Banesimport static android.support.design.widget.AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR; 52b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 53b7f9224b1495db47eb8fd813b5912250e900770aChris Banes/** 54b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Snackbars provide lightweight feedback about an operation. They show a brief message at the 55b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * bottom of the screen on mobile and lower left on larger devices. Snackbars appear above all other 56b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * elements on screen and only one can be displayed at a time. 57b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * <p> 58b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * They automatically disappear after a timeout or after user interaction elsewhere on the screen, 59b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * particularly after interactions that summon a new surface or activity. Snackbars can be swiped 60b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * off screen. 61b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * <p> 62b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Snackbars can contain an action which is set via 63b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * {@link #setAction(CharSequence, android.view.View.OnClickListener)}. 64bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * <p> 65bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * To be notified when a snackbar has been shown or dismissed, you can provide a {@link Callback} 66bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * via {@link #setCallback(Callback)}.</p> 67b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 68b7f9224b1495db47eb8fd813b5912250e900770aChris Banespublic class Snackbar { 69b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 70b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 71bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * Callback class for {@link Snackbar} instances. 72bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * 73bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * @see Snackbar#setCallback(Callback) 74bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes */ 75bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes public static abstract class Callback { 76bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes /** 77bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * Called when the given {@link Snackbar} has been dismissed, either through a time-out, 78bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * having been manually dismissed, or an action being clicked. 79bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * 80bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * @param snackbar The snackbar which has been dismissed. 81bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * @see Snackbar#dismiss() 82bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes */ 83bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes public void onDismissed(Snackbar snackbar) { 84bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes // empty 85bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes } 86bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes 87bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes /** 88bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * Called when the given {@link Snackbar} is visible. 89bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * 90bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * @param snackbar The snackbar which is now visible. 91bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * @see Snackbar#show() 92bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes */ 93bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes public void onShown(Snackbar snackbar) { 94bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes // empty 95bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes } 96bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes } 97bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes 98bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes /** 99b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @hide 100b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 1010bfb0e034ed6b4f7bbf58a111d2fc893e0553350Chris Banes @IntDef({LENGTH_INDEFINITE, LENGTH_SHORT, LENGTH_LONG}) 102de0cc188c28f8c19ef5e737e9cd22492b07250c8Tor Norbye @IntRange(from = 1) 103b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Retention(RetentionPolicy.SOURCE) 104b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public @interface Duration {} 105b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 106b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 1070bfb0e034ed6b4f7bbf58a111d2fc893e0553350Chris Banes * Show the Snackbar indefinitely. This means that the Snackbar will be displayed from the time 1080bfb0e034ed6b4f7bbf58a111d2fc893e0553350Chris Banes * that is {@link #show() shown} until either it is dismissed, or another Snackbar is shown. 1090bfb0e034ed6b4f7bbf58a111d2fc893e0553350Chris Banes * 1100bfb0e034ed6b4f7bbf58a111d2fc893e0553350Chris Banes * @see #setDuration 1110bfb0e034ed6b4f7bbf58a111d2fc893e0553350Chris Banes */ 1120bfb0e034ed6b4f7bbf58a111d2fc893e0553350Chris Banes public static final int LENGTH_INDEFINITE = -2; 1130bfb0e034ed6b4f7bbf58a111d2fc893e0553350Chris Banes 1140bfb0e034ed6b4f7bbf58a111d2fc893e0553350Chris Banes /** 115b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Show the Snackbar for a short period of time. 116b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 117b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @see #setDuration 118b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 119b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public static final int LENGTH_SHORT = -1; 120b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 121b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 122b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Show the Snackbar for a long period of time. 123b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 124b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @see #setDuration 125b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 126b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public static final int LENGTH_LONG = 0; 127b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 128b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private static final int ANIMATION_DURATION = 250; 129b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private static final int ANIMATION_FADE_DURATION = 180; 130b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 131b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private static final Handler sHandler; 132b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private static final int MSG_SHOW = 0; 133b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private static final int MSG_DISMISS = 1; 134b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 135b7f9224b1495db47eb8fd813b5912250e900770aChris Banes static { 136b7f9224b1495db47eb8fd813b5912250e900770aChris Banes sHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() { 137b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 138b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public boolean handleMessage(Message message) { 139b7f9224b1495db47eb8fd813b5912250e900770aChris Banes switch (message.what) { 140b7f9224b1495db47eb8fd813b5912250e900770aChris Banes case MSG_SHOW: 141b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ((Snackbar) message.obj).showView(); 142b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return true; 143b7f9224b1495db47eb8fd813b5912250e900770aChris Banes case MSG_DISMISS: 144b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ((Snackbar) message.obj).hideView(); 145b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return true; 146b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 147b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return false; 148b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 149b7f9224b1495db47eb8fd813b5912250e900770aChris Banes }); 150b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 151b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 152b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private final ViewGroup mParent; 153b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private final Context mContext; 154b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private final SnackbarLayout mView; 155b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private int mDuration; 156bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes private Callback mCallback; 157b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 158b7f9224b1495db47eb8fd813b5912250e900770aChris Banes Snackbar(ViewGroup parent) { 159b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mParent = parent; 160b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mContext = parent.getContext(); 161b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 162b7f9224b1495db47eb8fd813b5912250e900770aChris Banes LayoutInflater inflater = LayoutInflater.from(mContext); 163a577676a64e5353b8ec927117151aa6be84adf66Chris Banes mView = (SnackbarLayout) inflater.inflate(R.layout.design_layout_snackbar, mParent, false); 164b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 165b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 166b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 167c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * Make a Snackbar to display a message 168c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * 169c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * <p>Snackbar will try and find a parent view to hold Snackbar's view from the value given 170c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * to {@code view}. Snackbar will walk up the view tree trying to find a suitable parent, 171c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * which is defined as a {@link CoordinatorLayout} or the window decor's content view, 172c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * whichever comes first. 173c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * 174c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * <p>Having a {@link CoordinatorLayout} in your view hierarchy allows Snackbar to enable 175c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * certain features, such as swipe-to-dismiss and automatically moving of widgets like 176c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * {@link FloatingActionButton}. 177b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 178c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * @param view The view to find a parent from. 179b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param text The text to show. Can be formatted text. 180b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param duration How long to display the message. Either {@link #LENGTH_SHORT} or {@link 181b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * #LENGTH_LONG} 182b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 1835bb1f5d910c81ed2a31c687583bd90baccc972acChris Banes public static Snackbar make(@NonNull View view, @NonNull CharSequence text, 1845bb1f5d910c81ed2a31c687583bd90baccc972acChris Banes @Duration int duration) { 185c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes Snackbar snackbar = new Snackbar(findSuitableParent(view)); 186b7f9224b1495db47eb8fd813b5912250e900770aChris Banes snackbar.setText(text); 187b7f9224b1495db47eb8fd813b5912250e900770aChris Banes snackbar.setDuration(duration); 188b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return snackbar; 189b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 190b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 191b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 192b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Make a Snackbar to display a message. 193b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 194c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * <p>Snackbar will try and find a parent view to hold Snackbar's view from the value given 195c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * to {@code view}. Snackbar will walk up the view tree trying to find a suitable parent, 196c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * which is defined as a {@link CoordinatorLayout} or the window decor's content view, 197c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * whichever comes first. 198c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * 199c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * <p>Having a {@link CoordinatorLayout} in your view hierarchy allows Snackbar to enable 200c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * certain features, such as swipe-to-dismiss and automatically moving of widgets like 201c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * {@link FloatingActionButton}. 202c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * 203c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * @param view The view to find a parent from. 204c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes * @param resId The resource id of the string resource to use. Can be formatted text. 205b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param duration How long to display the message. Either {@link #LENGTH_SHORT} or {@link 206b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * #LENGTH_LONG} 207b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 2085bb1f5d910c81ed2a31c687583bd90baccc972acChris Banes public static Snackbar make(@NonNull View view, @StringRes int resId, @Duration int duration) { 209c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes return make(view, view.getResources().getText(resId), duration); 210c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes } 211c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes 212c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes private static ViewGroup findSuitableParent(View view) { 213c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes ViewGroup fallback = null; 214c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes do { 215c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes if (view instanceof CoordinatorLayout) { 216c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes // We've found a CoordinatorLayout, use it 217c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes return (ViewGroup) view; 218c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes } else if (view instanceof FrameLayout) { 219c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes if (view.getId() == android.R.id.content) { 220c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes // If we've hit the decor content view, then we didn't find a CoL in the 221c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes // hierarchy, so use it. 222c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes return (ViewGroup) view; 223c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes } else { 224c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes // It's not the content view but we'll use it as our fallback 225c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes fallback = (ViewGroup) view; 226c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes } 227c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes } 228c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes 229c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes if (view != null) { 230c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes // Else, we will loop and crawl up the view hierarchy and try to find a parent 231c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes final ViewParent parent = view.getParent(); 232c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes view = parent instanceof View ? (View) parent : null; 233c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes } 234c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes } while (view != null); 235c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes 236c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes // If we reach here then we didn't find a CoL or a suitable content view so we'll fallback 237c482f89070ee5032081e394f77a9a1e63c3cd7a8Chris Banes return fallback; 238b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 239b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 240b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 241b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Set the action to be displayed in this {@link Snackbar}. 242b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 243b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param resId String resource to display 244b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param listener callback to be invoked when the action is clicked 245b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 246b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public Snackbar setAction(@StringRes int resId, View.OnClickListener listener) { 247b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return setAction(mContext.getText(resId), listener); 248b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 249b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 250b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 251b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Set the action to be displayed in this {@link Snackbar}. 252b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 253b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param text Text to display 254b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param listener callback to be invoked when the action is clicked 255b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 256b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public Snackbar setAction(CharSequence text, final View.OnClickListener listener) { 257b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final TextView tv = mView.getActionView(); 258b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 259b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (TextUtils.isEmpty(text) || listener == null) { 260b7f9224b1495db47eb8fd813b5912250e900770aChris Banes tv.setVisibility(View.GONE); 261b7f9224b1495db47eb8fd813b5912250e900770aChris Banes tv.setOnClickListener(null); 262b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } else { 263b7f9224b1495db47eb8fd813b5912250e900770aChris Banes tv.setVisibility(View.VISIBLE); 264b7f9224b1495db47eb8fd813b5912250e900770aChris Banes tv.setText(text); 265b7f9224b1495db47eb8fd813b5912250e900770aChris Banes tv.setOnClickListener(new View.OnClickListener() { 266b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 267b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onClick(View view) { 268b7f9224b1495db47eb8fd813b5912250e900770aChris Banes listener.onClick(view); 269b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 270b7f9224b1495db47eb8fd813b5912250e900770aChris Banes // Now dismiss the Snackbar 271b7f9224b1495db47eb8fd813b5912250e900770aChris Banes dismiss(); 272b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 273b7f9224b1495db47eb8fd813b5912250e900770aChris Banes }); 274b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 275b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return this; 276b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 277b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 278b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 2794112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes * Sets the text color of the action specified in 2804112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes * {@link #setAction(CharSequence, View.OnClickListener)}. 2814112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes */ 2824112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes public Snackbar setActionTextColor(ColorStateList colors) { 2834112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes final TextView tv = mView.getActionView(); 2844112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes tv.setTextColor(colors); 2854112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes return this; 2864112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes } 2874112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes 2884112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes /** 2894112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes * Sets the text color of the action specified in 2904112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes * {@link #setAction(CharSequence, View.OnClickListener)}. 2914112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes */ 2925bb1f5d910c81ed2a31c687583bd90baccc972acChris Banes public Snackbar setActionTextColor(@ColorInt int color) { 2934112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes final TextView tv = mView.getActionView(); 2944112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes tv.setTextColor(color); 2954112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes return this; 2964112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes } 2974112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes 2984112c61626e5a6107c5874c28829b76bb9fc9f17Chris Banes /** 299b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Update the text in this {@link Snackbar}. 300b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 301b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param message The new text for the Toast. 302b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 3035bb1f5d910c81ed2a31c687583bd90baccc972acChris Banes public Snackbar setText(@NonNull CharSequence message) { 304b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final TextView tv = mView.getMessageView(); 305b7f9224b1495db47eb8fd813b5912250e900770aChris Banes tv.setText(message); 306b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return this; 307b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 308b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 309b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 310b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Update the text in this {@link Snackbar}. 311b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 312b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param resId The new text for the Toast. 313b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 314b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public Snackbar setText(@StringRes int resId) { 315b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return setText(mContext.getText(resId)); 316b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 317b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 318b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 319b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Set how long to show the view for. 320b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 321b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @param duration either be one of the predefined lengths: 322b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * {@link #LENGTH_SHORT}, {@link #LENGTH_LONG}, or a custom duration 323b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * in milliseconds. 324b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 325b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public Snackbar setDuration(@Duration int duration) { 326b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mDuration = duration; 327b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return this; 328b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 329b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 330b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 331b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Return the duration. 332b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * 333b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @see #setDuration 334b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 335b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Duration 336b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public int getDuration() { 337b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return mDuration; 338b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 339b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 340b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 341b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Returns the {@link Snackbar}'s view. 342b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 3435bb1f5d910c81ed2a31c687583bd90baccc972acChris Banes @NonNull 344b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public View getView() { 345b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return mView; 346b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 347b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 348b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 349b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Show the {@link Snackbar}. 350b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 351b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void show() { 352b7f9224b1495db47eb8fd813b5912250e900770aChris Banes SnackbarManager.getInstance().show(mDuration, mManagerCallback); 353b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 354b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 355b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 356b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * Dismiss the {@link Snackbar}. 357b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 358b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void dismiss() { 359b7f9224b1495db47eb8fd813b5912250e900770aChris Banes SnackbarManager.getInstance().dismiss(mManagerCallback); 360b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 361b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 362bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes /** 363bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes * Set a callback to be called when this the visibility of this {@link Snackbar} changes. 364bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes */ 365bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes public void setCallback(Callback callback) { 366bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes mCallback = callback; 367bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes } 368bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes 369b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private final SnackbarManager.Callback mManagerCallback = new SnackbarManager.Callback() { 370b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 371b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void show() { 372b7f9224b1495db47eb8fd813b5912250e900770aChris Banes sHandler.sendMessage(sHandler.obtainMessage(MSG_SHOW, Snackbar.this)); 373b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 374b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 375b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 376b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void dismiss() { 377b7f9224b1495db47eb8fd813b5912250e900770aChris Banes sHandler.sendMessage(sHandler.obtainMessage(MSG_DISMISS, Snackbar.this)); 378b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 379b7f9224b1495db47eb8fd813b5912250e900770aChris Banes }; 380b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 381b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final void showView() { 382b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (mView.getParent() == null) { 383b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final ViewGroup.LayoutParams lp = mView.getLayoutParams(); 384b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 385b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (lp instanceof CoordinatorLayout.LayoutParams) { 386b7f9224b1495db47eb8fd813b5912250e900770aChris Banes // If our LayoutParams are from a CoordinatorLayout, we'll setup our Behavior 387b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 388b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final Behavior behavior = new Behavior(); 389b7f9224b1495db47eb8fd813b5912250e900770aChris Banes behavior.setStartAlphaSwipeDistance(0.1f); 390b7f9224b1495db47eb8fd813b5912250e900770aChris Banes behavior.setEndAlphaSwipeDistance(0.6f); 391b7f9224b1495db47eb8fd813b5912250e900770aChris Banes behavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_START_TO_END); 392b7f9224b1495db47eb8fd813b5912250e900770aChris Banes behavior.setListener(new SwipeDismissBehavior.OnDismissListener() { 393b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 394b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onDismiss(View view) { 395b7f9224b1495db47eb8fd813b5912250e900770aChris Banes dismiss(); 396b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 397b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 398b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 399b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onDragStateChanged(int state) { 400b7f9224b1495db47eb8fd813b5912250e900770aChris Banes switch (state) { 401b7f9224b1495db47eb8fd813b5912250e900770aChris Banes case SwipeDismissBehavior.STATE_DRAGGING: 402b7f9224b1495db47eb8fd813b5912250e900770aChris Banes case SwipeDismissBehavior.STATE_SETTLING: 403b7f9224b1495db47eb8fd813b5912250e900770aChris Banes // If the view is being dragged or settling, cancel the timeout 404b7f9224b1495db47eb8fd813b5912250e900770aChris Banes SnackbarManager.getInstance().cancelTimeout(mManagerCallback); 405b7f9224b1495db47eb8fd813b5912250e900770aChris Banes break; 406b7f9224b1495db47eb8fd813b5912250e900770aChris Banes case SwipeDismissBehavior.STATE_IDLE: 407b7f9224b1495db47eb8fd813b5912250e900770aChris Banes // If the view has been released and is idle, restore the timeout 408b7f9224b1495db47eb8fd813b5912250e900770aChris Banes SnackbarManager.getInstance().restoreTimeout(mManagerCallback); 409b7f9224b1495db47eb8fd813b5912250e900770aChris Banes break; 410b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 411b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 412b7f9224b1495db47eb8fd813b5912250e900770aChris Banes }); 413b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ((CoordinatorLayout.LayoutParams) lp).setBehavior(behavior); 414b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 415b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 416b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mParent.addView(mView); 417b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 418b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 419b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (ViewCompat.isLaidOut(mView)) { 420b7f9224b1495db47eb8fd813b5912250e900770aChris Banes // If the view is already laid out, animate it now 421b7f9224b1495db47eb8fd813b5912250e900770aChris Banes animateViewIn(); 422b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } else { 423b7f9224b1495db47eb8fd813b5912250e900770aChris Banes // Otherwise, add one of our layout change listeners and animate it in when laid out 424b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mView.setOnLayoutChangeListener(new SnackbarLayout.OnLayoutChangeListener() { 425b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 426b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onLayoutChange(View view, int left, int top, int right, int bottom) { 427b7f9224b1495db47eb8fd813b5912250e900770aChris Banes animateViewIn(); 428b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mView.setOnLayoutChangeListener(null); 429b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 430b7f9224b1495db47eb8fd813b5912250e900770aChris Banes }); 431b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 432b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 433b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 434b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private void animateViewIn() { 435b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 436b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.setTranslationY(mView, mView.getHeight()); 437b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.animate(mView).translationY(0f) 438b7f9224b1495db47eb8fd813b5912250e900770aChris Banes .setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR) 439b7f9224b1495db47eb8fd813b5912250e900770aChris Banes .setDuration(ANIMATION_DURATION) 440b7f9224b1495db47eb8fd813b5912250e900770aChris Banes .setListener(new ViewPropertyAnimatorListenerAdapter() { 441b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 442b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onAnimationStart(View view) { 443b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mView.animateChildrenIn(ANIMATION_DURATION - ANIMATION_FADE_DURATION, 444b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ANIMATION_FADE_DURATION); 445b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 446b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 447b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 448b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onAnimationEnd(View view) { 449bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes if (mCallback != null) { 450bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes mCallback.onShown(Snackbar.this); 451bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes } 452b7f9224b1495db47eb8fd813b5912250e900770aChris Banes SnackbarManager.getInstance().onShown(mManagerCallback); 453b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 454b7f9224b1495db47eb8fd813b5912250e900770aChris Banes }).start(); 455b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } else { 456a577676a64e5353b8ec927117151aa6be84adf66Chris Banes Animation anim = AnimationUtils.loadAnimation(mView.getContext(), R.anim.design_snackbar_in); 457b7f9224b1495db47eb8fd813b5912250e900770aChris Banes anim.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); 458b7f9224b1495db47eb8fd813b5912250e900770aChris Banes anim.setDuration(ANIMATION_DURATION); 459b7f9224b1495db47eb8fd813b5912250e900770aChris Banes anim.setAnimationListener(new Animation.AnimationListener() { 460b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 461b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onAnimationEnd(Animation animation) { 462bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes if (mCallback != null) { 463bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes mCallback.onShown(Snackbar.this); 464bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes } 465b7f9224b1495db47eb8fd813b5912250e900770aChris Banes SnackbarManager.getInstance().onShown(mManagerCallback); 466b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 467b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 468b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 469b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onAnimationStart(Animation animation) {} 470b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 471b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 472b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onAnimationRepeat(Animation animation) {} 473b7f9224b1495db47eb8fd813b5912250e900770aChris Banes }); 474b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mView.startAnimation(anim); 475b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 476b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 477b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 478b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private void animateViewOut() { 479b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 480b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.animate(mView).translationY(mView.getHeight()) 481b7f9224b1495db47eb8fd813b5912250e900770aChris Banes .setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR) 482b7f9224b1495db47eb8fd813b5912250e900770aChris Banes .setDuration(ANIMATION_DURATION) 483b7f9224b1495db47eb8fd813b5912250e900770aChris Banes .setListener(new ViewPropertyAnimatorListenerAdapter() { 484b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 485b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onAnimationStart(View view) { 486b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mView.animateChildrenOut(0, ANIMATION_FADE_DURATION); 487b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 488b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 489b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 490b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onAnimationEnd(View view) { 491b7f9224b1495db47eb8fd813b5912250e900770aChris Banes onViewHidden(); 492b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 493b7f9224b1495db47eb8fd813b5912250e900770aChris Banes }).start(); 494b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } else { 495a577676a64e5353b8ec927117151aa6be84adf66Chris Banes Animation anim = AnimationUtils.loadAnimation(mView.getContext(), R.anim.design_snackbar_out); 496b7f9224b1495db47eb8fd813b5912250e900770aChris Banes anim.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); 497b7f9224b1495db47eb8fd813b5912250e900770aChris Banes anim.setDuration(ANIMATION_DURATION); 498b7f9224b1495db47eb8fd813b5912250e900770aChris Banes anim.setAnimationListener(new Animation.AnimationListener() { 499b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 500b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onAnimationEnd(Animation animation) { 501b7f9224b1495db47eb8fd813b5912250e900770aChris Banes onViewHidden(); 502b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 503b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 504b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 505b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onAnimationStart(Animation animation) {} 506b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 507b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 508b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onAnimationRepeat(Animation animation) {} 509b7f9224b1495db47eb8fd813b5912250e900770aChris Banes }); 510b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mView.startAnimation(anim); 511b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 512b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 513b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 514b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final void hideView() { 515b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (mView.getVisibility() != View.VISIBLE || isBeingDragged()) { 516b7f9224b1495db47eb8fd813b5912250e900770aChris Banes onViewHidden(); 517b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } else { 518b7f9224b1495db47eb8fd813b5912250e900770aChris Banes animateViewOut(); 519b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 520b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 521b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 522b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private void onViewHidden() { 523b7f9224b1495db47eb8fd813b5912250e900770aChris Banes // First remove the view from the parent 524b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mParent.removeView(mView); 525bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes // Now call the dismiss listener (if available) 526bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes if (mCallback != null) { 527bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes mCallback.onDismissed(this); 528bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes } 529bfae5eb86f8c5e63b33b6d36073f2230599a716bChris Banes // Finally, tell the SnackbarManager that it has been dismissed 530b7f9224b1495db47eb8fd813b5912250e900770aChris Banes SnackbarManager.getInstance().onDismissed(mManagerCallback); 531b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 532b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 533b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 534b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @return if the view is being being dragged or settled by {@link SwipeDismissBehavior}. 535b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 536b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private boolean isBeingDragged() { 537b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final ViewGroup.LayoutParams lp = mView.getLayoutParams(); 538b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 539b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (lp instanceof CoordinatorLayout.LayoutParams) { 540b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final CoordinatorLayout.LayoutParams cllp = (CoordinatorLayout.LayoutParams) lp; 541b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final CoordinatorLayout.Behavior behavior = cllp.getBehavior(); 542b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 543b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (behavior instanceof SwipeDismissBehavior) { 544b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return ((SwipeDismissBehavior) behavior).getDragState() 545b7f9224b1495db47eb8fd813b5912250e900770aChris Banes != SwipeDismissBehavior.STATE_IDLE; 546b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 547b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 548b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return false; 549b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 550b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 551b7f9224b1495db47eb8fd813b5912250e900770aChris Banes /** 552b7f9224b1495db47eb8fd813b5912250e900770aChris Banes * @hide 553b7f9224b1495db47eb8fd813b5912250e900770aChris Banes */ 554b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public static class SnackbarLayout extends LinearLayout { 555b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private TextView mMessageView; 5565cf1a7e04097b7e116c118cfa823a4cdb48f38a1Chris Banes private Button mActionView; 557b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 558b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private int mMaxWidth; 559b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private int mMaxInlineActionWidth; 560b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 561b7f9224b1495db47eb8fd813b5912250e900770aChris Banes interface OnLayoutChangeListener { 562b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public void onLayoutChange(View view, int left, int top, int right, int bottom); 563b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 564b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 565b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private OnLayoutChangeListener mOnLayoutChangeListener; 566b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 567b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public SnackbarLayout(Context context) { 568b7f9224b1495db47eb8fd813b5912250e900770aChris Banes this(context, null); 569b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 570b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 571b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public SnackbarLayout(Context context, AttributeSet attrs) { 572b7f9224b1495db47eb8fd813b5912250e900770aChris Banes super(context, attrs); 573b7f9224b1495db47eb8fd813b5912250e900770aChris Banes TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SnackbarLayout); 574b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mMaxWidth = a.getDimensionPixelSize(R.styleable.SnackbarLayout_android_maxWidth, -1); 575b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mMaxInlineActionWidth = a.getDimensionPixelSize( 576b7f9224b1495db47eb8fd813b5912250e900770aChris Banes R.styleable.SnackbarLayout_maxActionInlineWidth, -1); 5773a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes if (a.hasValue(R.styleable.SnackbarLayout_elevation)) { 5783a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes ViewCompat.setElevation(this, a.getDimensionPixelSize( 5793a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes R.styleable.SnackbarLayout_elevation, 0)); 5803a2c9c408e240e761b043139c5d228d3ad93f6c2Chris Banes } 581b7f9224b1495db47eb8fd813b5912250e900770aChris Banes a.recycle(); 582b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 583b7f9224b1495db47eb8fd813b5912250e900770aChris Banes setClickable(true); 584b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 585b7f9224b1495db47eb8fd813b5912250e900770aChris Banes // Now inflate our content. We need to do this manually rather than using an <include> 586b7f9224b1495db47eb8fd813b5912250e900770aChris Banes // in the layout since older versions of the Android do not inflate includes with 587b7f9224b1495db47eb8fd813b5912250e900770aChris Banes // the correct Context. 588a577676a64e5353b8ec927117151aa6be84adf66Chris Banes LayoutInflater.from(context).inflate(R.layout.design_layout_snackbar_include, this); 589b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 590b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 591b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 592b7f9224b1495db47eb8fd813b5912250e900770aChris Banes protected void onFinishInflate() { 593b7f9224b1495db47eb8fd813b5912250e900770aChris Banes super.onFinishInflate(); 594b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mMessageView = (TextView) findViewById(R.id.snackbar_text); 5955cf1a7e04097b7e116c118cfa823a4cdb48f38a1Chris Banes mActionView = (Button) findViewById(R.id.snackbar_action); 596b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 597b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 598b7f9224b1495db47eb8fd813b5912250e900770aChris Banes TextView getMessageView() { 599b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return mMessageView; 600b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 601b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 6025cf1a7e04097b7e116c118cfa823a4cdb48f38a1Chris Banes Button getActionView() { 603b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return mActionView; 604b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 605b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 606b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 607b7f9224b1495db47eb8fd813b5912250e900770aChris Banes protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 608b7f9224b1495db47eb8fd813b5912250e900770aChris Banes super.onMeasure(widthMeasureSpec, heightMeasureSpec); 609b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 610b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (mMaxWidth > 0 && getMeasuredWidth() > mMaxWidth) { 611b7f9224b1495db47eb8fd813b5912250e900770aChris Banes widthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxWidth, MeasureSpec.EXACTLY); 612b7f9224b1495db47eb8fd813b5912250e900770aChris Banes super.onMeasure(widthMeasureSpec, heightMeasureSpec); 613b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 614b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 615b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final int multiLineVPadding = getResources().getDimensionPixelSize( 616a577676a64e5353b8ec927117151aa6be84adf66Chris Banes R.dimen.design_snackbar_padding_vertical_2lines); 617b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final int singleLineVPadding = getResources().getDimensionPixelSize( 618a577676a64e5353b8ec927117151aa6be84adf66Chris Banes R.dimen.design_snackbar_padding_vertical); 619b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final boolean isMultiLine = mMessageView.getLayout().getLineCount() > 1; 620b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 621b7f9224b1495db47eb8fd813b5912250e900770aChris Banes boolean remeasure = false; 622b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (isMultiLine && mMaxInlineActionWidth > 0 623b7f9224b1495db47eb8fd813b5912250e900770aChris Banes && mActionView.getMeasuredWidth() > mMaxInlineActionWidth) { 624b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (updateViewsWithinLayout(VERTICAL, multiLineVPadding, 625b7f9224b1495db47eb8fd813b5912250e900770aChris Banes multiLineVPadding - singleLineVPadding)) { 626b7f9224b1495db47eb8fd813b5912250e900770aChris Banes remeasure = true; 627b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 628b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } else { 629b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final int messagePadding = isMultiLine ? multiLineVPadding : singleLineVPadding; 630b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (updateViewsWithinLayout(HORIZONTAL, messagePadding, messagePadding)) { 631b7f9224b1495db47eb8fd813b5912250e900770aChris Banes remeasure = true; 632b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 633b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 634b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 635b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (remeasure) { 636b7f9224b1495db47eb8fd813b5912250e900770aChris Banes super.onMeasure(widthMeasureSpec, heightMeasureSpec); 637b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 638b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 639b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 640b7f9224b1495db47eb8fd813b5912250e900770aChris Banes void animateChildrenIn(int delay, int duration) { 641b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.setAlpha(mMessageView, 0f); 642b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.animate(mMessageView).alpha(1f).setDuration(duration) 643b7f9224b1495db47eb8fd813b5912250e900770aChris Banes .setStartDelay(delay).start(); 644b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 645b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (mActionView.getVisibility() == VISIBLE) { 646b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.setAlpha(mActionView, 0f); 647b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.animate(mActionView).alpha(1f).setDuration(duration) 648b7f9224b1495db47eb8fd813b5912250e900770aChris Banes .setStartDelay(delay).start(); 649b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 650b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 651b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 652b7f9224b1495db47eb8fd813b5912250e900770aChris Banes void animateChildrenOut(int delay, int duration) { 653b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.setAlpha(mMessageView, 1f); 654b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.animate(mMessageView).alpha(0f).setDuration(duration) 655b7f9224b1495db47eb8fd813b5912250e900770aChris Banes .setStartDelay(delay).start(); 656b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 657b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (mActionView.getVisibility() == VISIBLE) { 658b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.setAlpha(mActionView, 1f); 659b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.animate(mActionView).alpha(0f).setDuration(duration) 660b7f9224b1495db47eb8fd813b5912250e900770aChris Banes .setStartDelay(delay).start(); 661b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 662b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 663b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 664b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 665b7f9224b1495db47eb8fd813b5912250e900770aChris Banes protected void onLayout(boolean changed, int l, int t, int r, int b) { 666b7f9224b1495db47eb8fd813b5912250e900770aChris Banes super.onLayout(changed, l, t, r, b); 667b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (changed && mOnLayoutChangeListener != null) { 668b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mOnLayoutChangeListener.onLayoutChange(this, l, t, r, b); 669b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 670b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 671b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 672b7f9224b1495db47eb8fd813b5912250e900770aChris Banes void setOnLayoutChangeListener(OnLayoutChangeListener onLayoutChangeListener) { 673b7f9224b1495db47eb8fd813b5912250e900770aChris Banes mOnLayoutChangeListener = onLayoutChangeListener; 674b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 675b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 676b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private boolean updateViewsWithinLayout(final int orientation, 677b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final int messagePadTop, final int messagePadBottom) { 678b7f9224b1495db47eb8fd813b5912250e900770aChris Banes boolean changed = false; 679b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (orientation != getOrientation()) { 680b7f9224b1495db47eb8fd813b5912250e900770aChris Banes setOrientation(orientation); 681b7f9224b1495db47eb8fd813b5912250e900770aChris Banes changed = true; 682b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 683b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (mMessageView.getPaddingTop() != messagePadTop 684b7f9224b1495db47eb8fd813b5912250e900770aChris Banes || mMessageView.getPaddingBottom() != messagePadBottom) { 685b7f9224b1495db47eb8fd813b5912250e900770aChris Banes updateTopBottomPadding(mMessageView, messagePadTop, messagePadBottom); 686b7f9224b1495db47eb8fd813b5912250e900770aChris Banes changed = true; 687b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 688b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return changed; 689b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 690b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 691b7f9224b1495db47eb8fd813b5912250e900770aChris Banes private static void updateTopBottomPadding(View view, int topPadding, int bottomPadding) { 692b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (ViewCompat.isPaddingRelative(view)) { 693b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.setPaddingRelative(view, 694b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.getPaddingStart(view), topPadding, 695b7f9224b1495db47eb8fd813b5912250e900770aChris Banes ViewCompat.getPaddingEnd(view), bottomPadding); 696b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } else { 697b7f9224b1495db47eb8fd813b5912250e900770aChris Banes view.setPadding(view.getPaddingLeft(), topPadding, 698b7f9224b1495db47eb8fd813b5912250e900770aChris Banes view.getPaddingRight(), bottomPadding); 699b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 700b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 701b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 702b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 703b7f9224b1495db47eb8fd813b5912250e900770aChris Banes final class Behavior extends SwipeDismissBehavior<SnackbarLayout> { 704b7f9224b1495db47eb8fd813b5912250e900770aChris Banes @Override 705b7f9224b1495db47eb8fd813b5912250e900770aChris Banes public boolean onInterceptTouchEvent(CoordinatorLayout parent, SnackbarLayout child, 706b7f9224b1495db47eb8fd813b5912250e900770aChris Banes MotionEvent event) { 707b7f9224b1495db47eb8fd813b5912250e900770aChris Banes // We want to make sure that we disable any Snackbar timeouts if the user is 708b7f9224b1495db47eb8fd813b5912250e900770aChris Banes // currently touching the Snackbar. We restore the timeout when complete 709b7f9224b1495db47eb8fd813b5912250e900770aChris Banes if (parent.isPointInChildBounds(child, (int) event.getX(), (int) event.getY())) { 710b7f9224b1495db47eb8fd813b5912250e900770aChris Banes switch (event.getActionMasked()) { 711b7f9224b1495db47eb8fd813b5912250e900770aChris Banes case MotionEvent.ACTION_DOWN: 712b7f9224b1495db47eb8fd813b5912250e900770aChris Banes SnackbarManager.getInstance().cancelTimeout(mManagerCallback); 713b7f9224b1495db47eb8fd813b5912250e900770aChris Banes break; 714b7f9224b1495db47eb8fd813b5912250e900770aChris Banes case MotionEvent.ACTION_UP: 715b7f9224b1495db47eb8fd813b5912250e900770aChris Banes case MotionEvent.ACTION_CANCEL: 716b7f9224b1495db47eb8fd813b5912250e900770aChris Banes SnackbarManager.getInstance().restoreTimeout(mManagerCallback); 717b7f9224b1495db47eb8fd813b5912250e900770aChris Banes break; 718b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 719b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 720b7f9224b1495db47eb8fd813b5912250e900770aChris Banes 721b7f9224b1495db47eb8fd813b5912250e900770aChris Banes return super.onInterceptTouchEvent(parent, child, event); 722b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 723b7f9224b1495db47eb8fd813b5912250e900770aChris Banes } 724b7f9224b1495db47eb8fd813b5912250e900770aChris Banes} 725