Add dynamically scrolling underline to view pager tabs.

- Implementation is lifted and simplified from Play Store's
implementation of PlayTabContainer and PlayTabStrip (see links
in bug)
- Replace mChild in ViewPagerTabs with the TabStrip.
- Add new transparent background (with ripple) for tabs.
- Restyle tab thickness (to 2dp) and color (to yellow) accent..

Bug: 15167378
Change-Id: I50136294a7210ead67553a82916fd09d52077860
diff --git a/res/drawable/view_pager_tab_background.xml b/res/drawable/view_pager_tab_background.xml
new file mode 100644
index 0000000..7dae671
--- /dev/null
+++ b/res/drawable/view_pager_tab_background.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:tint="@color/tab_ripple_color">
+    <item>
+        <selector>
+            <item android:state_focused="true"
+                android:drawable="@drawable/tab_unselected_focused" />
+        </selector>
+    </item>
+</ripple>
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index c79f4cf..8bba479 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -100,6 +100,8 @@
     <!-- Color for icons in the actionbar -->
     <color name="actionbar_icon_color">#ffffff</color>
 
-    <!-- 10% opacity, theme color. -->
     <color name="dialer_dialpad_touch_tint">#1a1dc7db</color>
+
+    <color name="tab_ripple_color">@color/dialer_accent_color</color>
+    <color name="tab_selected_underline_color">@color/dialer_accent_color</color>
 </resources>
diff --git a/src/com/android/dialer/list/ViewPagerTabStrip.java b/src/com/android/dialer/list/ViewPagerTabStrip.java
new file mode 100644
index 0000000..ac16694
--- /dev/null
+++ b/src/com/android/dialer/list/ViewPagerTabStrip.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2014 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.dialer.list;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.android.dialer.R;
+
+public class ViewPagerTabStrip extends LinearLayout {
+    private int mSelectedUnderlineThickness;
+    private final Paint mSelectedUnderlinePaint;
+
+    private int mIndexForSelection;
+    private float mSelectionOffset;
+
+    public ViewPagerTabStrip(Context context) {
+        this(context, null);
+    }
+
+    public ViewPagerTabStrip(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        final Resources res = context.getResources();
+
+        mSelectedUnderlineThickness =
+                res.getDimensionPixelSize(R.dimen.tab_selected_underline_height);
+        int underlineColor = res.getColor(R.color.tab_selected_underline_color);
+        int backgroundColor = res.getColor(R.color.actionbar_background_color);
+
+        mSelectedUnderlinePaint = new Paint();
+        mSelectedUnderlinePaint.setColor(underlineColor);
+
+        setBackgroundColor(backgroundColor);
+        setWillNotDraw(false);
+    }
+
+    /**
+     * Notifies this view that view pager has been scrolled. We save the tab index
+     * and selection offset for interpolating the position and width of selection
+     * underline.
+     */
+    void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+        mIndexForSelection = position;
+        mSelectionOffset = positionOffset;
+        invalidate();
+    }
+
+    /**
+     * Notifies this view that a new page has been selected in the view pager. We save the tab
+     * index and reset the selection offset to 0.
+     */
+    void onPageSelected(int position) {
+        mIndexForSelection = position;
+        mSelectionOffset = 0;
+        invalidate();
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        int childCount = getChildCount();
+
+        // Thick colored underline below the current selection
+        if (childCount > 0) {
+            View selectedTitle = getChildAt(mIndexForSelection);
+            int selectedLeft = selectedTitle.getLeft();
+            int selectedRight = selectedTitle.getRight();
+            if ((mSelectionOffset > 0.0f) &&
+                    (mIndexForSelection < (getChildCount() - 1))) {
+                // Draw the selection partway between the tabs
+                View nextTitle = getChildAt(mIndexForSelection + 1);
+                int nextLeft = nextTitle.getLeft();
+                int nextRight = nextTitle.getRight();
+
+                selectedLeft = (int) (mSelectionOffset * nextLeft +
+                        (1.0f - mSelectionOffset) * selectedLeft);
+                selectedRight = (int) (mSelectionOffset * nextRight +
+                        (1.0f - mSelectionOffset) * selectedRight);
+            }
+
+            int height = getHeight();
+            canvas.drawRect(selectedLeft, height - mSelectedUnderlineThickness,
+                    selectedRight, height, mSelectedUnderlinePaint);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/dialer/list/ViewPagerTabs.java b/src/com/android/dialer/list/ViewPagerTabs.java
index b545802..c95a80b 100644
--- a/src/com/android/dialer/list/ViewPagerTabs.java
+++ b/src/com/android/dialer/list/ViewPagerTabs.java
@@ -26,11 +26,12 @@
 public class ViewPagerTabs extends HorizontalScrollView implements ViewPager.OnPageChangeListener {
 
     ViewPager mPager;
+    private ViewPagerTabStrip mTabStrip;
+
     /**
      * Linearlayout that will contain the TextViews serving as tabs. This is the only child
      * of the parent HorizontalScrollView.
      */
-    LinearLayout mChild;
     final int mTextStyle;
     final ColorStateList mTextColor;
     final int mTextSize;
@@ -100,8 +101,8 @@
         mTextColor = a.getColorStateList(2);
         mTextAllCaps = a.getBoolean(3, false);
 
-        mChild = new LinearLayout(context);
-        addView(mChild,
+        mTabStrip = new ViewPagerTabStrip(context);
+        addView(mTabStrip,
                 new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
         a.recycle();
     }
@@ -112,7 +113,7 @@
     }
 
     private void addTabs(PagerAdapter adapter) {
-        mChild.removeAllViews();
+        mTabStrip.removeAllViews();
 
         final int count = adapter.getCount();
         for (int i = 0; i < count; i++) {
@@ -123,7 +124,7 @@
     private void addTab(CharSequence tabTitle, final int position) {
         final TextView textView = new TextView(getContext());
         textView.setText(tabTitle);
-        textView.setBackgroundResource(R.drawable.action_bar_tab);
+        textView.setBackgroundResource(R.drawable.view_pager_tab_background);
         textView.setGravity(Gravity.CENTER);
         textView.setOnClickListener(new OnClickListener() {
             @Override
@@ -146,7 +147,7 @@
         }
         textView.setAllCaps(mTextAllCaps);
         textView.setPadding(mSidePadding, 0, mSidePadding, 0);
-        mChild.addView(textView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
+        mTabStrip.addView(textView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
                 LayoutParams.MATCH_PARENT, 1));
         // Default to the first child being selected
         if (position == 0) {
@@ -157,15 +158,23 @@
 
     @Override
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+        int tabStripChildCount = mTabStrip.getChildCount();
+        if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
+            return;
+        }
+
+        mTabStrip.onPageScrolled(position, positionOffset, positionOffsetPixels);
+        smoothScrollTo(position, 0);
     }
 
     @Override
     public void onPageSelected(int position) {
         if (mPrevSelected >= 0) {
-            mChild.getChildAt(mPrevSelected).setSelected(false);
+            mTabStrip.getChildAt(mPrevSelected).setSelected(false);
         }
-        final View selectedChild = mChild.getChildAt(position);
+        final View selectedChild = mTabStrip.getChildAt(position);
         selectedChild.setSelected(true);
+
         // Update scroll position
         final int scrollPos = selectedChild.getLeft() - (getWidth() - selectedChild.getWidth()) / 2;
         smoothScrollTo(scrollPos, 0);
@@ -176,3 +185,4 @@
     public void onPageScrollStateChanged(int state) {
     }
 }
+