From 7d164bbbe5f93dc3447c1d7931aea97f092677ad Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Thu, 29 May 2014 17:55:49 -0700 Subject: 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 --- res/drawable/view_pager_tab_background.xml | 25 +++++ res/values/colors.xml | 4 +- src/com/android/dialer/list/ViewPagerTabStrip.java | 105 +++++++++++++++++++++ src/com/android/dialer/list/ViewPagerTabs.java | 26 +++-- 4 files changed, 151 insertions(+), 9 deletions(-) create mode 100644 res/drawable/view_pager_tab_background.xml create mode 100644 src/com/android/dialer/list/ViewPagerTabStrip.java diff --git a/res/drawable/view_pager_tab_background.xml b/res/drawable/view_pager_tab_background.xml new file mode 100644 index 000000000..7dae671ad --- /dev/null +++ b/res/drawable/view_pager_tab_background.xml @@ -0,0 +1,25 @@ + + + + + + + + + \ No newline at end of file diff --git a/res/values/colors.xml b/res/values/colors.xml index c79f4cff4..8bba479c7 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -100,6 +100,8 @@ #ffffff - #1a1dc7db + + @color/dialer_accent_color + @color/dialer_accent_color diff --git a/src/com/android/dialer/list/ViewPagerTabStrip.java b/src/com/android/dialer/list/ViewPagerTabStrip.java new file mode 100644 index 000000000..ac16694b3 --- /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 b54580249..c95a80bda 100644 --- a/src/com/android/dialer/list/ViewPagerTabs.java +++ b/src/com/android/dialer/list/ViewPagerTabs.java @@ -26,11 +26,12 @@ import com.android.dialer.R; 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 @@ public class ViewPagerTabs extends HorizontalScrollView implements ViewPager.OnP 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 @@ public class ViewPagerTabs extends HorizontalScrollView implements ViewPager.OnP } 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 @@ public class ViewPagerTabs extends HorizontalScrollView implements ViewPager.OnP 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 @@ public class ViewPagerTabs extends HorizontalScrollView implements ViewPager.OnP } 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 @@ public class ViewPagerTabs extends HorizontalScrollView implements ViewPager.OnP @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 class ViewPagerTabs extends HorizontalScrollView implements ViewPager.OnP public void onPageScrollStateChanged(int state) { } } + -- cgit v1.2.3