| Index: chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java
|
| index 2b3c5be16e09805982473bde6e4c7d1b7d2d9805..1e25b61f7461f839ff5cc8602254ce6b08d2b934 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java
|
| @@ -7,18 +7,22 @@ package org.chromium.chrome.browser.infobar;
|
| import android.animation.ObjectAnimator;
|
| import android.app.Activity;
|
| import android.graphics.Canvas;
|
| +import android.graphics.Paint;
|
| import android.view.Gravity;
|
| import android.view.MotionEvent;
|
| import android.view.View;
|
| import android.view.ViewGroup;
|
| import android.widget.FrameLayout;
|
| import android.widget.LinearLayout;
|
| +import android.widget.ScrollView;
|
|
|
| import com.google.common.annotations.VisibleForTesting;
|
|
|
| import org.chromium.base.CalledByNative;
|
| +import org.chromium.chrome.R;
|
| import org.chromium.content_public.browser.WebContents;
|
| import org.chromium.ui.UiUtils;
|
| +import org.chromium.ui.base.DeviceFormFactor;
|
|
|
| import java.util.ArrayDeque;
|
| import java.util.ArrayList;
|
| @@ -32,9 +36,11 @@ import java.util.LinkedList;
|
| * When initiated from native code, special code is needed to keep the Java and native infobar in
|
| * sync, see NativeInfoBar.
|
| */
|
| -public class InfoBarContainer extends LinearLayout {
|
| +public class InfoBarContainer extends ScrollView {
|
| private static final String TAG = "InfoBarContainer";
|
| private static final long REATTACH_FADE_IN_MS = 250;
|
| + private static final int TAB_STRIP_AND_TOOLBAR_HEIGHT_PHONE_DP = 56;
|
| + private static final int TAB_STRIP_AND_TOOLBAR_HEIGHT_TABLET_DP = 96;
|
|
|
| /**
|
| * A listener for the InfoBar animation.
|
| @@ -94,10 +100,34 @@ public class InfoBarContainer extends LinearLayout {
|
| // Parent view that contains us.
|
| private ViewGroup mParentView;
|
|
|
| + // The LinearLayout that holds the infobars. This is the only child of the InfoBarContainer.
|
| + private LinearLayout mLinearLayout;
|
| +
|
| + // These values are used in onLayout() to keep the infobars fixed to the bottom of the screen
|
| + // when infobars are added or removed.
|
| + private int mHeight;
|
| + private int mInnerHeight;
|
| + private int mDistanceFromBottom;
|
| +
|
| + private Paint mTopBorderPaint;
|
| +
|
| public InfoBarContainer(Activity activity, AutoLoginProcessor autoLoginProcessor,
|
| int tabId, ViewGroup parentView, WebContents webContents) {
|
| super(activity);
|
| - setOrientation(LinearLayout.VERTICAL);
|
| +
|
| + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
|
| + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, Gravity.BOTTOM);
|
| + int topMarginDp = DeviceFormFactor.isTablet(activity)
|
| + ? TAB_STRIP_AND_TOOLBAR_HEIGHT_TABLET_DP
|
| + : TAB_STRIP_AND_TOOLBAR_HEIGHT_PHONE_DP;
|
| + lp.topMargin = Math.round(topMarginDp * getResources().getDisplayMetrics().density);
|
| + setLayoutParams(lp);
|
| +
|
| + mLinearLayout = new LinearLayout(activity);
|
| + mLinearLayout.setOrientation(LinearLayout.VERTICAL);
|
| + addView(mLinearLayout,
|
| + new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
| +
|
| mAnimationListener = null;
|
| mInfoBarTransitions = new ArrayDeque<InfoBarTransitionInfo>();
|
|
|
| @@ -109,13 +139,18 @@ public class InfoBarContainer extends LinearLayout {
|
| mAnimationSizer = new FrameLayout(activity);
|
| mAnimationSizer.setVisibility(INVISIBLE);
|
|
|
| - setGravity(Gravity.BOTTOM);
|
| -
|
| // Chromium's InfoBarContainer may add an InfoBar immediately during this initialization
|
| // call, so make sure everything in the InfoBarContainer is completely ready beforehand.
|
| mNativeInfoBarContainer = nativeInit(webContents, mAutoLoginDelegate);
|
| }
|
|
|
| + /**
|
| + * @return The LinearLayout that holds the infobars (i.e. the ContentWrapperViews).
|
| + */
|
| + LinearLayout getLinearLayout() {
|
| + return mLinearLayout;
|
| + }
|
| +
|
| public void setAnimationListener(InfoBarAnimationListener listener) {
|
| mAnimationListener = listener;
|
| }
|
| @@ -125,33 +160,18 @@ public class InfoBarContainer extends LinearLayout {
|
| return mAnimationListener;
|
| }
|
|
|
| - public boolean areInfoBarsOnTop() {
|
| - return false;
|
| - }
|
| -
|
| @Override
|
| public boolean onInterceptTouchEvent(MotionEvent ev) {
|
| - // Trap any attempts to fiddle with the Views while we're animating.
|
| - return mAnimation != null;
|
| - }
|
| -
|
| - @Override
|
| - public boolean onTouchEvent(MotionEvent event) {
|
| - // Consume all motion events so they do not reach the ContentView.
|
| - return true;
|
| + // Trap any attempts to fiddle with the infobars while we're animating.
|
| + return super.onInterceptTouchEvent(ev) || mAnimation != null;
|
| }
|
|
|
| private void addToParentView() {
|
| if (mParentView != null && mParentView.indexOfChild(this) == -1) {
|
| - mParentView.addView(this, createLayoutParams());
|
| + mParentView.addView(this);
|
| }
|
| }
|
|
|
| - private FrameLayout.LayoutParams createLayoutParams() {
|
| - return new FrameLayout.LayoutParams(
|
| - LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, Gravity.BOTTOM);
|
| - }
|
| -
|
| public void removeFromParentView() {
|
| if (getParent() != null) {
|
| ((ViewGroup) getParent()).removeView(this);
|
| @@ -171,24 +191,6 @@ public class InfoBarContainer extends LinearLayout {
|
| }
|
|
|
| @Override
|
| - protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
| - if (mAnimation == null || child != mAnimation.getTarget()) {
|
| - return super.drawChild(canvas, child, drawingTime);
|
| - }
|
| - // When infobars are on top, the new infobar Z-order is greater than the previous infobar,
|
| - // which means it shows on top during the animation. We cannot change the Z-order in the
|
| - // linear layout, it is driven by the insertion index.
|
| - // So we simply clip the children to their bounds to make sure the new infobar does not
|
| - // paint over.
|
| - boolean retVal;
|
| - canvas.save();
|
| - canvas.clipRect(mAnimation.getTarget().getClippingRect());
|
| - retVal = super.drawChild(canvas, child, drawingTime);
|
| - canvas.restore();
|
| - return retVal;
|
| - }
|
| -
|
| - @Override
|
| protected void onAttachedToWindow() {
|
| super.onAttachedToWindow();
|
| ObjectAnimator.ofFloat(this, "alpha", 0.f, 1.f).setDuration(REATTACH_FADE_IN_MS).start();
|
| @@ -321,6 +323,42 @@ public class InfoBarContainer extends LinearLayout {
|
| }
|
| }
|
| super.onLayout(changed, l, t, r, b);
|
| +
|
| + // Keep the infobars fixed to the bottom of the screen when infobars are added or removed.
|
| + // Otherwise, infobars jump around when appearing or disappearing on small devices.
|
| + int newHeight = getHeight();
|
| + int newInnerHeight = mLinearLayout.getHeight();
|
| + if (mInnerHeight != newInnerHeight) {
|
| + int newScrollY = newInnerHeight - newHeight - mDistanceFromBottom;
|
| + scrollTo(0, newScrollY);
|
| + }
|
| + mHeight = newHeight;
|
| + mInnerHeight = newInnerHeight;
|
| + mDistanceFromBottom = mInnerHeight - mHeight - getScrollY();
|
| + }
|
| +
|
| + @Override
|
| + protected void onScrollChanged(int l, int t, int oldl, int oldt) {
|
| + super.onScrollChanged(l, t, oldl, oldt);
|
| + mDistanceFromBottom = mInnerHeight - mHeight - getScrollY();
|
| + }
|
| +
|
| + @Override
|
| + protected void dispatchDraw(Canvas canvas) {
|
| + super.dispatchDraw(canvas);
|
| +
|
| + // If the infobars overflow the ScrollView, draw a border at the top of the ScrollView.
|
| + // This prevents the topmost infobar from blending into the page when fullscreen mode
|
| + // is active.
|
| + if (getScrollY() != 0) {
|
| + if (mTopBorderPaint == null) {
|
| + mTopBorderPaint = new Paint();
|
| + mTopBorderPaint.setColor(
|
| + getResources().getColor(R.color.infobar_background_separator));
|
| + }
|
| + int height = ContentWrapperView.getBoundaryHeight(getContext());
|
| + canvas.drawRect(0, getScrollY(), getWidth(), getScrollY() + height, mTopBorderPaint);
|
| + }
|
| }
|
|
|
| /**
|
| @@ -345,7 +383,7 @@ public class InfoBarContainer extends LinearLayout {
|
| targetView = info.target.getContentWrapper(true);
|
| assert mInfoBars.contains(info.target);
|
| toShow = targetView.detachCurrentView();
|
| - addView(targetView, 0,
|
| + mLinearLayout.addView(targetView, 0,
|
| new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
|
| } else {
|
| targetView = info.target.getContentWrapper(false);
|
| @@ -380,7 +418,7 @@ public class InfoBarContainer extends LinearLayout {
|
|
|
| public void destroy() {
|
| mDestroyed = true;
|
| - removeAllViews();
|
| + mLinearLayout.removeAllViews();
|
| if (mNativeInfoBarContainer != 0) {
|
| nativeDestroy(mNativeInfoBarContainer);
|
| }
|
| @@ -426,7 +464,8 @@ public class InfoBarContainer extends LinearLayout {
|
| if (parent != null) parent.removeView(toShow);
|
|
|
| assert mAnimationSizer.getParent() == null;
|
| - mParentView.addView(mAnimationSizer, createLayoutParams());
|
| + mParentView.addView(mAnimationSizer, new FrameLayout.LayoutParams(
|
| + LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
| mAnimationSizer.addView(toShow, 0,
|
| new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
|
| mAnimationSizer.requestLayout();
|
| @@ -441,19 +480,19 @@ public class InfoBarContainer extends LinearLayout {
|
|
|
| // If the InfoBar was hidden, get rid of its View entirely.
|
| if (mAnimation.getAnimationType() == AnimationHelper.ANIMATION_TYPE_HIDE) {
|
| - removeView(mAnimation.getTarget());
|
| + mLinearLayout.removeView(mAnimation.getTarget());
|
| }
|
|
|
| // Reset all translations and put everything where they need to be.
|
| - for (int i = 0; i < getChildCount(); ++i) {
|
| - View view = getChildAt(i);
|
| + for (int i = 0; i < mLinearLayout.getChildCount(); ++i) {
|
| + View view = mLinearLayout.getChildAt(i);
|
| view.setTranslationY(0);
|
| }
|
| requestLayout();
|
|
|
| // If there are no infobars shown, there is no need to keep the infobar container in the
|
| // view hierarchy.
|
| - if (getChildCount() == 0) {
|
| + if (mLinearLayout.getChildCount() == 0) {
|
| removeFromParentView();
|
| }
|
|
|
| @@ -490,6 +529,5 @@ public class InfoBarContainer extends LinearLayout {
|
| }
|
|
|
| private native long nativeInit(WebContents webContents, AutoLoginDelegate autoLoginDelegate);
|
| -
|
| private native void nativeDestroy(long nativeInfoBarContainerAndroid);
|
| }
|
|
|