Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java |
| index dac8fbd155857d5f27d1e05f6671668acba72857..926fa11c3b3d4e9fe71e8b403687df3794f6b2a3 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java |
| @@ -15,6 +15,8 @@ import android.content.res.Resources; |
| import android.view.Gravity; |
| import android.view.MotionEvent; |
| import android.view.View; |
| +import android.view.ViewGroup; |
| +import android.view.ViewGroup.LayoutParams; |
| import android.widget.FrameLayout; |
| import org.chromium.base.ObserverList; |
| @@ -22,6 +24,7 @@ import org.chromium.chrome.R; |
| import org.chromium.chrome.browser.infobar.InfoBarContainer.InfoBarAnimationListener; |
| import java.util.ArrayList; |
| +import java.util.List; |
| /** |
| * Layout that displays infobars in a stack. Handles all the animations when adding or removing |
| @@ -112,6 +115,15 @@ public class InfoBarContainerLayout extends FrameLayout { |
| Resources res = context.getResources(); |
| mBackInfobarHeight = res.getDimensionPixelSize(R.dimen.infobar_peeking_height); |
| mFloatingBehavior = new FloatingBehavior(this); |
| + mBackgroundPeekSize = getResources().getDimensionPixelSize(R.dimen.infobar_compact_size); |
| + mInfoBarShadowHeight = getResources().getDimensionPixelSize(R.dimen.infobar_shadow_height); |
| + } |
| + |
| + @Override |
| + public void onAttachedToWindow() { |
| + super.onAttachedToWindow(); |
| + |
| + mBottomContainer = (ViewGroup) getRootView().findViewById(R.id.bottom_container); |
| } |
| /** |
| @@ -175,10 +187,20 @@ public class InfoBarContainerLayout extends FrameLayout { |
| // Animation durations. |
| private static final int DURATION_SLIDE_UP_MS = 250; |
| + private static final int DURATION_PEEK_MS = 500; |
| private static final int DURATION_SLIDE_DOWN_MS = 250; |
| private static final int DURATION_FADE_MS = 100; |
| private static final int DURATION_FADE_OUT_MS = 200; |
| + /** The height that an infobar will peek when being added behind another one. */ |
| + private final int mBackgroundPeekSize; |
| + |
| + /** The height of the shadow that sits above the infobar. */ |
| + private final int mInfoBarShadowHeight; |
| + |
| + /** The bottom container that the infobar container sits inside of. */ |
| + private ViewGroup mBottomContainer; |
| + |
| /** |
| * Base class for animations inside the InfoBarContainerLayout. |
| * |
| @@ -215,11 +237,10 @@ public class InfoBarContainerLayout extends FrameLayout { |
| * value to endValue and updates the side shadow positions on each frame. |
| */ |
| ValueAnimator createTranslationYAnimator(final InfoBarWrapper wrapper, float endValue) { |
| - ValueAnimator animator = ValueAnimator.ofFloat(wrapper.getTranslationY(), endValue); |
| + ValueAnimator animator = ObjectAnimator.ofFloat(wrapper, View.TRANSLATION_Y, endValue); |
| animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { |
| @Override |
| public void onAnimationUpdate(ValueAnimator animation) { |
| - wrapper.setTranslationY((float) animation.getAnimatedValue()); |
| mFloatingBehavior.updateShadowPosition(); |
| } |
| }); |
| @@ -396,8 +417,24 @@ public class InfoBarContainerLayout extends FrameLayout { |
| private class BackInfoBarAppearingAnimation extends InfoBarAnimation { |
| private InfoBarWrapper mAppearingWrapper; |
| + /** |
| + * A wrapper view to shrink the height of the infobar while it is appearing behind other |
| + * infobars. |
| + */ |
| + private ViewGroup mAppearanceAnimationWrapper; |
| + |
| BackInfoBarAppearingAnimation(Item appearingItem) { |
| 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.
|
| + mAppearanceAnimationWrapper = new FrameLayout(getContext()); |
| + mAppearingWrapper.addView(mAppearanceAnimationWrapper); |
| + |
| + mAppearanceAnimationWrapper.addView(appearingItem.getView()); |
| + mAppearanceAnimationWrapper.setClipChildren(true); |
| + mAppearanceAnimationWrapper.setLayoutParams(new LayoutParams( |
| + LayoutParams.MATCH_PARENT, mInfoBarShadowHeight + mBackgroundPeekSize)); |
| + |
| + // Set the infobar height to WRAP_CONTENT to avoid an assert in InfobarLayout. |
| + appearingItem.getView().getLayoutParams().height = LayoutParams.WRAP_CONTENT; |
| } |
| @Override |
| @@ -407,9 +444,36 @@ public class InfoBarContainerLayout extends FrameLayout { |
| @Override |
| Animator createAnimator() { |
| + AnimatorSet set = new AnimatorSet(); |
| + List<Animator> animators = new ArrayList<>(); |
| + |
| mAppearingWrapper.setTranslationY(mAppearingWrapper.getHeight()); |
| - return createTranslationYAnimator(mAppearingWrapper, 0f) |
| - .setDuration(DURATION_SLIDE_UP_MS); |
| + ValueAnimator animator = createTranslationYAnimator( |
| + mAppearingWrapper, mInfoBarShadowHeight - mBackgroundPeekSize); |
| + animators.add(animator); |
| + |
| + animators.add(createTranslationYAnimator(mAppearingWrapper, 0)); |
| + |
| + // When the infobar container is running this specific animation, do not clip the |
| + // children so the infobars can animate outside their container. |
| + set.addListener(new AnimatorListenerAdapter() { |
| + @Override |
| + public void onAnimationStart(Animator animation) { |
| + setHierarchyClipsChildren(false); |
| + } |
| + |
| + @Override |
| + public void onAnimationEnd(Animator animation) { |
| + mAppearanceAnimationWrapper.removeView(mAppearingWrapper.getItem().getView()); |
| + mAppearingWrapper.removeView(mAppearanceAnimationWrapper); |
| + setHierarchyClipsChildren(true); |
| + } |
| + }); |
| + |
| + set.playSequentially(animators); |
| + set.setDuration(DURATION_PEEK_MS); |
| + |
| + return set; |
| } |
| @Override |
| @@ -419,6 +483,17 @@ public class InfoBarContainerLayout extends FrameLayout { |
| } |
| /** |
| + * Used to set the relevant view hierarchy to not clip its children. This is used during |
| + * animation so views can draw outside the normal bounds. |
| + * @param clip Whether or not to clip child views. |
| + */ |
| + private void setHierarchyClipsChildren(boolean clip) { |
| + setClipChildren(clip); |
| + ((ViewGroup) getParent()).setClipChildren(clip); |
| + mBottomContainer.setClipChildren(clip); |
| + } |
| + |
| + /** |
| * The animation to hide the front infobar and reveal the second-to-front infobar. The front |
| * infobar slides down and off the screen. The back infobar(s) will adjust to the size of the |
| * new front infobar, and then the new front infobar's contents will fade in. |
| @@ -837,7 +912,10 @@ public class InfoBarContainerLayout extends FrameLayout { |
| protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { |
| widthMeasureSpec = mFloatingBehavior.beforeOnMeasure(widthMeasureSpec); |
| super.onMeasure(widthMeasureSpec, heightMeasureSpec); |
| - mFloatingBehavior.afterOnMeasure(getMeasuredHeight()); |
| + |
| + // Make sure the shadow is tall enough to compensate for the peek animation of other |
| + // infboars. |
| + mFloatingBehavior.afterOnMeasure(getMeasuredHeight() + mBackgroundPeekSize); |
| } |
| @Override |