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..babe13a61cd767ce22726b3c6c6344aa471354e4 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(); |
} |
}); |
@@ -407,9 +428,39 @@ 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); |
+ mAppearingWrapper.setRestrictHeightForAnimation(true); |
+ mAppearingWrapper.setHeightForAnimation(mInfoBarShadowHeight + mBackgroundPeekSize); |
+ mAppearingWrapper.addView(mAppearingWrapper.getItem().getView()); |
+ ValueAnimator animator = createTranslationYAnimator( |
+ mAppearingWrapper, mBackInfobarHeight - 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) { |
+ mAppearingWrapper.setRestrictHeightForAnimation(false); |
+ mAppearingWrapper.removeView(mAppearingWrapper.getItem().getView()); |
+ setHierarchyClipsChildren(true); |
+ } |
+ }); |
+ |
+ set.playSequentially(animators); |
+ set.setDuration(DURATION_PEEK_MS); |
+ |
+ return set; |
} |
@Override |
@@ -419,6 +470,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 +899,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 |