OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 mAppearingWrapper = new InfoBarWrapper(getContext(), appearingItem); | 421 mAppearingWrapper = new InfoBarWrapper(getContext(), appearingItem); |
401 } | 422 } |
402 | 423 |
403 @Override | 424 @Override |
404 void prepareAnimation() { | 425 void prepareAnimation() { |
405 addWrapper(mAppearingWrapper); | 426 addWrapper(mAppearingWrapper); |
406 } | 427 } |
407 | 428 |
408 @Override | 429 @Override |
409 Animator createAnimator() { | 430 Animator createAnimator() { |
| 431 AnimatorSet set = new AnimatorSet(); |
| 432 List<Animator> animators = new ArrayList<>(); |
| 433 |
410 mAppearingWrapper.setTranslationY(mAppearingWrapper.getHeight()); | 434 mAppearingWrapper.setTranslationY(mAppearingWrapper.getHeight()); |
411 return createTranslationYAnimator(mAppearingWrapper, 0f) | 435 mAppearingWrapper.setRestrictHeightForAnimation(true); |
412 .setDuration(DURATION_SLIDE_UP_MS); | 436 mAppearingWrapper.setHeightForAnimation(mInfoBarShadowHeight + mBack
groundPeekSize); |
| 437 mAppearingWrapper.addView(mAppearingWrapper.getItem().getView()); |
| 438 ValueAnimator animator = createTranslationYAnimator( |
| 439 mAppearingWrapper, mBackInfobarHeight - mBackgroundPeekSize)
; |
| 440 animators.add(animator); |
| 441 |
| 442 animators.add(createTranslationYAnimator(mAppearingWrapper, 0)); |
| 443 |
| 444 // When the infobar container is running this specific animation, do
not clip the |
| 445 // children so the infobars can animate outside their container. |
| 446 set.addListener(new AnimatorListenerAdapter() { |
| 447 @Override |
| 448 public void onAnimationStart(Animator animation) { |
| 449 setHierarchyClipsChildren(false); |
| 450 } |
| 451 |
| 452 @Override |
| 453 public void onAnimationEnd(Animator animation) { |
| 454 mAppearingWrapper.setRestrictHeightForAnimation(false); |
| 455 mAppearingWrapper.removeView(mAppearingWrapper.getItem().get
View()); |
| 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 Loading... |
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 Loading... |
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 } |
OLD | NEW |