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

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: wrapper has height restricted mode 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
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 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
399 BackInfoBarAppearingAnimation(Item appearingItem) { 420 BackInfoBarAppearingAnimation(Item appearingItem) {
400 mAppearingWrapper = new InfoBarWrapper(getContext(), appearingItem); 421 mAppearingWrapper = new InfoBarWrapper(getContext(), appearingItem);
422 mAppearingWrapper.addView(appearingItem.getView());
401 } 423 }
402 424
403 @Override 425 @Override
404 void prepareAnimation() { 426 void prepareAnimation() {
405 addWrapper(mAppearingWrapper); 427 addWrapper(mAppearingWrapper);
406 } 428 }
407 429
408 @Override 430 @Override
409 Animator createAnimator() { 431 Animator createAnimator() {
432 AnimatorSet set = new AnimatorSet();
433 List<Animator> animators = new ArrayList<>();
434
410 mAppearingWrapper.setTranslationY(mAppearingWrapper.getHeight()); 435 mAppearingWrapper.setTranslationY(mAppearingWrapper.getHeight());
411 return createTranslationYAnimator(mAppearingWrapper, 0f) 436 mAppearingWrapper.setHeightForAnimation(mInfoBarShadowHeight + mBack groundPeekSize);
412 .setDuration(DURATION_SLIDE_UP_MS); 437 ValueAnimator animator = createTranslationYAnimator(
438 mAppearingWrapper, mInfoBarShadowHeight - mBackgroundPeekSiz e);
439 animators.add(animator);
440
441 animators.add(createTranslationYAnimator(mAppearingWrapper, 0));
442
443 // When the infobar container is running this specific animation, do not clip the
444 // children so the infobars can animate outside their container.
445 set.addListener(new AnimatorListenerAdapter() {
446 @Override
447 public void onAnimationStart(Animator animation) {
448 mAppearingWrapper.setRestrictHeightForAnimation(true);
449 setHierarchyClipsChildren(false);
450 }
451
452 @Override
453 public void onAnimationEnd(Animator animation) {
454 mAppearingWrapper.setRestrictHeightForAnimation(false);
455 mAppearingWrapper.removeView(mAppearingWrapper.getItem().get View());
Ted C 2017/05/19 17:21:41 do we need to do this anymore?
mdjones 2017/05/19 17:30:14 Technically no. Prior to this change the content w
456 setHierarchyClipsChildren(true);
457 }
458 });
459
460 set.playSequentially(animators);
461 set.setDuration(DURATION_PEEK_MS);
462
463 return set;
413 } 464 }
414 465
415 @Override 466 @Override
416 int getAnimationType() { 467 int getAnimationType() {
417 return InfoBarAnimationListener.ANIMATION_TYPE_SHOW; 468 return InfoBarAnimationListener.ANIMATION_TYPE_SHOW;
418 } 469 }
419 } 470 }
420 471
421 /** 472 /**
473 * Used to set the relevant view hierarchy to not clip its children. This is used during
474 * animation so views can draw outside the normal bounds.
475 * @param clip Whether or not to clip child views.
476 */
477 private void setHierarchyClipsChildren(boolean clip) {
478 setClipChildren(clip);
479 ((ViewGroup) getParent()).setClipChildren(clip);
480 mBottomContainer.setClipChildren(clip);
481 }
482
483 /**
422 * The animation to hide the front infobar and reveal the second-to-front in fobar. The front 484 * 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 485 * 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 . 486 * new front infobar, and then the new front infobar's contents will fade in .
425 */ 487 */
426 private class FrontInfoBarDisappearingAndRevealingAnimation extends InfoBarA nimation { 488 private class FrontInfoBarDisappearingAndRevealingAnimation extends InfoBarA nimation {
427 private InfoBarWrapper mOldFrontWrapper; 489 private InfoBarWrapper mOldFrontWrapper;
428 private InfoBarWrapper mNewFrontWrapper; 490 private InfoBarWrapper mNewFrontWrapper;
429 private View mNewFrontContents; 491 private View mNewFrontContents;
430 492
431 @Override 493 @Override
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 LayoutParams lp = (LayoutParams) child.getLayoutParams(); 892 LayoutParams lp = (LayoutParams) child.getLayoutParams();
831 lp.topMargin = (childCount - 1 - i) * mBackInfobarHeight; 893 lp.topMargin = (childCount - 1 - i) * mBackInfobarHeight;
832 child.setLayoutParams(lp); 894 child.setLayoutParams(lp);
833 } 895 }
834 } 896 }
835 897
836 @Override 898 @Override
837 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 899 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
838 widthMeasureSpec = mFloatingBehavior.beforeOnMeasure(widthMeasureSpec); 900 widthMeasureSpec = mFloatingBehavior.beforeOnMeasure(widthMeasureSpec);
839 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 901 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
840 mFloatingBehavior.afterOnMeasure(getMeasuredHeight()); 902
903 // Make sure the shadow is tall enough to compensate for the peek animat ion of other
904 // infboars.
905 mFloatingBehavior.afterOnMeasure(getMeasuredHeight() + mBackgroundPeekSi ze);
841 } 906 }
842 907
843 @Override 908 @Override
844 protected void onLayout(boolean changed, int left, int top, int right, int b ottom) { 909 protected void onLayout(boolean changed, int left, int top, int right, int b ottom) {
845 super.onLayout(changed, left, top, right, bottom); 910 super.onLayout(changed, left, top, right, bottom);
846 mFloatingBehavior.updateShadowPosition(); 911 mFloatingBehavior.updateShadowPosition();
847 912
848 // Animations start after a layout has completed, at which point all vie ws are guaranteed 913 // Animations start after a layout has completed, at which point all vie ws are guaranteed
849 // to have valid sizes and positions. 914 // to have valid sizes and positions.
850 if (mAnimation != null && !mAnimation.isStarted()) { 915 if (mAnimation != null && !mAnimation.isStarted()) {
(...skipping 19 matching lines...) Expand all
870 935
871 @Override 936 @Override
872 public boolean onHoverEvent(MotionEvent event) { 937 public boolean onHoverEvent(MotionEvent event) {
873 super.onHoverEvent(event); 938 super.onHoverEvent(event);
874 // Consume all hover events so they do not reach the ContentView. In tou ch exploration mode, 939 // 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 940 // this prevents the user from interacting with the part of the ContentV iew behind the
876 // infobars. http://crbug.com/430701 941 // infobars. http://crbug.com/430701
877 return true; 942 return true;
878 } 943 }
879 } 944 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698