Fix some issues with the action bar and action modes.

Fix bug 4976004 - bad title measurement for split action modes

Fix bug 4902960 - action modes leaving a hidden action bar in a bad state

Sync with design for the behavior of various permutations of action
bar configuration + modes.

Change-Id: Id75f6b5911b761fabc5fef2cc2600ce197cf9a92
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 8d5df6f..519acf5 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.app;
 
-import com.android.internal.R;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.view.menu.MenuPopupHelper;
 import com.android.internal.view.menu.SubMenuBuilder;
@@ -36,7 +35,6 @@
 import android.app.FragmentTransaction;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.view.ActionMode;
@@ -580,6 +578,9 @@
 
         mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
         mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE);
+        if (mTabScrollView != null && !mActionView.hasEmbeddedTabs() && mActionView.isCollapsed()) {
+            mTabScrollView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
+        }
     }
 
     /**
@@ -620,6 +621,7 @@
 
             // Clear out the context mode views after the animation finishes
             mContextView.closeMode();
+
             mActionMode = null;
 
             if (mWasHiddenBeforeMode) {
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index d710cfa..953328c 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -105,24 +105,19 @@
     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
-        int nonTabHeight = 0;
-        final int count = getChildCount();
-        for (int i = 0; i < count; i++) {
-            final View child = getChildAt(i);
+        if (mActionBarView == null) return;
 
-            if (child == mTabContainer) continue;
-
-            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-            nonTabHeight = Math.max(nonTabHeight,
-                    child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
-        }
+        final LayoutParams lp = (LayoutParams) mActionBarView.getLayoutParams();
+        final int actionBarViewHeight = mActionBarView.isCollapsed() ? 0 :
+                mActionBarView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
 
         if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
             final int mode = MeasureSpec.getMode(heightMeasureSpec);
             if (mode == MeasureSpec.AT_MOST) {
                 final int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
                 setMeasuredDimension(getMeasuredWidth(),
-                        Math.min(nonTabHeight + mTabContainer.getMeasuredHeight(), maxHeight));
+                        Math.min(actionBarViewHeight + mTabContainer.getMeasuredHeight(),
+                                maxHeight));
             }
         }
     }
@@ -137,12 +132,14 @@
             if ((mActionBarView.getDisplayOptions() & ActionBar.DISPLAY_SHOW_HOME) == 0) {
                 // Not showing home, put tabs on top.
                 final int count = getChildCount();
-                for (int i = 0; i < count; i++){
+                for (int i = 0; i < count; i++) {
                     final View child = getChildAt(i);
 
                     if (child == mTabContainer) continue;
 
-                    child.offsetTopAndBottom(tabHeight);
+                    if (!mActionBarView.isCollapsed()) {
+                        child.offsetTopAndBottom(tabHeight);
+                    }
                 }
                 mTabContainer.layout(l, 0, r, tabHeight);
             } else {
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index fc43994..3e3eeab 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -287,7 +287,7 @@
             availableWidth = measureChildView(mClose, availableWidth, childSpecHeight, 0);
         }
 
-        if (mMenuView != null) {
+        if (mMenuView != null && mMenuView.getParent() == this) {
             availableWidth = measureChildView(mMenuView, availableWidth,
                     childSpecHeight, 0);
         }
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 8eb046e..09bc1fc 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -117,6 +117,7 @@
     private boolean mUserTitle;
     private boolean mIncludeTabs;
     private boolean mIsCollapsable;
+    private boolean mIsCollapsed;
 
     private MenuBuilder mOptionsMenu;
     
@@ -692,6 +693,10 @@
         mIsCollapsable = collapsable;
     }
 
+    public boolean isCollapsed() {
+        return mIsCollapsed;
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int childCount = getChildCount();
@@ -708,9 +713,11 @@
             if (visibleChildren == 0) {
                 // No size for an empty action bar when collapsable.
                 setMeasuredDimension(0, 0);
+                mIsCollapsed = true;
                 return;
             }
         }
+        mIsCollapsed = false;
 
         int widthMode = MeasureSpec.getMode(widthMeasureSpec);
         if (widthMode != MeasureSpec.EXACTLY) {
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 5b4d7ab..2f7adf0 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -15,6 +15,9 @@
  */
 package com.android.internal.widget;
 
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
 import android.app.ActionBar;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
@@ -22,6 +25,7 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
 import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -35,6 +39,13 @@
 
     int mMaxTabWidth;
 
+    protected Animator mVisibilityAnim;
+    protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener();
+
+    private static final TimeInterpolator sAlphaInterpolator = new DecelerateInterpolator();
+
+    private static final int FADE_DURATION = 200;
+
     public ScrollingTabContainerView(Context context) {
         super(context);
         setHorizontalScrollBarEnabled(false);
@@ -76,6 +87,30 @@
         }
     }
 
+    public void animateToVisibility(int visibility) {
+        if (mVisibilityAnim != null) {
+            mVisibilityAnim.cancel();
+        }
+        if (visibility == VISIBLE) {
+            if (getVisibility() != VISIBLE) {
+                setAlpha(0);
+            }
+            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
+            anim.setDuration(FADE_DURATION);
+            anim.setInterpolator(sAlphaInterpolator);
+
+            anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
+            anim.start();
+        } else {
+            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
+            anim.setDuration(FADE_DURATION);
+            anim.setInterpolator(sAlphaInterpolator);
+
+            anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
+            anim.start();
+        }
+    }
+
     public void animateToTab(int position) {
         final View tabView = mTabLayout.getChildAt(position);
         if (mTabSelector != null) {
@@ -259,4 +294,38 @@
             }
         }
     }
+
+    protected class VisibilityAnimListener implements Animator.AnimatorListener {
+        private boolean mCanceled = false;
+        private int mFinalVisibility;
+
+        public VisibilityAnimListener withFinalVisibility(int visibility) {
+            mFinalVisibility = visibility;
+            return this;
+        }
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+            setVisibility(VISIBLE);
+            mVisibilityAnim = animation;
+            mCanceled = false;
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            if (mCanceled) return;
+
+            mVisibilityAnim = null;
+            setVisibility(mFinalVisibility);
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            mCanceled = true;
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+        }
+    }
 }