Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarManager.java

Issue 1229733002: Add new snackbar features to prepare for omnibox geolocation snackbar. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Ian's comments; fixed snackbar location in multiwindow mode when keyboard is visible Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.snackbar; 5 package org.chromium.chrome.browser.snackbar;
6 6
7 import android.graphics.Rect;
7 import android.os.Handler; 8 import android.os.Handler;
8 import android.view.Gravity; 9 import android.view.Gravity;
9 import android.view.View; 10 import android.view.View;
10 import android.view.View.OnClickListener; 11 import android.view.View.OnClickListener;
11 import android.view.ViewTreeObserver.OnGlobalLayoutListener; 12 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
13 import android.view.Window;
12 14
13 import org.chromium.base.ApiCompatibilityUtils; 15 import org.chromium.base.ApiCompatibilityUtils;
14 import org.chromium.base.VisibleForTesting; 16 import org.chromium.base.VisibleForTesting;
15 import org.chromium.chrome.R; 17 import org.chromium.chrome.R;
16 import org.chromium.chrome.browser.device.DeviceClassManager; 18 import org.chromium.chrome.browser.device.DeviceClassManager;
19 import org.chromium.ui.UiUtils;
17 import org.chromium.ui.base.DeviceFormFactor; 20 import org.chromium.ui.base.DeviceFormFactor;
18 21
19 import java.util.HashSet; 22 import java.util.HashSet;
20 import java.util.Stack; 23 import java.util.Stack;
21 24
22 /** 25 /**
23 * Manager for the snackbar showing at the bottom of activity. 26 * Manager for the snackbar showing at the bottom of activity.
24 * <p/> 27 * <p/>
25 * There should be only one SnackbarManager and one snackbar in the activity. Th e manager maintains 28 * There should be only one SnackbarManager and one snackbar in the activity. Th e manager maintains
26 * a stack to store all entries that should be displayed. When showing a new sna ckbar, old entry 29 * a stack to store all entries that should be displayed. When showing a new sna ckbar, old entry
27 * will be pushed to stack and text/button will be updated to the newest entry. 30 * will be pushed to stack and text/button will be updated to the newest entry.
28 * <p/> 31 * <p/>
29 * When action button is clicked, this manager will call 32 * When action button is clicked, this manager will call
30 * {@link SnackbarController#onAction(Object)} in corresponding listener, and sh ow the next 33 * {@link SnackbarController#onAction(Object)} in corresponding listener, and sh ow the next
31 * entry in stack. Otherwise if no action is taken by user during 34 * entry in stack. Otherwise if no action is taken by user during
32 * {@link #DEFAULT_SNACKBAR_SHOW_DURATION_MS} milliseconds, it will clear the st ack and call 35 * {@link #DEFAULT_SNACKBAR_DURATION_MS} milliseconds, it will clear the stack a nd call
33 * {@link SnackbarController#onDismissNoAction(Object)} to all listeners. 36 * {@link SnackbarController#onDismissNoAction(Object)} to all listeners.
34 */ 37 */
35 public class SnackbarManager implements OnClickListener, OnGlobalLayoutListener { 38 public class SnackbarManager implements OnClickListener, OnGlobalLayoutListener {
36 39
37 /** 40 /**
38 * Interface that shows the ability to provide a unified snackbar manager. 41 * Interface that shows the ability to provide a unified snackbar manager.
39 */ 42 */
40 public interface SnackbarManageable { 43 public interface SnackbarManageable {
41 /** 44 /**
42 * @return The snackbar manager that has a proper anchor view. 45 * @return The snackbar manager that has a proper anchor view.
(...skipping 26 matching lines...) Expand all
69 72
70 /** 73 /**
71 * Notify each SnackbarControllers instance only once immediately before the snackbar is 74 * Notify each SnackbarControllers instance only once immediately before the snackbar is
72 * dismissed. This function is likely to be used for controllers to do u ser metrics for 75 * dismissed. This function is likely to be used for controllers to do u ser metrics for
73 * dismissal. 76 * dismissal.
74 * @param isTimeout Whether this dismissal is triggered by timeout. 77 * @param isTimeout Whether this dismissal is triggered by timeout.
75 */ 78 */
76 void onDismissForEachType(boolean isTimeout); 79 void onDismissForEachType(boolean isTimeout);
77 } 80 }
78 81
79 private static final int DEFAULT_SNACKBAR_SHOW_DURATION_MS = 3000; 82 private static final int DEFAULT_SNACKBAR_DURATION_MS = 3000;
80 private static final int ACCESSIBILITY_MODE_SNACKBAR_DURATION_MS = 6000; 83 private static final int ACCESSIBILITY_MODE_SNACKBAR_DURATION_MS = 6000;
81 84
82 // Used instead of the constant so tests can override the value. 85 // Used instead of the constant so tests can override the value.
83 private static int sUndoBarShowDurationMs = DEFAULT_SNACKBAR_SHOW_DURATION_M S; 86 private static int sSnackbarDurationMs = DEFAULT_SNACKBAR_DURATION_MS;
84 private static int sAccessibilityUndoBarDurationMs = ACCESSIBILITY_MODE_SNAC KBAR_DURATION_MS; 87 private static int sAccessibilitySnackbarDurationMs = ACCESSIBILITY_MODE_SNA CKBAR_DURATION_MS;
85 88
86 private final boolean mIsTablet; 89 private final boolean mIsTablet;
87 90
88 private View mParent; 91 private View mDecor;
89 // Variable storing current xy position of parent view.
90 private int[] mTempTopLeft = new int[2];
91 private final Handler mUIThreadHandler; 92 private final Handler mUIThreadHandler;
92 private Stack<SnackbarEntry> mStack = new Stack<SnackbarEntry>(); 93 private Stack<Snackbar> mStack = new Stack<Snackbar>();
93 private SnackbarPopupWindow mPopup; 94 private SnackbarPopupWindow mPopup;
94 private final Runnable mHideRunnable = new Runnable() { 95 private final Runnable mHideRunnable = new Runnable() {
95 @Override 96 @Override
96 public void run() { 97 public void run() {
97 dismissSnackbar(true); 98 dismissSnackbar(true);
98 } 99 }
99 }; 100 };
100 101
102 // Variables used and reused in local calculations.
103 private int[] mTempDecorPosition = new int[2];
104 private Rect mTempVisibleDisplayFrame = new Rect();
105
101 /** 106 /**
102 * Create an instance of SnackbarManager with the root view of entire activi ty. 107 * Constructs a SnackbarManager to show snackbars in the given window.
103 * @param parent The view that snackbar anchors to. Since SnackbarManager sh ould be initialized
104 * during activity initialization, parent should always be set to root view of
105 * entire activity.
106 */ 108 */
107 public SnackbarManager(View parent) { 109 public SnackbarManager(Window window) {
108 mParent = parent; 110 mDecor = window.getDecorView();
109 mUIThreadHandler = new Handler(); 111 mUIThreadHandler = new Handler();
110 mIsTablet = DeviceFormFactor.isTablet(parent.getContext()); 112 mIsTablet = DeviceFormFactor.isTablet(mDecor.getContext());
111 } 113 }
112 114
113 /** 115 /**
116 * Shows a snackbar at the bottom of the screen, or above the keyboard if th e keyboard is
117 * visible.
118 */
119 public void showSnackbar(Snackbar snackbar) {
120 int durationMs = snackbar.getDuration();
121 if (durationMs == 0) {
122 durationMs = DeviceClassManager.isAccessibilityModeEnabled(mDecor.ge tContext())
123 ? sAccessibilitySnackbarDurationMs : sSnackbarDurationMs;
124 }
125
126 mUIThreadHandler.removeCallbacks(mHideRunnable);
127 mUIThreadHandler.postDelayed(mHideRunnable, durationMs);
128
129 mStack.push(snackbar);
130 if (mPopup == null) {
131 mPopup = new SnackbarPopupWindow(mDecor, this, snackbar);
132 showPopupAtBottom();
133 mDecor.getViewTreeObserver().addOnGlobalLayoutListener(this);
134 } else {
135 mPopup.update(snackbar, true);
136 }
137
138 mPopup.announceforAccessibility();
139 }
140
141 /**
142 * TODO(newt): delete this method. Update callers to use {@link #showSnackba r(Snackbar)}.
114 * Shows a snackbar with description text and an action button. 143 * Shows a snackbar with description text and an action button.
115 * @param template Teamplate used to compose full description. 144 * @param template Teamplate used to compose full description.
116 * @param description Text for description showing at start of snackbar. 145 * @param description Text for description showing at start of snackbar.
117 * @param actionText Text for action button to show. 146 * @param actionText Text for action button to show.
118 * @param actionData Data bound to this snackbar entry. Will be returned to listeners when 147 * @param actionData Data bound to this snackbar entry. Will be returned to listeners when
119 * action be clicked or snackbar be dismissed. 148 * action be clicked or snackbar be dismissed.
120 * @param controller Listener for this snackbar entry. 149 * @param controller Listener for this snackbar entry.
121 */ 150 */
122 public void showSnackbar(String template, String description, String actionT ext, 151 public void showSnackbar(String template, String description, String actionT ext,
123 Object actionData, SnackbarController controller) { 152 Object actionData, SnackbarController controller) {
124 int duration = sUndoBarShowDurationMs; 153 showSnackbar(Snackbar.make(description, controller).setTemplateText(temp late)
125 // Duration for snackbars to show is different in normal mode and in acc essibility mode. 154 .setAction(actionText, actionData));
126 if (DeviceClassManager.isAccessibilityModeEnabled(mParent.getContext())) {
127 duration = sAccessibilityUndoBarDurationMs;
128 }
129 showSnackbar(template, description, actionText, actionData, controller, duration);
130 } 155 }
131 156
132 /** 157 /**
158 * TODO(newt): delete this method. Update callers to use {@link #showSnackba r(Snackbar)}.
133 * Shows a snackbar for the given timeout duration with description text and an action button. 159 * Shows a snackbar for the given timeout duration with description text and an action button.
134 * Allows overriding the default timeout of {@link #DEFAULT_SNACKBAR_SHOW_DU RATION_MS} with 160 * Allows overriding the default timeout of {@link #DEFAULT_SNACKBAR_DURATIO N_MS} with
135 * a custom value. 161 * a custom value.
136 * @param template Teamplate used to compose full description. 162 * @param template Teamplate used to compose full description.
137 * @param description Text for description showing at start of snackbar. 163 * @param description Text for description showing at start of snackbar.
138 * @param actionText Text for action button to show. 164 * @param actionText Text for action button to show.
139 * @param actionData Data bound to this snackbar entry. Will be returned to listeners when 165 * @param actionData Data bound to this snackbar entry. Will be returned to listeners when
140 * action be clicked or snackbar be dismissed. 166 * action be clicked or snackbar be dismissed.
141 * @param controller Listener for this snackbar entry. 167 * @param controller Listener for this snackbar entry.
142 * @param timeoutMs The timeout to use in ms. 168 * @param timeoutMs The timeout to use in ms.
143 */ 169 */
144 public void showSnackbar(String template, String description, String actionT ext, 170 public void showSnackbar(String template, String description, String actionT ext,
145 Object actionData, SnackbarController controller, int timeoutMs) { 171 Object actionData, SnackbarController controller, int timeoutMs) {
146 mUIThreadHandler.removeCallbacks(mHideRunnable); 172 showSnackbar(Snackbar.make(description, controller).setTemplateText(temp late)
147 mUIThreadHandler.postDelayed(mHideRunnable, timeoutMs); 173 .setAction(actionText, actionData).setDuration(timeoutMs));
148
149 mStack.push(new SnackbarEntry(template, description, actionText, actionD ata, controller));
150 if (mPopup == null) {
151 mPopup = new SnackbarPopupWindow(mParent, this, template, descriptio n, actionText);
152 showPopupAtBottom();
153 mParent.getViewTreeObserver().addOnGlobalLayoutListener(this);
154 } else {
155 mPopup.setTextViews(template, description, actionText, true);
156 }
157
158 mPopup.announceforAccessibility();
159 } 174 }
160 175
161 /** 176 /**
162 * Convinient function for showSnackbar. Note this method adds passed entry to stack.
163 */
164 private void showSnackbar(SnackbarEntry entry) {
165 showSnackbar(entry.mTemplate, entry.mDescription, entry.mActionText, ent ry.mData,
166 entry.mController);
167 }
168
169 /**
170 * Change parent view of snackbar. This method is likely to be called when a new window is
171 * hiding the snackbar and will dismiss all snackbars.
172 * @param newParent The new parent view snackbar anchors to.
173 */
174 public void setParentView(View newParent) {
175 if (newParent == mParent) return;
176 mParent.getViewTreeObserver().removeOnGlobalLayoutListener(this);
177 mUIThreadHandler.removeCallbacks(mHideRunnable);
178 dismissSnackbar(false);
179 mParent = newParent;
180 }
181
182 /**
183 * Dismisses snackbar, clears out all entries in stack and prevents future r emove callbacks from 177 * Dismisses snackbar, clears out all entries in stack and prevents future r emove callbacks from
184 * happening. This method also unregisters this class from global layout not ifications. 178 * happening. This method also unregisters this class from global layout not ifications.
185 * @param isTimeout Whether dismissal was triggered by timeout. 179 * @param isTimeout Whether dismissal was triggered by timeout.
186 */ 180 */
187 public void dismissSnackbar(boolean isTimeout) { 181 public void dismissSnackbar(boolean isTimeout) {
188 mUIThreadHandler.removeCallbacks(mHideRunnable); 182 mUIThreadHandler.removeCallbacks(mHideRunnable);
189 183
190 if (mPopup != null) { 184 if (mPopup != null) {
191 mPopup.dismiss(); 185 mPopup.dismiss();
192 mPopup = null; 186 mPopup = null;
193 } 187 }
194 188
195 HashSet<SnackbarController> controllers = new HashSet<SnackbarController >(); 189 HashSet<SnackbarController> controllers = new HashSet<SnackbarController >();
196 190
197 while (!mStack.isEmpty()) { 191 while (!mStack.isEmpty()) {
198 SnackbarEntry entry = mStack.pop(); 192 Snackbar snackbar = mStack.pop();
199 if (!controllers.contains(entry.mController)) { 193 if (!controllers.contains(snackbar.getController())) {
200 entry.mController.onDismissForEachType(isTimeout); 194 snackbar.getController().onDismissForEachType(isTimeout);
201 controllers.add(entry.mController); 195 controllers.add(snackbar.getController());
202 } 196 }
203 entry.mController.onDismissNoAction(entry.mData); 197 snackbar.getController().onDismissNoAction(snackbar.getActionData()) ;
204 } 198 }
205 mParent.getViewTreeObserver().removeOnGlobalLayoutListener(this); 199 mDecor.getViewTreeObserver().removeOnGlobalLayoutListener(this);
206 } 200 }
207 201
208 /** 202 /**
209 * Removes all entries for certain type of controller. This method is used w hen a controller 203 * Removes all entries for certain type of controller. This method is used w hen a controller
210 * wants to remove all entries it posted to snackbar manager before. 204 * wants to remove all entries it posted to snackbar manager before.
211 * @param controller This method only removes entries posted by this control ler. 205 * @param controller This method only removes entries posted by this control ler.
212 */ 206 */
213 public void removeSnackbarEntry(SnackbarController controller) { 207 public void removeSnackbarEntry(SnackbarController controller) {
214 boolean isFound = false; 208 boolean isFound = false;
215 SnackbarEntry[] snackbarEntries = new SnackbarEntry[mStack.size()]; 209 Snackbar[] snackbars = new Snackbar[mStack.size()];
216 mStack.toArray(snackbarEntries); 210 mStack.toArray(snackbars);
217 for (SnackbarEntry entry : snackbarEntries) { 211 for (Snackbar snackbar : snackbars) {
218 if (entry.mController == controller) { 212 if (snackbar.getController() == controller) {
219 mStack.remove(entry); 213 mStack.remove(snackbar);
220 isFound = true; 214 isFound = true;
221 } 215 }
222 } 216 }
223 if (!isFound) return; 217 if (!isFound) return;
224 218
225 finishSnackbarEntryRemoval(controller); 219 finishSnackbarEntryRemoval(controller);
226 } 220 }
227 221
228 /** 222 /**
229 * Removes all entries for certain type of controller and with specified dat a. This method is 223 * Removes all entries for certain type of controller and with specified dat a. This method is
230 * used when a controller wants to remove some entries it posted to snackbar manager before. 224 * used when a controller wants to remove some entries it posted to snackbar manager before.
231 * However it does not affect other controllers' entries. Note that this met hod assumes 225 * However it does not affect other controllers' entries. Note that this met hod assumes
232 * different types of snackbar controllers are not sharing the same instance . 226 * different types of snackbar controllers are not sharing the same instance .
233 * @param controller This method only removes entries posted by this control ler. 227 * @param controller This method only removes entries posted by this control ler.
234 * @param data Identifier of an entry to be removed from stack. 228 * @param data Identifier of an entry to be removed from stack.
235 */ 229 */
236 public void removeSnackbarEntry(SnackbarController controller, Object data) { 230 public void removeSnackbarEntry(SnackbarController controller, Object data) {
237 boolean isFound = false; 231 boolean isFound = false;
238 for (SnackbarEntry entry : mStack) { 232 for (Snackbar snackbar : mStack) {
239 if (entry.mData != null && entry.mData.equals(data) 233 if (snackbar.getActionData() != null && snackbar.getActionData().equ als(data)
240 && entry.mController == controller) { 234 && snackbar.getController() == controller) {
241 mStack.remove(entry); 235 mStack.remove(snackbar);
242 isFound = true; 236 isFound = true;
243 break; 237 break;
244 } 238 }
245 } 239 }
246 if (!isFound) return; 240 if (!isFound) return;
247 241
248 finishSnackbarEntryRemoval(controller); 242 finishSnackbarEntryRemoval(controller);
249 } 243 }
250 244
251 private void finishSnackbarEntryRemoval(SnackbarController controller) { 245 private void finishSnackbarEntryRemoval(SnackbarController controller) {
252 controller.onDismissForEachType(false); 246 controller.onDismissForEachType(false);
253 247
254 if (mStack.isEmpty()) { 248 if (mStack.isEmpty()) {
255 dismissSnackbar(false); 249 dismissSnackbar(false);
256 } else { 250 } else {
257 // Refresh the snackbar to let it show top of stack and have full ti meout. 251 // Refresh the snackbar to let it show top of stack and have full ti meout.
258 showSnackbar(mStack.pop()); 252 showSnackbar(mStack.pop());
259 } 253 }
260 } 254 }
261 255
262 /** 256 /**
263 * Handles click event for action button at end of snackbar. 257 * Handles click event for action button at end of snackbar.
264 */ 258 */
265 @Override 259 @Override
266 public void onClick(View v) { 260 public void onClick(View v) {
267 assert !mStack.isEmpty(); 261 assert !mStack.isEmpty();
268 262
269 SnackbarEntry entry = mStack.pop(); 263 Snackbar snackbar = mStack.pop();
270 entry.mController.onAction(entry.mData); 264 snackbar.getController().onAction(snackbar.getActionData());
271 265
272 if (!mStack.isEmpty()) { 266 if (!mStack.isEmpty()) {
273 showSnackbar(mStack.pop()); 267 showSnackbar(mStack.pop());
274 } else { 268 } else {
275 dismissSnackbar(false); 269 dismissSnackbar(false);
276 } 270 }
277 } 271 }
278 272
279 /**
280 * Calculates the show-up position from TOP START corner of parent view as a workaround of an
281 * android bug http://b/17789629 on Lollipop.
282 */
283 private void showPopupAtBottom() { 273 private void showPopupAtBottom() {
284 int margin = mIsTablet ? mParent.getResources().getDimensionPixelSize( 274 // When the keyboard is showing, translating the snackbar upwards looks bad because it
285 R.dimen.undo_bar_tablet_margin) : 0; 275 // overlaps the keyboard. In this case, use an alternative animation wit hout translation.
286 mParent.getLocationInWindow(mTempTopLeft); 276 boolean isKeyboardShowing = UiUtils.isKeyboardShowing(mDecor.getContext( ), mDecor);
287 mPopup.showAtLocation(mParent, Gravity.START | Gravity.TOP, margin, 277 mPopup.setAnimationStyle(isKeyboardShowing ? R.style.SnackbarAnimationWi thKeyboard
288 mTempTopLeft[1] + mParent.getHeight() - mPopup.getHeight() - mar gin); 278 : R.style.SnackbarAnimation);
279
280 mDecor.getLocationInWindow(mTempDecorPosition);
281 mDecor.getWindowVisibleDisplayFrame(mTempVisibleDisplayFrame);
282 int decorBottom = mTempDecorPosition[1] + mDecor.getHeight();
283 int visibleBottom = Math.min(mTempVisibleDisplayFrame.bottom, decorBotto m);
284 int margin = mIsTablet ? mDecor.getResources().getDimensionPixelSize(
285 R.dimen.snackbar_tablet_margin) : 0;
286
287 mPopup.showAtLocation(mDecor, Gravity.START | Gravity.BOTTOM, margin,
288 decorBottom - visibleBottom + margin);
289 } 289 }
290 290
291 /** 291 /**
292 * Resize and re-align popup window when device orientation changes, or soft keyboard shows up. 292 * Resize and re-position popup window when the device orientation changes o r the software
293 * keyboard appears. Be careful not to let the snackbar overlap the Android navigation bar:
294 * http://b/17789629.
293 */ 295 */
294 @Override 296 @Override
295 public void onGlobalLayout() { 297 public void onGlobalLayout() {
296 if (mPopup == null) return; 298 if (mPopup == null) return;
297 mParent.getLocationInWindow(mTempTopLeft); 299
300 mDecor.getLocationInWindow(mTempDecorPosition);
301 mDecor.getWindowVisibleDisplayFrame(mTempVisibleDisplayFrame);
302 int decorBottom = mTempDecorPosition[1] + mDecor.getHeight();
303 int visibleBottom = Math.min(mTempVisibleDisplayFrame.bottom, decorBotto m);
304
298 if (mIsTablet) { 305 if (mIsTablet) {
299 int margin = mParent.getResources().getDimensionPixelSize( 306 int margin = mDecor.getResources().getDimensionPixelOffset(
300 R.dimen.undo_bar_tablet_margin); 307 R.dimen.snackbar_tablet_margin);
301 int width = mParent.getResources().getDimensionPixelSize( 308 int width = mDecor.getResources().getDimensionPixelSize(R.dimen.snac kbar_tablet_width);
302 R.dimen.undo_bar_tablet_width); 309 boolean isRtl = ApiCompatibilityUtils.isLayoutRtl(mDecor);
303 boolean isRtl = ApiCompatibilityUtils.isLayoutRtl(mParent); 310 int startPosition = isRtl ? mDecor.getRight() - width - margin
304 int startPosition = isRtl ? mParent.getRight() - width - margin 311 : mDecor.getLeft() + margin;
305 : mParent.getLeft() + margin; 312 mPopup.update(startPosition, decorBottom - visibleBottom + margin, w idth, -1);
306 mPopup.update(startPosition,
307 mTempTopLeft[1] + mParent.getHeight() - mPopup.getHeight() - margin, width, -1);
308 } else { 313 } else {
309 // Phone relayout 314 mPopup.update(mDecor.getLeft(), decorBottom - visibleBottom, mDecor. getWidth(), -1);
310 mPopup.update(mParent.getLeft(),
311 mTempTopLeft[1] + mParent.getHeight() - mPopup.getHeight(), mParent.getWidth(),
312 -1);
313 } 315 }
314 } 316 }
315 317
316 /** 318 /**
317 * @return Whether there is a snackbar on screen. 319 * @return Whether there is a snackbar on screen.
318 */ 320 */
319 public boolean isShowing() { 321 public boolean isShowing() {
320 if (mPopup == null) return false; 322 if (mPopup == null) return false;
321 return mPopup.isShowing(); 323 return mPopup.isShowing();
322 } 324 }
323 325
324 /** 326 /**
325 * Allows overriding the default timeout of {@link #DEFAULT_SNACKBAR_SHOW_DU RATION_MS} with 327 * Overrides the default snackbar duration with a custom value for testing.
326 * a custom value. This is meant to be used by tests. 328 * @param durationMs The duration to use in ms.
327 * @param timeoutMs The new timeout to use in ms.
328 */ 329 */
329 @VisibleForTesting 330 @VisibleForTesting
330 public static void setTimeoutForTesting(int timeoutMs) { 331 public static void setDurationForTesting(int durationMs) {
331 sUndoBarShowDurationMs = timeoutMs; 332 sSnackbarDurationMs = durationMs;
332 sAccessibilityUndoBarDurationMs = timeoutMs; 333 sAccessibilitySnackbarDurationMs = durationMs;
333 }
334
335 /**
336 * Simple data structure representing a single snackbar in stack.
337 */
338 private static class SnackbarEntry {
339 public String mTemplate;
340 public String mDescription;
341 public String mActionText;
342 public Object mData;
343 public SnackbarController mController;
344
345 public SnackbarEntry(String template, String description, String actionT ext,
346 Object actionData, SnackbarController controller) {
347 mTemplate = template;
348 mDescription = description;
349 mActionText = actionText;
350 mData = actionData;
351 mController = controller;
352 }
353 } 334 }
354 } 335 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698