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 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |