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