Add alpha layer to tab carousel on contact card

- Introduce CarouselTab class to handle the
alpha layer and touch interceptor
- Clicking anywhere on the tab will select that
tab
- Remove split style action bar on contact card
so favorites star will be in upper right corner

Bug: 5081735
Bug: 5042660

Change-Id: I54088b49c928297dbfc523752258ceaa97cce445
diff --git a/res/layout/carousel_about_tab.xml b/res/layout/carousel_about_tab.xml
index dfcf0da..e902c8e 100644
--- a/res/layout/carousel_about_tab.xml
+++ b/res/layout/carousel_about_tab.xml
@@ -14,8 +14,9 @@
      limitations under the License.
 -->
 
-<RelativeLayout
+<view
     xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.contacts.detail.CarouselTab"
     android:layout_width="0dip"
     android:layout_height="match_parent"
     android:layout_weight="1"
@@ -51,4 +52,22 @@
         android:textColor="@color/detail_tab_carousel_tab_label_color"
         style="@android:style/Widget.Holo.ActionBar.TabView" />
 
-</RelativeLayout>
+    <View
+        android:id="@+id/alpha_overlay"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentTop="true"
+        android:background="@android:color/black"
+        android:alpha="0"
+        android:visibility="gone"/>
+
+    <View
+        android:id="@+id/touch_intercept_overlay"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentTop="true"
+        android:background="?android:attr/selectableItemBackground"
+        android:visibility="gone"/>
+</view>
diff --git a/res/layout/carousel_updates_tab.xml b/res/layout/carousel_updates_tab.xml
index b036523..689e17b 100644
--- a/res/layout/carousel_updates_tab.xml
+++ b/res/layout/carousel_updates_tab.xml
@@ -14,8 +14,13 @@
      limitations under the License.
 -->
 
-<RelativeLayout
+<!--
+  TODO: Collapse carousel_about_tab with carousel_updates_tab into 1 XML that
+  handles all cases when updates fragment is more finalized.
+-->
+<view
     xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.contacts.detail.CarouselTab"
     android:layout_width="0dip"
     android:layout_height="match_parent"
     android:layout_weight="1"
@@ -68,4 +73,23 @@
         android:textStyle="bold"
         android:maxLines="3"/>
 
-</RelativeLayout>
+    <View
+        android:id="@+id/alpha_overlay"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentTop="true"
+        android:background="@android:color/black"
+        android:alpha="0"
+        android:visibility="gone"/>
+
+    <View
+        android:id="@+id/touch_intercept_overlay"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentTop="true"
+        android:background="?android:attr/selectableItemBackground"
+        android:visibility="gone"/>
+
+</view>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index e98175d..c23d99d 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -73,7 +73,7 @@
         <item name="call_log_voicemail_status_text_color">#000000</item>
     </style>
 
-    <style name="ContactDetailActivityTheme" parent="@android:style/Theme.Holo.Light.SolidActionBar.Inverse.SplitActionBarWhenNarrow">
+    <style name="ContactDetailActivityTheme" parent="@android:style/Theme.Holo.Light.SolidActionBar.Inverse">
         <item name="android:actionBarStyle">@style/ContactsActionBarStyle</item>
         <item name="android:windowContentOverlay">@null</item>
     </style>
diff --git a/src/com/android/contacts/detail/CarouselTab.java b/src/com/android/contacts/detail/CarouselTab.java
new file mode 100644
index 0000000..9b8efd5
--- /dev/null
+++ b/src/com/android/contacts/detail/CarouselTab.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.detail;
+
+import com.android.contacts.R;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+/**
+ * This is a tab in the {@link ContactDetailTabCarousel}.
+ */
+public class CarouselTab extends RelativeLayout implements ViewOverlay {
+
+    private static final String TAG = CarouselTab.class.getSimpleName();
+
+    private TextView mLabelView;
+
+    /**
+     * This view adds an alpha layer over the entire tab.
+     */
+    private View mAlphaLayer;
+
+    /**
+     * This view adds a layer over the entire tab so that when visible, it intercepts all touch
+     * events on the tab.
+     */
+    private View mTouchInterceptLayer;
+
+    public CarouselTab(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mLabelView = (TextView) findViewById(R.id.label);
+        mLabelView.setClickable(true);
+
+        mAlphaLayer = findViewById(R.id.alpha_overlay);
+        mTouchInterceptLayer = findViewById(R.id.touch_intercept_overlay);
+    }
+
+    public void setLabel(String label) {
+        mLabelView.setText(label);
+    }
+
+    public void showSelectedState() {
+        mLabelView.setSelected(true);
+    }
+
+    public void showDeselectedState() {
+        mLabelView.setSelected(false);
+    }
+
+    @Override
+    public void disableTouchInterceptor() {
+        // This shouldn't be called because there is no need to disable the touch interceptor if
+        // there is no content within the tab that needs to be clicked.
+    }
+
+    @Override
+    public void enableAlphaLayer() {
+        if (mAlphaLayer != null) {
+            mAlphaLayer.setVisibility(View.VISIBLE);
+        }
+    }
+
+    @Override
+    public void enableTouchInterceptor(OnClickListener clickListener) {
+        if (mTouchInterceptLayer != null) {
+            mTouchInterceptLayer.setVisibility(View.VISIBLE);
+            mTouchInterceptLayer.setOnClickListener(clickListener);
+        }
+    }
+
+    @Override
+    public void setAlphaLayerValue(float alpha) {
+        if (mAlphaLayer != null) {
+            mAlphaLayer.setAlpha(alpha);
+        }
+    }
+}
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 1dae19f..41324f8 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -116,7 +116,7 @@
 import java.util.List;
 import java.util.Map;
 
-public class ContactDetailFragment extends Fragment implements FragmentKeyListener, FragmentOverlay,
+public class ContactDetailFragment extends Fragment implements FragmentKeyListener, ViewOverlay,
         OnItemClickListener, SelectAccountDialogFragment.Listener {
 
     private static final String TAG = "ContactDetailFragment";
diff --git a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
index da64c34..95cf055 100644
--- a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
@@ -46,8 +46,8 @@
     private int mCurrentPage = ABOUT_PAGE;
     private int mLastScrollPosition;
 
-    private FragmentOverlay mAboutFragment;
-    private FragmentOverlay mUpdatesFragment;
+    private ViewOverlay mAboutFragment;
+    private ViewOverlay mUpdatesFragment;
 
     private static final float MAX_ALPHA = 0.5f;
 
@@ -69,7 +69,7 @@
         setOnTouchListener(this);
     }
 
-    public void setAboutFragment(FragmentOverlay fragment) {
+    public void setAboutFragment(ViewOverlay fragment) {
         // TODO: We can't always assume the "about" page will be the current page.
         mAboutFragment = fragment;
         mAboutFragment.enableAlphaLayer();
@@ -77,7 +77,7 @@
         mAboutFragment.disableTouchInterceptor();
     }
 
-    public void setUpdatesFragment(FragmentOverlay fragment) {
+    public void setUpdatesFragment(ViewOverlay fragment) {
         mUpdatesFragment = fragment;
         mUpdatesFragment.enableAlphaLayer();
         mUpdatesFragment.setAlphaLayerValue(MAX_ALPHA);
diff --git a/src/com/android/contacts/detail/ContactDetailTabCarousel.java b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
index 26987f6..79ac5fb 100644
--- a/src/com/android/contacts/detail/ContactDetailTabCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
@@ -24,6 +24,7 @@
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.View.OnTouchListener;
 import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
@@ -49,15 +50,22 @@
 
     private Listener mListener;
 
-    private final View[] mTabs = new View[TAB_COUNT];
+    private int mCurrentTab = TAB_INDEX_ABOUT;
+
+    private CarouselTab mAboutTab;
+    private CarouselTab mUpdatesTab;
 
     private int mTabWidth;
     private int mTabHeight;
     private int mTabDisplayLabelHeight;
 
+    private int mLastScrollPosition;
+
     private int mAllowedHorizontalScrollLength = Integer.MIN_VALUE;
     private int mAllowedVerticalScrollLength = Integer.MIN_VALUE;
 
+    private static final float MAX_ALPHA = 0.5f;
+
     /**
      * Interface for callbacks invoked when the user interacts with the carousel.
      */
@@ -83,40 +91,28 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        View aboutView = findViewById(R.id.tab_about);
-        View updateView = findViewById(R.id.tab_update);
+        mAboutTab = (CarouselTab) findViewById(R.id.tab_about);
+        mAboutTab.setLabel(mContext.getString(R.string.contactDetailAbout));
 
-        TextView aboutTab = (TextView) aboutView.findViewById(R.id.label);
-        aboutTab.setText(mContext.getString(R.string.contactDetailAbout));
-        aboutTab.setClickable(true);
-        aboutTab.setSelected(true);
+        mUpdatesTab = (CarouselTab) findViewById(R.id.tab_update);
+        mUpdatesTab.setLabel(mContext.getString(R.string.contactDetailUpdates));
 
-        TextView updatesTab = (TextView) updateView.findViewById(R.id.label);
-        updatesTab.setText(mContext.getString(R.string.contactDetailUpdates));
-        updatesTab.setClickable(true);
+        // TODO: We can't always assume the "about" page will be the current page.
+        mAboutTab.showSelectedState();
+        mAboutTab.enableAlphaLayer();
+        mAboutTab.setAlphaLayerValue(0);
+        mAboutTab.enableTouchInterceptor(mAboutTabTouchInterceptListener);
 
-        aboutTab.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                mListener.onTabSelected(TAB_INDEX_ABOUT);
-            }
-        });
-        updatesTab.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                mListener.onTabSelected(TAB_INDEX_ABOUT);
-            }
-        });
-
-        mTabs[TAB_INDEX_ABOUT] = aboutTab;
-        mTabs[TAB_INDEX_UPDATES] = updatesTab;
+        mUpdatesTab.enableAlphaLayer();
+        mUpdatesTab.setAlphaLayerValue(MAX_ALPHA);
+        mUpdatesTab.enableTouchInterceptor(mUpdatesTabTouchInterceptListener);
 
         // Retrieve the photo view for the "about" tab
-        mPhotoView = (ImageView) aboutView.findViewById(R.id.photo);
+        mPhotoView = (ImageView) mAboutTab.findViewById(R.id.photo);
 
         // Retrieve the social update views for the "updates" tab
-        mStatusView = (TextView) updateView.findViewById(R.id.status);
-        mStatusPhotoView = (ImageView) updateView.findViewById(R.id.status_photo);
+        mStatusView = (TextView) mUpdatesTab.findViewById(R.id.status);
+        mStatusPhotoView = (ImageView) mUpdatesTab.findViewById(R.id.status_photo);
     }
 
     @Override
@@ -143,10 +139,33 @@
         }
     }
 
+    private final OnClickListener mAboutTabTouchInterceptListener = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            mListener.onTabSelected(TAB_INDEX_ABOUT);
+        }
+    };
+
+    private final OnClickListener mUpdatesTabTouchInterceptListener = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            mListener.onTabSelected(TAB_INDEX_UPDATES);
+        }
+    };
+
+    private void updateAlphaLayers() {
+        mAboutTab.setAlphaLayerValue(mLastScrollPosition * MAX_ALPHA /
+                mAllowedHorizontalScrollLength);
+        mUpdatesTab.setAlphaLayerValue(MAX_ALPHA - mLastScrollPosition * MAX_ALPHA /
+                mAllowedVerticalScrollLength);
+    }
+
     @Override
     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
         super.onScrollChanged(l, t, oldl, oldt);
         mListener.onScrollChanged(l, t, oldl, oldt);
+        mLastScrollPosition = l;
+        updateAlphaLayers();
     }
 
     /**
@@ -168,24 +187,21 @@
      * Updates the tab selection.
      */
     public void setCurrentTab(int position) {
-        if (position < 0 || position > mTabs.length) {
-            throw new IllegalStateException("Invalid position in array of tabs: " + position);
-        }
         // TODO: Handle device rotation (saving and restoring state of the selected tab)
         // This will take more work because there is no tab carousel in phone landscape
-        if (mTabs[position] == null) {
-            return;
+        switch (position) {
+            case TAB_INDEX_ABOUT:
+                mAboutTab.showSelectedState();
+                mUpdatesTab.showDeselectedState();
+                break;
+            case TAB_INDEX_UPDATES:
+                mUpdatesTab.showSelectedState();
+                mAboutTab.showDeselectedState();
+                break;
+            default:
+                throw new IllegalStateException("Invalid tab position " + position);
         }
-        mTabs[position].setSelected(true);
-        unselectAllOtherTabs(position);
-    }
-
-    private void unselectAllOtherTabs(int position) {
-        for (int i = 0; i < mTabs.length; i++) {
-            if (position != i) {
-                mTabs[i].setSelected(false);
-            }
-        }
+        mCurrentTab = position;
     }
 
     /**
@@ -197,6 +213,8 @@
             return;
         }
 
+        // TODO: Move this into the {@link CarouselTab} class when the updates fragment code is more
+        // finalized
         ContactDetailDisplayUtils.setPhoto(mContext, contactData, mPhotoView);
         ContactDetailDisplayUtils.setSocialSnippet(mContext, contactData, mStatusView,
                 mStatusPhotoView);
diff --git a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
index daeae00..602958d 100644
--- a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
@@ -31,7 +31,7 @@
 import android.widget.TextView;
 
 public class ContactDetailUpdatesFragment extends Fragment
-        implements FragmentKeyListener, FragmentOverlay {
+        implements FragmentKeyListener, ViewOverlay {
 
     private static final String TAG = "ContactDetailUpdatesFragment";
 
diff --git a/src/com/android/contacts/detail/FragmentOverlay.java b/src/com/android/contacts/detail/ViewOverlay.java
similarity index 88%
rename from src/com/android/contacts/detail/FragmentOverlay.java
rename to src/com/android/contacts/detail/ViewOverlay.java
index 6ef0846..4c14460 100644
--- a/src/com/android/contacts/detail/FragmentOverlay.java
+++ b/src/com/android/contacts/detail/ViewOverlay.java
@@ -19,12 +19,12 @@
 import android.view.View.OnClickListener;
 
 /**
- * This is implemented by {@link Fragment}s that contain an alpha layer and touch interceptor layer.
+ * This is implemented by {@link View}s that contain an alpha layer and touch interceptor layer.
  * The alpha layer covers the entire fragment and has an alpha value which makes the fragment
  * contents appear "dimmed" out. The touch interceptor layer covers the entire fragment so that
- * when visible, it intercepts all touch events on the {@link Fragment}.
+ * when visible, it intercepts all touch events on the {@link View}.
  */
-public interface FragmentOverlay {
+public interface ViewOverlay {
 
     /**
      * Sets the alpha value on the alpha layer (if there is one).