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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java

Issue 2846663002: Peek new infobars behind existing ones (Closed)
Patch Set: fix short infobar bug Created 3 years, 7 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.infobar; 5 package org.chromium.chrome.browser.infobar;
6 6
7 import android.animation.Animator; 7 import android.animation.Animator;
8 import android.animation.AnimatorListenerAdapter; 8 import android.animation.AnimatorListenerAdapter;
9 import android.animation.AnimatorSet; 9 import android.animation.AnimatorSet;
10 import android.animation.ObjectAnimator; 10 import android.animation.ObjectAnimator;
11 import android.animation.ValueAnimator; 11 import android.animation.ValueAnimator;
12 import android.annotation.SuppressLint; 12 import android.annotation.SuppressLint;
13 import android.content.Context; 13 import android.content.Context;
14 import android.content.res.Resources; 14 import android.content.res.Resources;
15 import android.view.Gravity; 15 import android.view.Gravity;
16 import android.view.MotionEvent; 16 import android.view.MotionEvent;
17 import android.view.View; 17 import android.view.View;
18 import android.view.ViewGroup;
19 import android.view.ViewGroup.LayoutParams;
18 import android.widget.FrameLayout; 20 import android.widget.FrameLayout;
19 21
20 import org.chromium.base.ObserverList; 22 import org.chromium.base.ObserverList;
21 import org.chromium.chrome.R; 23 import org.chromium.chrome.R;
22 import org.chromium.chrome.browser.infobar.InfoBarContainer.InfoBarAnimationList ener; 24 import org.chromium.chrome.browser.infobar.InfoBarContainer.InfoBarAnimationList ener;
23 25
24 import java.util.ArrayList; 26 import java.util.ArrayList;
27 import java.util.List;
25 28
26 /** 29 /**
27 * Layout that displays infobars in a stack. Handles all the animations when add ing or removing 30 * Layout that displays infobars in a stack. Handles all the animations when add ing or removing
28 * infobars and when swapping infobar contents. 31 * infobars and when swapping infobar contents.
29 * 32 *
30 * The first infobar to be added is visible at the front of the stack. Later inf obars peek up just 33 * The first infobar to be added is visible at the front of the stack. Later inf obars peek up just
31 * enough behind the front infobar to signal their existence; their contents are n't visible at all. 34 * enough behind the front infobar to signal their existence; their contents are n't visible at all.
32 * The stack has a max depth of three infobars. If additional infobars are added beyond this, they 35 * The stack has a max depth of three infobars. If additional infobars are added beyond this, they
33 * won't be visible at all until infobars in front of them are dismissed. 36 * won't be visible at all until infobars in front of them are dismissed.
34 * 37 *
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 } 108 }
106 109
107 /** 110 /**
108 * Creates an empty InfoBarContainerLayout. 111 * Creates an empty InfoBarContainerLayout.
109 */ 112 */
110 InfoBarContainerLayout(Context context) { 113 InfoBarContainerLayout(Context context) {
111 super(context); 114 super(context);
112 Resources res = context.getResources(); 115 Resources res = context.getResources();
113 mBackInfobarHeight = res.getDimensionPixelSize(R.dimen.infobar_peeking_h eight); 116 mBackInfobarHeight = res.getDimensionPixelSize(R.dimen.infobar_peeking_h eight);
114 mFloatingBehavior = new FloatingBehavior(this); 117 mFloatingBehavior = new FloatingBehavior(this);
118 mBackgroundPeekSize = getResources().getDimensionPixelSize(R.dimen.infob ar_compact_size);
119 mInfoBarShadowHeight = getResources().getDimensionPixelSize(R.dimen.info bar_shadow_height);
120 }
121
122 @Override
123 public void onAttachedToWindow() {
124 super.onAttachedToWindow();
125
126 mBottomContainer = (ViewGroup) getRootView().findViewById(R.id.bottom_co ntainer);
115 } 127 }
116 128
117 /** 129 /**
118 * Adds an infobar to the container. The infobar appearing animation will ha ppen after the 130 * Adds an infobar to the container. The infobar appearing animation will ha ppen after the
119 * current animation, if any, finishes. 131 * current animation, if any, finishes.
120 */ 132 */
121 void addInfoBar(Item item) { 133 void addInfoBar(Item item) {
122 if (item.isLegalDisclosure()) { 134 if (item.isLegalDisclosure()) {
123 mItems.add(0, item); 135 mItems.add(0, item);
124 } else { 136 } else {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 180
169 ///////////////////////////////////////// 181 /////////////////////////////////////////
170 // Implementation details 182 // Implementation details
171 ///////////////////////////////////////// 183 /////////////////////////////////////////
172 184
173 /** The maximum number of infobars visible at any time. */ 185 /** The maximum number of infobars visible at any time. */
174 private static final int MAX_STACK_DEPTH = 3; 186 private static final int MAX_STACK_DEPTH = 3;
175 187
176 // Animation durations. 188 // Animation durations.
177 private static final int DURATION_SLIDE_UP_MS = 250; 189 private static final int DURATION_SLIDE_UP_MS = 250;
190 private static final int DURATION_PEEK_MS = 500;
178 private static final int DURATION_SLIDE_DOWN_MS = 250; 191 private static final int DURATION_SLIDE_DOWN_MS = 250;
179 private static final int DURATION_FADE_MS = 100; 192 private static final int DURATION_FADE_MS = 100;
180 private static final int DURATION_FADE_OUT_MS = 200; 193 private static final int DURATION_FADE_OUT_MS = 200;
181 194
195 /** The height that an infobar will peek when being added behind another one . */
196 private final int mBackgroundPeekSize;
197
198 /** The height of the shadow that sits above the infobar. */
199 private final int mInfoBarShadowHeight;
200
201 /** The bottom container that the infobar container sits inside of. */
202 private ViewGroup mBottomContainer;
203
182 /** 204 /**
183 * Base class for animations inside the InfoBarContainerLayout. 205 * Base class for animations inside the InfoBarContainerLayout.
184 * 206 *
185 * Provides a standardized way to prepare for, run, and clean up after anima tions. Each subclass 207 * Provides a standardized way to prepare for, run, and clean up after anima tions. Each subclass
186 * should implement prepareAnimation(), createAnimator(), and onAnimationEnd () as needed. 208 * should implement prepareAnimation(), createAnimator(), and onAnimationEnd () as needed.
187 */ 209 */
188 private abstract class InfoBarAnimation { 210 private abstract class InfoBarAnimation {
189 private Animator mAnimator; 211 private Animator mAnimator;
190 212
191 final boolean isStarted() { 213 final boolean isStarted() {
(...skipping 16 matching lines...) Expand all
208 mAnimator = createAnimator(); 230 mAnimator = createAnimator();
209 mAnimator.addListener(listener); 231 mAnimator.addListener(listener);
210 mAnimator.start(); 232 mAnimator.start();
211 } 233 }
212 234
213 /** 235 /**
214 * Returns an animator that animates an InfoBarWrapper's y-translation f rom its current 236 * Returns an animator that animates an InfoBarWrapper's y-translation f rom its current
215 * value to endValue and updates the side shadow positions on each frame . 237 * value to endValue and updates the side shadow positions on each frame .
216 */ 238 */
217 ValueAnimator createTranslationYAnimator(final InfoBarWrapper wrapper, f loat endValue) { 239 ValueAnimator createTranslationYAnimator(final InfoBarWrapper wrapper, f loat endValue) {
218 ValueAnimator animator = ValueAnimator.ofFloat(wrapper.getTranslatio nY(), endValue); 240 ValueAnimator animator = ObjectAnimator.ofFloat(wrapper, View.TRANSL ATION_Y, endValue);
219 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener( ) { 241 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener( ) {
220 @Override 242 @Override
221 public void onAnimationUpdate(ValueAnimator animation) { 243 public void onAnimationUpdate(ValueAnimator animation) {
222 wrapper.setTranslationY((float) animation.getAnimatedValue() );
223 mFloatingBehavior.updateShadowPosition(); 244 mFloatingBehavior.updateShadowPosition();
224 } 245 }
225 }); 246 });
226 return animator; 247 return animator;
227 } 248 }
228 249
229 /** 250 /**
230 * Called before the animation begins. This is the time to add views to the hierarchy and 251 * Called before the animation begins. This is the time to add views to the hierarchy and
231 * adjust layout parameters. 252 * adjust layout parameters.
232 */ 253 */
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 } 410 }
390 } 411 }
391 412
392 /** 413 /**
393 * The animation to show a back infobar. The infobar slides up behind the ex isting infobars, so 414 * The animation to show a back infobar. The infobar slides up behind the ex isting infobars, so
394 * its top edge peeks out just a bit. 415 * its top edge peeks out just a bit.
395 */ 416 */
396 private class BackInfoBarAppearingAnimation extends InfoBarAnimation { 417 private class BackInfoBarAppearingAnimation extends InfoBarAnimation {
397 private InfoBarWrapper mAppearingWrapper; 418 private InfoBarWrapper mAppearingWrapper;
398 419
420 /**
421 * A wrapper view to shrink the height of the infobar while it is appear ing behind other
422 * infobars.
423 */
424 private ViewGroup mAppearanceAnimationWrapper;
425
399 BackInfoBarAppearingAnimation(Item appearingItem) { 426 BackInfoBarAppearingAnimation(Item appearingItem) {
400 mAppearingWrapper = new InfoBarWrapper(getContext(), appearingItem); 427 mAppearingWrapper = new InfoBarWrapper(getContext(), appearingItem);
Ted C 2017/05/18 23:01:33 I wonder if we could achieve the same if we did so
mdjones 2017/05/19 16:47:21 This could work, but the wrapper persists beyond t
Ted C 2017/05/19 16:52:13 Maybe we should just update InfoBarWrapper to have
mdjones 2017/05/19 17:18:20 Done.
428 mAppearanceAnimationWrapper = new FrameLayout(getContext());
429 mAppearingWrapper.addView(mAppearanceAnimationWrapper);
430
431 mAppearanceAnimationWrapper.addView(appearingItem.getView());
432 mAppearanceAnimationWrapper.setClipChildren(true);
433 mAppearanceAnimationWrapper.setLayoutParams(new LayoutParams(
434 LayoutParams.MATCH_PARENT, mInfoBarShadowHeight + mBackgroun dPeekSize));
435
436 // Set the infobar height to WRAP_CONTENT to avoid an assert in Info barLayout.
437 appearingItem.getView().getLayoutParams().height = LayoutParams.WRAP _CONTENT;
401 } 438 }
402 439
403 @Override 440 @Override
404 void prepareAnimation() { 441 void prepareAnimation() {
405 addWrapper(mAppearingWrapper); 442 addWrapper(mAppearingWrapper);
406 } 443 }
407 444
408 @Override 445 @Override
409 Animator createAnimator() { 446 Animator createAnimator() {
447 AnimatorSet set = new AnimatorSet();
448 List<Animator> animators = new ArrayList<>();
449
410 mAppearingWrapper.setTranslationY(mAppearingWrapper.getHeight()); 450 mAppearingWrapper.setTranslationY(mAppearingWrapper.getHeight());
411 return createTranslationYAnimator(mAppearingWrapper, 0f) 451 ValueAnimator animator = createTranslationYAnimator(
412 .setDuration(DURATION_SLIDE_UP_MS); 452 mAppearingWrapper, mInfoBarShadowHeight - mBackgroundPeekSiz e);
453 animators.add(animator);
454
455 animators.add(createTranslationYAnimator(mAppearingWrapper, 0));
456
457 // When the infobar container is running this specific animation, do not clip the
458 // children so the infobars can animate outside their container.
459 set.addListener(new AnimatorListenerAdapter() {
460 @Override
461 public void onAnimationStart(Animator animation) {
462 setHierarchyClipsChildren(false);
463 }
464
465 @Override
466 public void onAnimationEnd(Animator animation) {
467 mAppearanceAnimationWrapper.removeView(mAppearingWrapper.get Item().getView());
468 mAppearingWrapper.removeView(mAppearanceAnimationWrapper);
469 setHierarchyClipsChildren(true);
470 }
471 });
472
473 set.playSequentially(animators);
474 set.setDuration(DURATION_PEEK_MS);
475
476 return set;
413 } 477 }
414 478
415 @Override 479 @Override
416 int getAnimationType() { 480 int getAnimationType() {
417 return InfoBarAnimationListener.ANIMATION_TYPE_SHOW; 481 return InfoBarAnimationListener.ANIMATION_TYPE_SHOW;
418 } 482 }
419 } 483 }
420 484
421 /** 485 /**
486 * Used to set the relevant view hierarchy to not clip its children. This is used during
487 * animation so views can draw outside the normal bounds.
488 * @param clip Whether or not to clip child views.
489 */
490 private void setHierarchyClipsChildren(boolean clip) {
491 setClipChildren(clip);
492 ((ViewGroup) getParent()).setClipChildren(clip);
493 mBottomContainer.setClipChildren(clip);
494 }
495
496 /**
422 * The animation to hide the front infobar and reveal the second-to-front in fobar. The front 497 * The animation to hide the front infobar and reveal the second-to-front in fobar. The front
423 * infobar slides down and off the screen. The back infobar(s) will adjust t o the size of the 498 * infobar slides down and off the screen. The back infobar(s) will adjust t o the size of the
424 * new front infobar, and then the new front infobar's contents will fade in . 499 * new front infobar, and then the new front infobar's contents will fade in .
425 */ 500 */
426 private class FrontInfoBarDisappearingAndRevealingAnimation extends InfoBarA nimation { 501 private class FrontInfoBarDisappearingAndRevealingAnimation extends InfoBarA nimation {
427 private InfoBarWrapper mOldFrontWrapper; 502 private InfoBarWrapper mOldFrontWrapper;
428 private InfoBarWrapper mNewFrontWrapper; 503 private InfoBarWrapper mNewFrontWrapper;
429 private View mNewFrontContents; 504 private View mNewFrontContents;
430 505
431 @Override 506 @Override
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 LayoutParams lp = (LayoutParams) child.getLayoutParams(); 905 LayoutParams lp = (LayoutParams) child.getLayoutParams();
831 lp.topMargin = (childCount - 1 - i) * mBackInfobarHeight; 906 lp.topMargin = (childCount - 1 - i) * mBackInfobarHeight;
832 child.setLayoutParams(lp); 907 child.setLayoutParams(lp);
833 } 908 }
834 } 909 }
835 910
836 @Override 911 @Override
837 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 912 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
838 widthMeasureSpec = mFloatingBehavior.beforeOnMeasure(widthMeasureSpec); 913 widthMeasureSpec = mFloatingBehavior.beforeOnMeasure(widthMeasureSpec);
839 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 914 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
840 mFloatingBehavior.afterOnMeasure(getMeasuredHeight()); 915
916 // Make sure the shadow is tall enough to compensate for the peek animat ion of other
917 // infboars.
918 mFloatingBehavior.afterOnMeasure(getMeasuredHeight() + mBackgroundPeekSi ze);
841 } 919 }
842 920
843 @Override 921 @Override
844 protected void onLayout(boolean changed, int left, int top, int right, int b ottom) { 922 protected void onLayout(boolean changed, int left, int top, int right, int b ottom) {
845 super.onLayout(changed, left, top, right, bottom); 923 super.onLayout(changed, left, top, right, bottom);
846 mFloatingBehavior.updateShadowPosition(); 924 mFloatingBehavior.updateShadowPosition();
847 925
848 // Animations start after a layout has completed, at which point all vie ws are guaranteed 926 // Animations start after a layout has completed, at which point all vie ws are guaranteed
849 // to have valid sizes and positions. 927 // to have valid sizes and positions.
850 if (mAnimation != null && !mAnimation.isStarted()) { 928 if (mAnimation != null && !mAnimation.isStarted()) {
(...skipping 19 matching lines...) Expand all
870 948
871 @Override 949 @Override
872 public boolean onHoverEvent(MotionEvent event) { 950 public boolean onHoverEvent(MotionEvent event) {
873 super.onHoverEvent(event); 951 super.onHoverEvent(event);
874 // Consume all hover events so they do not reach the ContentView. In tou ch exploration mode, 952 // Consume all hover events so they do not reach the ContentView. In tou ch exploration mode,
875 // this prevents the user from interacting with the part of the ContentV iew behind the 953 // this prevents the user from interacting with the part of the ContentV iew behind the
876 // infobars. http://crbug.com/430701 954 // infobars. http://crbug.com/430701
877 return true; 955 return true;
878 } 956 }
879 } 957 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698