Snackbar.java revision bfae5eb86f8c5e63b33b6d36073f2230599a716b
1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/* 2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2015 The Android Open Source Project 3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License"); 5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License. 6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at 7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * http://www.apache.org/licenses/LICENSE-2.0 9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software 11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS, 12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and 14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License. 15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage android.support.design.widget; 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.content.Context; 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.content.res.ColorStateList; 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.content.res.TypedArray; 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.Build; 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.Handler; 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.Looper; 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.os.Message; 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.support.annotation.IntDef; 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.support.annotation.Nullable; 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.support.annotation.StringRes; 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.support.design.R; 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.support.v4.view.ViewCompat; 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.support.v4.view.ViewPropertyAnimatorListenerAdapter; 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.text.TextUtils; 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.util.AttributeSet; 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.LayoutInflater; 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.MotionEvent; 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.View; 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.ViewGroup; 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.ViewParent; 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.animation.Animation; 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.view.animation.AnimationUtils; 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.widget.FrameLayout; 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.widget.LinearLayout; 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.widget.TextView; 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.lang.annotation.Retention; 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport java.lang.annotation.RetentionPolicy; 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport static android.support.design.widget.AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR; 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/** 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Snackbars provide lightweight feedback about an operation. They show a brief message at the 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * bottom of the screen on mobile and lower left on larger devices. Snackbars appear above all other 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * elements on screen and only one can be displayed at a time. 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p> 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * They automatically disappear after a timeout or after user interaction elsewhere on the screen, 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * particularly after interactions that summon a new surface or activity. Snackbars can be swiped 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * off screen. 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p> 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Snackbars can contain an action which is set via 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link #setAction(CharSequence, android.view.View.OnClickListener)}. 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p> 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * To be notified when a snackbar has been shown or dismissed, you can provide a {@link Callback} 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * via {@link #setCallback(Callback)}.</p> 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class Snackbar { 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Callback class for {@link Snackbar} instances. 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see Snackbar#setCallback(Callback) 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static abstract class Callback { 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Called when the given {@link Snackbar} has been dismissed, either through a time-out, 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * having been manually dismissed, or an action being clicked. 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param snackbar The snackbar which has been dismissed. 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see Snackbar#dismiss() 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onDismissed(Snackbar snackbar) { 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // empty 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Called when the given {@link Snackbar} is visible. 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param snackbar The snackbar which is now visible. 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see Snackbar#show() 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onShown(Snackbar snackbar) { 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // empty 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @hide 97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @IntDef({LENGTH_SHORT, LENGTH_LONG}) 99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Retention(RetentionPolicy.SOURCE) 100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public @interface Duration {} 101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Show the Snackbar for a short period of time. 104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #setDuration 106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int LENGTH_SHORT = -1; 108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Show the Snackbar for a long period of time. 111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #setDuration 113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static final int LENGTH_LONG = 0; 115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final int ANIMATION_DURATION = 250; 117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final int ANIMATION_FADE_DURATION = 180; 118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final Handler sHandler; 120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final int MSG_SHOW = 0; 121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static final int MSG_DISMISS = 1; 122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks static { 124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks sHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() { 125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public boolean handleMessage(Message message) { 127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks switch (message.what) { 128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case MSG_SHOW: 129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ((Snackbar) message.obj).showView(); 130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return true; 131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case MSG_DISMISS: 132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ((Snackbar) message.obj).hideView(); 133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return true; 134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return false; 136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }); 138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final ViewGroup mParent; 141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final Context mContext; 142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final SnackbarLayout mView; 143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mDuration; 144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Callback mCallback; 145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Snackbar(ViewGroup parent) { 147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mParent = parent; 148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mContext = parent.getContext(); 149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks LayoutInflater inflater = LayoutInflater.from(mContext); 151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mView = (SnackbarLayout) inflater.inflate(R.layout.layout_snackbar, mParent, false); 152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Make a Snackbar to display a message 156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p>Snackbar will try and find a parent view to hold Snackbar's view from the value given 158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * to {@code view}. Snackbar will walk up the view tree trying to find a suitable parent, 159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * which is defined as a {@link CoordinatorLayout} or the window decor's content view, 160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * whichever comes first. 161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p>Having a {@link CoordinatorLayout} in your view hierarchy allows Snackbar to enable 163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * certain features, such as swipe-to-dismiss and automatically moving of widgets like 164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link FloatingActionButton}. 165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param view The view to find a parent from. 167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param text The text to show. Can be formatted text. 168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param duration How long to display the message. Either {@link #LENGTH_SHORT} or {@link 169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * #LENGTH_LONG} 170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static Snackbar make(View view, CharSequence text, @Duration int duration) { 172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Snackbar snackbar = new Snackbar(findSuitableParent(view)); 173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks snackbar.setText(text); 174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks snackbar.setDuration(duration); 175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return snackbar; 176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Make a Snackbar to display a message. 180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p>Snackbar will try and find a parent view to hold Snackbar's view from the value given 182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * to {@code view}. Snackbar will walk up the view tree trying to find a suitable parent, 183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * which is defined as a {@link CoordinatorLayout} or the window decor's content view, 184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * whichever comes first. 185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * <p>Having a {@link CoordinatorLayout} in your view hierarchy allows Snackbar to enable 187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * certain features, such as swipe-to-dismiss and automatically moving of widgets like 188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link FloatingActionButton}. 189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param view The view to find a parent from. 191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param resId The resource id of the string resource to use. Can be formatted text. 192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param duration How long to display the message. Either {@link #LENGTH_SHORT} or {@link 193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * #LENGTH_LONG} 194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static Snackbar make(View view, int resId, @Duration int duration) { 196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return make(view, view.getResources().getText(resId), duration); 197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Nullable 200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static ViewGroup findSuitableParent(View view) { 201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ViewGroup fallback = null; 202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks do { 203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (view instanceof CoordinatorLayout) { 204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // We've found a CoordinatorLayout, use it 205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return (ViewGroup) view; 206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else if (view instanceof FrameLayout) { 207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (view.getId() == android.R.id.content) { 208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // If we've hit the decor content view, then we didn't find a CoL in the 209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // hierarchy, so use it. 210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return (ViewGroup) view; 211227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 212227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // It's not the content view but we'll use it as our fallback 213227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks fallback = (ViewGroup) view; 214227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 215227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 216227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 217227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (view != null) { 218227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Else, we will loop and crawl up the view hierarchy and try to find a parent 219227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final ViewParent parent = view.getParent(); 220227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks view = parent instanceof View ? (View) parent : null; 221227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 222227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } while (view != null); 223227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 224227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // If we reach here then we didn't find a CoL or a suitable content view so we'll fallback 225227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return fallback; 226227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 227227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 228227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 229227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Set the action to be displayed in this {@link Snackbar}. 230227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 231227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param resId String resource to display 232227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param listener callback to be invoked when the action is clicked 233227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 234227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Snackbar setAction(@StringRes int resId, View.OnClickListener listener) { 235227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return setAction(mContext.getText(resId), listener); 236227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 237227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 238227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 239227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Set the action to be displayed in this {@link Snackbar}. 240227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 241227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param text Text to display 242227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param listener callback to be invoked when the action is clicked 243227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 244227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Snackbar setAction(CharSequence text, final View.OnClickListener listener) { 245227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final TextView tv = mView.getActionView(); 246227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 247227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (TextUtils.isEmpty(text) || listener == null) { 248227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks tv.setVisibility(View.GONE); 249227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks tv.setOnClickListener(null); 250227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 251227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks tv.setVisibility(View.VISIBLE); 252227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks tv.setText(text); 253227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks tv.setOnClickListener(new View.OnClickListener() { 254227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 255227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onClick(View view) { 256227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks listener.onClick(view); 257227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 258227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Now dismiss the Snackbar 259227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks dismiss(); 260227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 261227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }); 262227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 263227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return this; 264227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 265227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 266227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 267227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Sets the text color of the action specified in 268227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link #setAction(CharSequence, View.OnClickListener)}. 269227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 270227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Snackbar setActionTextColor(ColorStateList colors) { 271227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final TextView tv = mView.getActionView(); 272227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks tv.setTextColor(colors); 273227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return this; 274227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 275227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 276227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 277227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Sets the text color of the action specified in 278227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link #setAction(CharSequence, View.OnClickListener)}. 279227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 280227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Snackbar setActionTextColor(int color) { 281227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final TextView tv = mView.getActionView(); 282227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks tv.setTextColor(color); 283227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return this; 284227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 285227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 286227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 287227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Update the text in this {@link Snackbar}. 288227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 289227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param message The new text for the Toast. 290227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 291227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Snackbar setText(CharSequence message) { 292227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final TextView tv = mView.getMessageView(); 293227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks tv.setText(message); 294227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return this; 295227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 296227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 297227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 298227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Update the text in this {@link Snackbar}. 299227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 300227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param resId The new text for the Toast. 301227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 302227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Snackbar setText(@StringRes int resId) { 303227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return setText(mContext.getText(resId)); 304227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 305227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 306227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 307227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Set how long to show the view for. 308227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 309227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param duration either be one of the predefined lengths: 310227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * {@link #LENGTH_SHORT}, {@link #LENGTH_LONG}, or a custom duration 311227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * in milliseconds. 312227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 313227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Snackbar setDuration(@Duration int duration) { 314227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mDuration = duration; 315227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return this; 316227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 317227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 318227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 319227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Return the duration. 320227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 321227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @see #setDuration 322227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 323227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Duration 324227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public int getDuration() { 325227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mDuration; 326227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 327227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 328227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 329227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the {@link Snackbar}'s view. 330227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 331227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public View getView() { 332227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mView; 333227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 334227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 335227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 336227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Show the {@link Snackbar}. 337227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 338227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void show() { 339227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks SnackbarManager.getInstance().show(mDuration, mManagerCallback); 340227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 341227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 342227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 343227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Dismiss the {@link Snackbar}. 344227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 345227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void dismiss() { 346227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks SnackbarManager.getInstance().dismiss(mManagerCallback); 347227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 348227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 349227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 350227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Set a callback to be called when this the visibility of this {@link Snackbar} changes. 351227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 352227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void setCallback(Callback callback) { 353227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mCallback = callback; 354227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 355227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 356227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final SnackbarManager.Callback mManagerCallback = new SnackbarManager.Callback() { 357227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 358227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void show() { 359227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks sHandler.sendMessage(sHandler.obtainMessage(MSG_SHOW, Snackbar.this)); 360227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 361227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 362227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 363227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void dismiss() { 364227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks sHandler.sendMessage(sHandler.obtainMessage(MSG_DISMISS, Snackbar.this)); 365227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 366227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }; 367227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 368227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final void showView() { 369227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mView.getParent() == null) { 370227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final ViewGroup.LayoutParams lp = mView.getLayoutParams(); 371227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 372227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (lp instanceof CoordinatorLayout.LayoutParams) { 373227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // If our LayoutParams are from a CoordinatorLayout, we'll setup our Behavior 374227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 375227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final Behavior behavior = new Behavior(); 376227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks behavior.setStartAlphaSwipeDistance(0.1f); 377227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks behavior.setEndAlphaSwipeDistance(0.6f); 378227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks behavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_START_TO_END); 379227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks behavior.setListener(new SwipeDismissBehavior.OnDismissListener() { 380227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 381227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onDismiss(View view) { 382227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks dismiss(); 383227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 384227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 385227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 386227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onDragStateChanged(int state) { 387227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks switch (state) { 388227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case SwipeDismissBehavior.STATE_DRAGGING: 389227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case SwipeDismissBehavior.STATE_SETTLING: 390227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // If the view is being dragged or settling, cancel the timeout 391227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks SnackbarManager.getInstance().cancelTimeout(mManagerCallback); 392227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 393227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks case SwipeDismissBehavior.STATE_IDLE: 394227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // If the view has been released and is idle, restore the timeout 395227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks SnackbarManager.getInstance().restoreTimeout(mManagerCallback); 396227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks break; 397227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 398227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 399227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }); 400227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ((CoordinatorLayout.LayoutParams) lp).setBehavior(behavior); 401227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 402227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 403227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mParent.addView(mView); 404227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 405227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 406227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (ViewCompat.isLaidOut(mView)) { 407227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // If the view is already laid out, animate it now 408227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks animateViewIn(); 409227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 410227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Otherwise, add one of our layout change listeners and animate it in when laid out 411227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mView.setOnLayoutChangeListener(new SnackbarLayout.OnLayoutChangeListener() { 412227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 413227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onLayoutChange(View view, int left, int top, int right, int bottom) { 414227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks animateViewIn(); 415227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mView.setOnLayoutChangeListener(null); 416227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 417227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }); 418227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 419227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 420227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 421227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void animateViewIn() { 422227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 423227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ViewCompat.setTranslationY(mView, mView.getHeight()); 424227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ViewCompat.animate(mView).translationY(0f) 425227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR) 426227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .setDuration(ANIMATION_DURATION) 427227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .setListener(new ViewPropertyAnimatorListenerAdapter() { 428227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 429227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onAnimationStart(View view) { 430227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mView.animateChildrenIn(ANIMATION_DURATION - ANIMATION_FADE_DURATION, 431227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ANIMATION_FADE_DURATION); 432227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 433227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 434227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 435227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onAnimationEnd(View view) { 436227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mCallback != null) { 437227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mCallback.onShown(Snackbar.this); 438227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 439227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks SnackbarManager.getInstance().onShown(mManagerCallback); 440227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 441227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }).start(); 442227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 443227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Animation anim = AnimationUtils.loadAnimation(mView.getContext(), R.anim.snackbar_in); 444227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks anim.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); 445227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks anim.setDuration(ANIMATION_DURATION); 446227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks anim.setAnimationListener(new Animation.AnimationListener() { 447227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 448227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onAnimationEnd(Animation animation) { 449227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mCallback != null) { 450227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mCallback.onShown(Snackbar.this); 451227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 452227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks SnackbarManager.getInstance().onShown(mManagerCallback); 453227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 454227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 455227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 456227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onAnimationStart(Animation animation) {} 457227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 458227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 459227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onAnimationRepeat(Animation animation) {} 460227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }); 461227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mView.startAnimation(anim); 462227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 463227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 464227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 465227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void animateViewOut() { 466227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 467227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ViewCompat.animate(mView).translationY(mView.getHeight()) 468227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR) 469227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .setDuration(ANIMATION_DURATION) 470227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks .setListener(new ViewPropertyAnimatorListenerAdapter() { 471227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 472227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onAnimationStart(View view) { 473227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mView.animateChildrenOut(0, ANIMATION_FADE_DURATION); 474227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 475227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 476227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 477227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onAnimationEnd(View view) { 478227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onViewHidden(); 479227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 480227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }).start(); 481227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 482227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Animation anim = AnimationUtils.loadAnimation(mView.getContext(), R.anim.snackbar_out); 483227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks anim.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); 484227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks anim.setDuration(ANIMATION_DURATION); 485227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks anim.setAnimationListener(new Animation.AnimationListener() { 486227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 487227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onAnimationEnd(Animation animation) { 488227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onViewHidden(); 489227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 490227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 491227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 492227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onAnimationStart(Animation animation) {} 493227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 494227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 495227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onAnimationRepeat(Animation animation) {} 496227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks }); 497227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mView.startAnimation(anim); 498227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 499227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 500227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 501227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final void hideView() { 502227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mView.getVisibility() != View.VISIBLE || isBeingDragged()) { 503227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks onViewHidden(); 504227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } else { 505227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks animateViewOut(); 506227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 507227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 508227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 509227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private void onViewHidden() { 510227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // First remove the view from the parent 511227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mParent.removeView(mView); 512227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Now call the dismiss listener (if available) 513227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (mCallback != null) { 514227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mCallback.onDismissed(this); 515227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 516227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // Finally, tell the SnackbarManager that it has been dismissed 517227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks SnackbarManager.getInstance().onDismissed(mManagerCallback); 518227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 519227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 520227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 521227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return if the view is being being dragged or settled by {@link SwipeDismissBehavior}. 522227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 523227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private boolean isBeingDragged() { 524227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final ViewGroup.LayoutParams lp = mView.getLayoutParams(); 525227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 526227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (lp instanceof CoordinatorLayout.LayoutParams) { 527227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final CoordinatorLayout.LayoutParams cllp = (CoordinatorLayout.LayoutParams) lp; 528227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks final CoordinatorLayout.Behavior behavior = cllp.getBehavior(); 529227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 530227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (behavior instanceof SwipeDismissBehavior) { 531227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return ((SwipeDismissBehavior) behavior).getDragState() 532227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks != SwipeDismissBehavior.STATE_IDLE; 533227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 534227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 535227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return false; 536227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 537227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 538227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 539227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @hide 540227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 541227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static class SnackbarLayout extends LinearLayout { 542227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private TextView mMessageView; 543227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private TextView mActionView; 544227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 545227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mMaxWidth; 546227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private int mMaxInlineActionWidth; 547227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 548227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks interface OnLayoutChangeListener { 549227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public void onLayoutChange(View view, int left, int top, int right, int bottom); 550227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 551227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 552227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private OnLayoutChangeListener mOnLayoutChangeListener; 553227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 554227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public SnackbarLayout(Context context) { 555227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks this(context, null); 556227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 557227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 558227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public SnackbarLayout(Context context, AttributeSet attrs) { 559227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks super(context, attrs); 560227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SnackbarLayout); 561227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mMaxWidth = a.getDimensionPixelSize(R.styleable.SnackbarLayout_android_maxWidth, -1); 562227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mMaxInlineActionWidth = a.getDimensionPixelSize( 563227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks R.styleable.SnackbarLayout_maxActionInlineWidth, -1); 564227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks if (a.hasValue(R.styleable.SnackbarLayout_elevation)) { 565227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks ViewCompat.setElevation(this, a.getDimensionPixelSize( 566227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks R.styleable.SnackbarLayout_elevation, 0)); 567227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 568 a.recycle(); 569 570 setClickable(true); 571 572 // Now inflate our content. We need to do this manually rather than using an <include> 573 // in the layout since older versions of the Android do not inflate includes with 574 // the correct Context. 575 LayoutInflater.from(context).inflate(R.layout.layout_snackbar_include, this); 576 } 577 578 @Override 579 protected void onFinishInflate() { 580 super.onFinishInflate(); 581 mMessageView = (TextView) findViewById(R.id.snackbar_text); 582 mActionView = (TextView) findViewById(R.id.snackbar_action); 583 } 584 585 TextView getMessageView() { 586 return mMessageView; 587 } 588 589 TextView getActionView() { 590 return mActionView; 591 } 592 593 @Override 594 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 595 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 596 597 if (mMaxWidth > 0 && getMeasuredWidth() > mMaxWidth) { 598 widthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxWidth, MeasureSpec.EXACTLY); 599 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 600 } 601 602 final int multiLineVPadding = getResources().getDimensionPixelSize( 603 R.dimen.snackbar_padding_vertical_2lines); 604 final int singleLineVPadding = getResources().getDimensionPixelSize( 605 R.dimen.snackbar_padding_vertical); 606 final boolean isMultiLine = mMessageView.getLayout().getLineCount() > 1; 607 608 boolean remeasure = false; 609 if (isMultiLine && mMaxInlineActionWidth > 0 610 && mActionView.getMeasuredWidth() > mMaxInlineActionWidth) { 611 if (updateViewsWithinLayout(VERTICAL, multiLineVPadding, 612 multiLineVPadding - singleLineVPadding)) { 613 remeasure = true; 614 } 615 } else { 616 final int messagePadding = isMultiLine ? multiLineVPadding : singleLineVPadding; 617 if (updateViewsWithinLayout(HORIZONTAL, messagePadding, messagePadding)) { 618 remeasure = true; 619 } 620 } 621 622 if (remeasure) { 623 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 624 } 625 } 626 627 void animateChildrenIn(int delay, int duration) { 628 ViewCompat.setAlpha(mMessageView, 0f); 629 ViewCompat.animate(mMessageView).alpha(1f).setDuration(duration) 630 .setStartDelay(delay).start(); 631 632 if (mActionView.getVisibility() == VISIBLE) { 633 ViewCompat.setAlpha(mActionView, 0f); 634 ViewCompat.animate(mActionView).alpha(1f).setDuration(duration) 635 .setStartDelay(delay).start(); 636 } 637 } 638 639 void animateChildrenOut(int delay, int duration) { 640 ViewCompat.setAlpha(mMessageView, 1f); 641 ViewCompat.animate(mMessageView).alpha(0f).setDuration(duration) 642 .setStartDelay(delay).start(); 643 644 if (mActionView.getVisibility() == VISIBLE) { 645 ViewCompat.setAlpha(mActionView, 1f); 646 ViewCompat.animate(mActionView).alpha(0f).setDuration(duration) 647 .setStartDelay(delay).start(); 648 } 649 } 650 651 @Override 652 protected void onLayout(boolean changed, int l, int t, int r, int b) { 653 super.onLayout(changed, l, t, r, b); 654 if (changed && mOnLayoutChangeListener != null) { 655 mOnLayoutChangeListener.onLayoutChange(this, l, t, r, b); 656 } 657 } 658 659 void setOnLayoutChangeListener(OnLayoutChangeListener onLayoutChangeListener) { 660 mOnLayoutChangeListener = onLayoutChangeListener; 661 } 662 663 private boolean updateViewsWithinLayout(final int orientation, 664 final int messagePadTop, final int messagePadBottom) { 665 boolean changed = false; 666 if (orientation != getOrientation()) { 667 setOrientation(orientation); 668 changed = true; 669 } 670 if (mMessageView.getPaddingTop() != messagePadTop 671 || mMessageView.getPaddingBottom() != messagePadBottom) { 672 updateTopBottomPadding(mMessageView, messagePadTop, messagePadBottom); 673 changed = true; 674 } 675 return changed; 676 } 677 678 private static void updateTopBottomPadding(View view, int topPadding, int bottomPadding) { 679 if (ViewCompat.isPaddingRelative(view)) { 680 ViewCompat.setPaddingRelative(view, 681 ViewCompat.getPaddingStart(view), topPadding, 682 ViewCompat.getPaddingEnd(view), bottomPadding); 683 } else { 684 view.setPadding(view.getPaddingLeft(), topPadding, 685 view.getPaddingRight(), bottomPadding); 686 } 687 } 688 } 689 690 final class Behavior extends SwipeDismissBehavior<SnackbarLayout> { 691 @Override 692 public boolean onInterceptTouchEvent(CoordinatorLayout parent, SnackbarLayout child, 693 MotionEvent event) { 694 // We want to make sure that we disable any Snackbar timeouts if the user is 695 // currently touching the Snackbar. We restore the timeout when complete 696 if (parent.isPointInChildBounds(child, (int) event.getX(), (int) event.getY())) { 697 switch (event.getActionMasked()) { 698 case MotionEvent.ACTION_DOWN: 699 SnackbarManager.getInstance().cancelTimeout(mManagerCallback); 700 break; 701 case MotionEvent.ACTION_UP: 702 case MotionEvent.ACTION_CANCEL: 703 SnackbarManager.getInstance().restoreTimeout(mManagerCallback); 704 break; 705 } 706 } 707 708 return super.onInterceptTouchEvent(parent, child, event); 709 } 710 } 711} 712