diff --git a/demo/src/main/java/com/ogaclejapan/smarttablayout/demo/DemoActivity.java b/demo/src/main/java/com/ogaclejapan/smarttablayout/demo/DemoActivity.java index 4fd2f32..0403995 100755 --- a/demo/src/main/java/com/ogaclejapan/smarttablayout/demo/DemoActivity.java +++ b/demo/src/main/java/com/ogaclejapan/smarttablayout/demo/DemoActivity.java @@ -2,6 +2,7 @@ import android.content.Context; import android.content.Intent; +import android.graphics.Color; import android.os.Bundle; import android.view.LayoutInflater; import android.view.ViewGroup; @@ -17,47 +18,50 @@ public class DemoActivity extends AppCompatActivity { - private static final String KEY_DEMO = "demo"; + private static final String KEY_DEMO = "demo"; - public static void startActivity(Context context, Demo demo) { - Intent intent = new Intent(context, DemoActivity.class); - intent.putExtra(KEY_DEMO, demo.name()); - context.startActivity(intent); - } + public static void startActivity(Context context, Demo demo) { + Intent intent = new Intent(context, DemoActivity.class); + intent.putExtra(KEY_DEMO, demo.name()); + context.startActivity(intent); + } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_demo); + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo); - Demo demo = getDemo(); + Demo demo = getDemo(); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - toolbar.setTitle(demo.titleResId); - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + toolbar.setTitle(demo.titleResId); + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); - ViewGroup tab = (ViewGroup) findViewById(R.id.tab); - tab.addView(LayoutInflater.from(this).inflate(demo.layoutResId, tab, false)); + ViewGroup tab = (ViewGroup) findViewById(R.id.tab); + tab.addView(LayoutInflater.from(this).inflate(demo.layoutResId, tab, false)); - ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager); - SmartTabLayout viewPagerTab = (SmartTabLayout) findViewById(R.id.viewpagertab); - demo.setup(viewPagerTab); + ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager); + SmartTabLayout viewPagerTab = (SmartTabLayout) findViewById(R.id.viewpagertab); + demo.setup(viewPagerTab); - FragmentPagerItems pages = new FragmentPagerItems(this); - for (int titleResId : demo.tabs()) { - pages.add(FragmentPagerItem.of(getString(titleResId), DemoFragment.class)); - } + // Sample Usage for setGradientIndicator +// viewPagerTab.setGradientIndicator(Color.rgb(243, 22, 42), Color.rgb(10, 32, 210)); - FragmentPagerItemAdapter adapter = new FragmentPagerItemAdapter( - getSupportFragmentManager(), pages); + FragmentPagerItems pages = new FragmentPagerItems(this); + for (int titleResId : demo.tabs()) { + pages.add(FragmentPagerItem.of(getString(titleResId), DemoFragment.class)); + } - viewPager.setAdapter(adapter); - viewPagerTab.setViewPager(viewPager); + FragmentPagerItemAdapter adapter = new FragmentPagerItemAdapter( + getSupportFragmentManager(), pages); - } + viewPager.setAdapter(adapter); + viewPagerTab.setViewPager(viewPager); - private Demo getDemo() { - return Demo.valueOf(getIntent().getStringExtra(KEY_DEMO)); - } + } + + private Demo getDemo() { + return Demo.valueOf(getIntent().getStringExtra(KEY_DEMO)); + } } diff --git a/library/src/main/java/com/ogaclejapan/smarttablayout/SmartTabLayout.java b/library/src/main/java/com/ogaclejapan/smarttablayout/SmartTabLayout.java index 994733c..e628f20 100755 --- a/library/src/main/java/com/ogaclejapan/smarttablayout/SmartTabLayout.java +++ b/library/src/main/java/com/ogaclejapan/smarttablayout/SmartTabLayout.java @@ -1,13 +1,13 @@ /** * Copyright (C) 2015 ogaclejapan * Copyright (C) 2013 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. @@ -61,593 +61,606 @@ */ public class SmartTabLayout extends HorizontalScrollView { - private static final boolean DEFAULT_DISTRIBUTE_EVENLY = false; - private static final int TITLE_OFFSET_DIPS = 24; - private static final int TITLE_OFFSET_AUTO_CENTER = -1; - private static final int TAB_VIEW_PADDING_DIPS = 16; - private static final boolean TAB_VIEW_TEXT_ALL_CAPS = true; - private static final int TAB_VIEW_TEXT_SIZE_SP = 12; - private static final int TAB_VIEW_TEXT_COLOR = 0xFC000000; - private static final int TAB_VIEW_TEXT_MIN_WIDTH = 0; - private static final boolean TAB_CLICKABLE = true; - - protected final SmartTabStrip tabStrip; - private int titleOffset; - private int tabViewBackgroundResId; - private boolean tabViewTextAllCaps; - private ColorStateList tabViewTextColors; - private float tabViewTextSize; - private int tabViewTextHorizontalPadding; - private int tabViewTextMinWidth; - private ViewPager viewPager; - private ViewPager.OnPageChangeListener viewPagerPageChangeListener; - private OnScrollChangeListener onScrollChangeListener; - private TabProvider tabProvider; - private InternalTabClickListener internalTabClickListener; - private OnTabClickListener onTabClickListener; - private boolean distributeEvenly; - - public SmartTabLayout(Context context) { - this(context, null); - } - - public SmartTabLayout(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public SmartTabLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - // Disable the Scroll Bar - setHorizontalScrollBarEnabled(false); - - final DisplayMetrics dm = getResources().getDisplayMetrics(); - final float density = dm.density; - - int tabBackgroundResId = NO_ID; - boolean textAllCaps = TAB_VIEW_TEXT_ALL_CAPS; - ColorStateList textColors; - float textSize = TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP, dm); - int textHorizontalPadding = (int) (TAB_VIEW_PADDING_DIPS * density); - int textMinWidth = (int) (TAB_VIEW_TEXT_MIN_WIDTH * density); - boolean distributeEvenly = DEFAULT_DISTRIBUTE_EVENLY; - int customTabLayoutId = NO_ID; - int customTabTextViewId = NO_ID; - boolean clickable = TAB_CLICKABLE; - int titleOffset = (int) (TITLE_OFFSET_DIPS * density); - - TypedArray a = context.obtainStyledAttributes( - attrs, R.styleable.stl_SmartTabLayout, defStyle, 0); - tabBackgroundResId = a.getResourceId( - R.styleable.stl_SmartTabLayout_stl_defaultTabBackground, tabBackgroundResId); - textAllCaps = a.getBoolean( - R.styleable.stl_SmartTabLayout_stl_defaultTabTextAllCaps, textAllCaps); - textColors = a.getColorStateList( - R.styleable.stl_SmartTabLayout_stl_defaultTabTextColor); - textSize = a.getDimension( - R.styleable.stl_SmartTabLayout_stl_defaultTabTextSize, textSize); - textHorizontalPadding = a.getDimensionPixelSize( - R.styleable.stl_SmartTabLayout_stl_defaultTabTextHorizontalPadding, textHorizontalPadding); - textMinWidth = a.getDimensionPixelSize( - R.styleable.stl_SmartTabLayout_stl_defaultTabTextMinWidth, textMinWidth); - customTabLayoutId = a.getResourceId( - R.styleable.stl_SmartTabLayout_stl_customTabTextLayoutId, customTabLayoutId); - customTabTextViewId = a.getResourceId( - R.styleable.stl_SmartTabLayout_stl_customTabTextViewId, customTabTextViewId); - distributeEvenly = a.getBoolean( - R.styleable.stl_SmartTabLayout_stl_distributeEvenly, distributeEvenly); - clickable = a.getBoolean( - R.styleable.stl_SmartTabLayout_stl_clickable, clickable); - titleOffset = a.getLayoutDimension( - R.styleable.stl_SmartTabLayout_stl_titleOffset, titleOffset); - a.recycle(); - - this.titleOffset = titleOffset; - this.tabViewBackgroundResId = tabBackgroundResId; - this.tabViewTextAllCaps = textAllCaps; - this.tabViewTextColors = (textColors != null) - ? textColors - : ColorStateList.valueOf(TAB_VIEW_TEXT_COLOR); - this.tabViewTextSize = textSize; - this.tabViewTextHorizontalPadding = textHorizontalPadding; - this.tabViewTextMinWidth = textMinWidth; - this.internalTabClickListener = clickable ? new InternalTabClickListener() : null; - this.distributeEvenly = distributeEvenly; - - if (customTabLayoutId != NO_ID) { - setCustomTabView(customTabLayoutId, customTabTextViewId); + private static final boolean DEFAULT_DISTRIBUTE_EVENLY = false; + private static final int TITLE_OFFSET_DIPS = 24; + private static final int TITLE_OFFSET_AUTO_CENTER = -1; + private static final int TAB_VIEW_PADDING_DIPS = 16; + private static final boolean TAB_VIEW_TEXT_ALL_CAPS = true; + private static final int TAB_VIEW_TEXT_SIZE_SP = 12; + private static final int TAB_VIEW_TEXT_COLOR = 0xFC000000; + private static final int TAB_VIEW_TEXT_MIN_WIDTH = 0; + private static final boolean TAB_CLICKABLE = true; + + protected final SmartTabStrip tabStrip; + private int titleOffset; + private int tabViewBackgroundResId; + private boolean tabViewTextAllCaps; + private ColorStateList tabViewTextColors; + private float tabViewTextSize; + private int tabViewTextHorizontalPadding; + private int tabViewTextMinWidth; + private ViewPager viewPager; + private ViewPager.OnPageChangeListener viewPagerPageChangeListener; + private OnScrollChangeListener onScrollChangeListener; + private TabProvider tabProvider; + private InternalTabClickListener internalTabClickListener; + private OnTabClickListener onTabClickListener; + private boolean distributeEvenly; + + public SmartTabLayout(Context context) { + this(context, null); } - this.tabStrip = new SmartTabStrip(context, attrs); - - if (distributeEvenly && tabStrip.isIndicatorAlwaysInCenter()) { - throw new UnsupportedOperationException( - "'distributeEvenly' and 'indicatorAlwaysInCenter' both use does not support"); + public SmartTabLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); } - // Make sure that the Tab Strips fills this View - setFillViewport(!tabStrip.isIndicatorAlwaysInCenter()); + public SmartTabLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + // Disable the Scroll Bar + setHorizontalScrollBarEnabled(false); + + final DisplayMetrics dm = getResources().getDisplayMetrics(); + final float density = dm.density; + + int tabBackgroundResId = NO_ID; + boolean textAllCaps = TAB_VIEW_TEXT_ALL_CAPS; + ColorStateList textColors; + float textSize = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP, dm); + int textHorizontalPadding = (int) (TAB_VIEW_PADDING_DIPS * density); + int textMinWidth = (int) (TAB_VIEW_TEXT_MIN_WIDTH * density); + boolean distributeEvenly = DEFAULT_DISTRIBUTE_EVENLY; + int customTabLayoutId = NO_ID; + int customTabTextViewId = NO_ID; + boolean clickable = TAB_CLICKABLE; + int titleOffset = (int) (TITLE_OFFSET_DIPS * density); + + TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.stl_SmartTabLayout, defStyle, 0); + tabBackgroundResId = a.getResourceId( + R.styleable.stl_SmartTabLayout_stl_defaultTabBackground, tabBackgroundResId); + textAllCaps = a.getBoolean( + R.styleable.stl_SmartTabLayout_stl_defaultTabTextAllCaps, textAllCaps); + textColors = a.getColorStateList( + R.styleable.stl_SmartTabLayout_stl_defaultTabTextColor); + textSize = a.getDimension( + R.styleable.stl_SmartTabLayout_stl_defaultTabTextSize, textSize); + textHorizontalPadding = a.getDimensionPixelSize( + R.styleable.stl_SmartTabLayout_stl_defaultTabTextHorizontalPadding, textHorizontalPadding); + textMinWidth = a.getDimensionPixelSize( + R.styleable.stl_SmartTabLayout_stl_defaultTabTextMinWidth, textMinWidth); + customTabLayoutId = a.getResourceId( + R.styleable.stl_SmartTabLayout_stl_customTabTextLayoutId, customTabLayoutId); + customTabTextViewId = a.getResourceId( + R.styleable.stl_SmartTabLayout_stl_customTabTextViewId, customTabTextViewId); + distributeEvenly = a.getBoolean( + R.styleable.stl_SmartTabLayout_stl_distributeEvenly, distributeEvenly); + clickable = a.getBoolean( + R.styleable.stl_SmartTabLayout_stl_clickable, clickable); + titleOffset = a.getLayoutDimension( + R.styleable.stl_SmartTabLayout_stl_titleOffset, titleOffset); + a.recycle(); + + this.titleOffset = titleOffset; + this.tabViewBackgroundResId = tabBackgroundResId; + this.tabViewTextAllCaps = textAllCaps; + this.tabViewTextColors = (textColors != null) + ? textColors + : ColorStateList.valueOf(TAB_VIEW_TEXT_COLOR); + this.tabViewTextSize = textSize; + this.tabViewTextHorizontalPadding = textHorizontalPadding; + this.tabViewTextMinWidth = textMinWidth; + this.internalTabClickListener = clickable ? new InternalTabClickListener() : null; + this.distributeEvenly = distributeEvenly; + + if (customTabLayoutId != NO_ID) { + setCustomTabView(customTabLayoutId, customTabTextViewId); + } + + this.tabStrip = new SmartTabStrip(context, attrs); + + if (distributeEvenly && tabStrip.isIndicatorAlwaysInCenter()) { + throw new UnsupportedOperationException( + "'distributeEvenly' and 'indicatorAlwaysInCenter' both use does not support"); + } - addView(tabStrip, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + // Make sure that the Tab Strips fills this View + setFillViewport(!tabStrip.isIndicatorAlwaysInCenter()); - } + addView(tabStrip, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - @Override - protected void onScrollChanged(int l, int t, int oldl, int oldt) { - super.onScrollChanged(l, t, oldl, oldt); - if (onScrollChangeListener != null) { - onScrollChangeListener.onScrollChanged(l, oldl); } - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - if (tabStrip.isIndicatorAlwaysInCenter() && tabStrip.getChildCount() > 0) { - View firstTab = tabStrip.getChildAt(0); - View lastTab = tabStrip.getChildAt(tabStrip.getChildCount() - 1); - int start = (w - Utils.getMeasuredWidth(firstTab)) / 2 - Utils.getMarginStart(firstTab); - int end = (w - Utils.getMeasuredWidth(lastTab)) / 2 - Utils.getMarginEnd(lastTab); - tabStrip.setMinimumWidth(tabStrip.getMeasuredWidth()); - ViewCompat.setPaddingRelative(this, start, getPaddingTop(), end, getPaddingBottom()); - setClipToPadding(false); + + @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + if (onScrollChangeListener != null) { + onScrollChangeListener.onScrollChanged(l, oldl); + } } - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - super.onLayout(changed, l, t, r, b); - // Ensure first scroll - if (changed && viewPager != null) { - scrollToTab(viewPager.getCurrentItem(), 0); + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + if (tabStrip.isIndicatorAlwaysInCenter() && tabStrip.getChildCount() > 0) { + View firstTab = tabStrip.getChildAt(0); + View lastTab = tabStrip.getChildAt(tabStrip.getChildCount() - 1); + int start = (w - Utils.getMeasuredWidth(firstTab)) / 2 - Utils.getMarginStart(firstTab); + int end = (w - Utils.getMeasuredWidth(lastTab)) / 2 - Utils.getMarginEnd(lastTab); + tabStrip.setMinimumWidth(tabStrip.getMeasuredWidth()); + ViewCompat.setPaddingRelative(this, start, getPaddingTop(), end, getPaddingBottom()); + setClipToPadding(false); + } } - } - - /** - * Set the behavior of the Indicator scrolling feedback. - * - * @param interpolator {@link com.ogaclejapan.smarttablayout.SmartTabIndicationInterpolator} - */ - public void setIndicationInterpolator(SmartTabIndicationInterpolator interpolator) { - tabStrip.setIndicationInterpolator(interpolator); - } - - /** - * Set the custom {@link TabColorizer} to be used. - * - * If you only require simple customisation then you can use - * {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve - * similar effects. - */ - public void setCustomTabColorizer(TabColorizer tabColorizer) { - tabStrip.setCustomTabColorizer(tabColorizer); - } - - /** - * Set the color used for styling the tab text. This will need to be called prior to calling - * {@link #setViewPager(ViewPager)} otherwise it will not get set - * - * @param color to use for tab text - */ - public void setDefaultTabTextColor(int color) { - tabViewTextColors = ColorStateList.valueOf(color); - } - - /** - * Sets the colors used for styling the tab text. This will need to be called prior to calling - * {@link #setViewPager(ViewPager)} otherwise it will not get set - * - * @param colors ColorStateList to use for tab text - */ - public void setDefaultTabTextColor(ColorStateList colors) { - tabViewTextColors = colors; - } - - /** - * Set the same weight for tab - */ - public void setDistributeEvenly(boolean distributeEvenly) { - this.distributeEvenly = distributeEvenly; - } - - /** - * Sets the colors to be used for indicating the selected tab. These colors are treated as a - * circular array. Providing one color will mean that all tabs are indicated with the same color. - */ - public void setSelectedIndicatorColors(int... colors) { - tabStrip.setSelectedIndicatorColors(colors); - } - - /** - * Sets the colors to be used for tab dividers. These colors are treated as a circular array. - * Providing one color will mean that all tabs are indicated with the same color. - */ - public void setDividerColors(int... colors) { - tabStrip.setDividerColors(colors); - } - - /** - * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SmartTabLayout} you are - * required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so - * that the layout can update it's scroll position correctly. - * - * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener) - */ - public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { - viewPagerPageChangeListener = listener; - } - - /** - * Set {@link OnScrollChangeListener} for obtaining values of scrolling. - * - * @param listener the {@link OnScrollChangeListener} to set - */ - public void setOnScrollChangeListener(OnScrollChangeListener listener) { - onScrollChangeListener = listener; - } - - /** - * Set {@link OnTabClickListener} for obtaining click event. - * - * @param listener the {@link OnTabClickListener} to set - */ - public void setOnTabClickListener(OnTabClickListener listener) { - onTabClickListener = listener; - } - - /** - * Set the custom layout to be inflated for the tab views. - * - * @param layoutResId Layout id to be inflated - * @param textViewId id of the {@link android.widget.TextView} in the inflated view - */ - public void setCustomTabView(int layoutResId, int textViewId) { - tabProvider = new SimpleTabProvider(getContext(), layoutResId, textViewId); - } - - /** - * Set the custom layout to be inflated for the tab views. - * - * @param provider {@link TabProvider} - */ - public void setCustomTabView(TabProvider provider) { - tabProvider = provider; - } - - /** - * Sets the associated view pager. Note that the assumption here is that the pager content - * (number of tabs and tab titles) does not change after this call has been made. - */ - public void setViewPager(ViewPager viewPager) { - tabStrip.removeAllViews(); - - this.viewPager = viewPager; - if (viewPager != null && viewPager.getAdapter() != null) { - viewPager.addOnPageChangeListener(new InternalViewPagerListener()); - populateTabStrip(); + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + // Ensure first scroll + if (changed && viewPager != null) { + scrollToTab(viewPager.getCurrentItem(), 0); + } } - } - - /** - * Returns the view at the specified position in the tabs. - * - * @param position the position at which to get the view from - * @return the view at the specified position or null if the position does not exist within the - * tabs - */ - public View getTabAt(int position) { - return tabStrip.getChildAt(position); - } - - /** - * Create a default view to be used for tabs. This is called if a custom tab view is not set via - * {@link #setCustomTabView(int, int)}. - */ - protected TextView createDefaultTabView(CharSequence title) { - TextView textView = new TextView(getContext()); - textView.setGravity(Gravity.CENTER); - textView.setText(title); - textView.setTextColor(tabViewTextColors); - textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabViewTextSize); - textView.setTypeface(Typeface.DEFAULT_BOLD); - textView.setLayoutParams(new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT)); - - if (tabViewBackgroundResId != NO_ID) { - textView.setBackgroundResource(tabViewBackgroundResId); - } else { - // If we're running on Honeycomb or newer, then we can use the Theme's - // selectableItemBackground to ensure that the View has a pressed state - TypedValue outValue = new TypedValue(); - getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, - outValue, true); - textView.setBackgroundResource(outValue.resourceId); + + /** + * Set the behavior of the Indicator scrolling feedback. + * + * @param interpolator {@link com.ogaclejapan.smarttablayout.SmartTabIndicationInterpolator} + */ + public void setIndicationInterpolator(SmartTabIndicationInterpolator interpolator) { + tabStrip.setIndicationInterpolator(interpolator); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - // If we're running on ICS or newer, enable all-caps to match the Action Bar tab style - textView.setAllCaps(tabViewTextAllCaps); + /** + * Set the custom {@link TabColorizer} to be used. + * + * If you only require simple customisation then you can use + * {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve + * similar effects. + */ + public void setCustomTabColorizer(TabColorizer tabColorizer) { + tabStrip.setCustomTabColorizer(tabColorizer); } - textView.setPadding( - tabViewTextHorizontalPadding, 0, - tabViewTextHorizontalPadding, 0); + /** + * Set the color used for styling the tab text. This will need to be called prior to calling + * {@link #setViewPager(ViewPager)} otherwise it will not get set + * + * @param color to use for tab text + */ + public void setDefaultTabTextColor(int color) { + tabViewTextColors = ColorStateList.valueOf(color); + } - if (tabViewTextMinWidth > 0) { - textView.setMinWidth(tabViewTextMinWidth); + /** + * Sets the colors used for styling the tab text. This will need to be called prior to calling + * {@link #setViewPager(ViewPager)} otherwise it will not get set + * + * @param colors ColorStateList to use for tab text + */ + public void setDefaultTabTextColor(ColorStateList colors) { + tabViewTextColors = colors; } - return textView; - } + /** + * Set the same weight for tab + */ + public void setDistributeEvenly(boolean distributeEvenly) { + this.distributeEvenly = distributeEvenly; + } - private void populateTabStrip() { - final PagerAdapter adapter = viewPager.getAdapter(); + /** + * Sets the colors to be used for indicating the selected tab. These colors are treated as a + * circular array. Providing one color will mean that all tabs are indicated with the same color. + */ + public void setSelectedIndicatorColors(int... colors) { + tabStrip.setSelectedIndicatorColors(colors); + } - for (int i = 0; i < adapter.getCount(); i++) { + /** + * Sets the colors to be used for tab dividers. These colors are treated as a circular array. + * Providing one color will mean that all tabs are indicated with the same color. + */ + public void setDividerColors(int... colors) { + tabStrip.setDividerColors(colors); + } - final View tabView = (tabProvider == null) - ? createDefaultTabView(adapter.getPageTitle(i)) - : tabProvider.createTabView(tabStrip, i, adapter); + /** + * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SmartTabLayout} you are + * required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so + * that the layout can update it's scroll position correctly. + * + * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener) + */ + public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { + viewPagerPageChangeListener = listener; + } - if (tabView == null) { - throw new IllegalStateException("tabView is null."); - } + /** + * Set {@link OnScrollChangeListener} for obtaining values of scrolling. + * + * @param listener the {@link OnScrollChangeListener} to set + */ + public void setOnScrollChangeListener(OnScrollChangeListener listener) { + onScrollChangeListener = listener; + } - if (distributeEvenly) { - LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams(); - lp.width = 0; - lp.weight = 1; - } + /** + * Set {@link OnTabClickListener} for obtaining click event. + * + * @param listener the {@link OnTabClickListener} to set + */ + public void setOnTabClickListener(OnTabClickListener listener) { + onTabClickListener = listener; + } - if (internalTabClickListener != null) { - tabView.setOnClickListener(internalTabClickListener); - } + /** + * Set the custom layout to be inflated for the tab views. + * + * @param layoutResId Layout id to be inflated + * @param textViewId id of the {@link android.widget.TextView} in the inflated view + */ + public void setCustomTabView(int layoutResId, int textViewId) { + tabProvider = new SimpleTabProvider(getContext(), layoutResId, textViewId); + } - tabStrip.addView(tabView); + /** + * Set the custom layout to be inflated for the tab views. + * + * @param provider {@link TabProvider} + */ + public void setCustomTabView(TabProvider provider) { + tabProvider = provider; + } - if (i == viewPager.getCurrentItem()) { - tabView.setSelected(true); - } + /** + * Sets the associated view pager. Note that the assumption here is that the pager content + * (number of tabs and tab titles) does not change after this call has been made. + */ + public void setViewPager(ViewPager viewPager) { + tabStrip.removeAllViews(); + this.viewPager = viewPager; + if (viewPager != null && viewPager.getAdapter() != null) { + viewPager.addOnPageChangeListener(new InternalViewPagerListener()); + populateTabStrip(); + } } - } - private void scrollToTab(int tabIndex, float positionOffset) { - final int tabStripChildCount = tabStrip.getChildCount(); - if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) { - return; + + /** + * Overriding indicator color with gradient when using this function, + * Note : if this function not called, tab indicator will use default stl_indicatorColor + * Usage : SmartTabLayout.setGradientIndicator(Color.rgb(1,1,1),Color.rgb(100,100,100)) + * + * @param colorEnd are Color.rgb + * @param colorStart are Color.rgb too + * */ + public void setGradientIndicator(int colorStart, int colorEnd) { + tabStrip.getGradientColor(true, colorStart, colorEnd); + } + + /** + * Returns the view at the specified position in the tabs. + * + * @param position the position at which to get the view from + * @return the view at the specified position or null if the position does not exist within the + * tabs + */ + public View getTabAt(int position) { + return tabStrip.getChildAt(position); } - final boolean isLayoutRtl = Utils.isLayoutRtl(this); - View selectedTab = tabStrip.getChildAt(tabIndex); - int widthPlusMargin = Utils.getWidth(selectedTab) + Utils.getMarginHorizontally(selectedTab); - int extraOffset = (int) (positionOffset * widthPlusMargin); - - if (tabStrip.isIndicatorAlwaysInCenter()) { - - if (0f < positionOffset && positionOffset < 1f) { - View nextTab = tabStrip.getChildAt(tabIndex + 1); - int selectHalfWidth = Utils.getWidth(selectedTab) / 2 + Utils.getMarginEnd(selectedTab); - int nextHalfWidth = Utils.getWidth(nextTab) / 2 + Utils.getMarginStart(nextTab); - extraOffset = Math.round(positionOffset * (selectHalfWidth + nextHalfWidth)); - } - - View firstTab = tabStrip.getChildAt(0); - int x; - if (isLayoutRtl) { - int first = Utils.getWidth(firstTab) + Utils.getMarginEnd(firstTab); - int selected = Utils.getWidth(selectedTab) + Utils.getMarginEnd(selectedTab); - x = Utils.getEnd(selectedTab) - Utils.getMarginEnd(selectedTab) - extraOffset; - x -= (first - selected) / 2; - } else { - int first = Utils.getWidth(firstTab) + Utils.getMarginStart(firstTab); - int selected = Utils.getWidth(selectedTab) + Utils.getMarginStart(selectedTab); - x = Utils.getStart(selectedTab) - Utils.getMarginStart(selectedTab) + extraOffset; - x -= (first - selected) / 2; - } - - scrollTo(x, 0); - return; + /** + * Create a default view to be used for tabs. This is called if a custom tab view is not set via + * {@link #setCustomTabView(int, int)}. + */ + protected TextView createDefaultTabView(CharSequence title) { + TextView textView = new TextView(getContext()); + textView.setGravity(Gravity.CENTER); + textView.setText(title); + textView.setTextColor(tabViewTextColors); + textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabViewTextSize); + textView.setTypeface(Typeface.DEFAULT_BOLD); + textView.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT)); + + if (tabViewBackgroundResId != NO_ID) { + textView.setBackgroundResource(tabViewBackgroundResId); + } else { + // If we're running on Honeycomb or newer, then we can use the Theme's + // selectableItemBackground to ensure that the View has a pressed state + TypedValue outValue = new TypedValue(); + getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, + outValue, true); + textView.setBackgroundResource(outValue.resourceId); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + // If we're running on ICS or newer, enable all-caps to match the Action Bar tab style + textView.setAllCaps(tabViewTextAllCaps); + } + + textView.setPadding( + tabViewTextHorizontalPadding, 0, + tabViewTextHorizontalPadding, 0); + + if (tabViewTextMinWidth > 0) { + textView.setMinWidth(tabViewTextMinWidth); + } + return textView; } - int x; - if (titleOffset == TITLE_OFFSET_AUTO_CENTER) { + private void populateTabStrip() { + final PagerAdapter adapter = viewPager.getAdapter(); - if (0f < positionOffset && positionOffset < 1f) { - View nextTab = tabStrip.getChildAt(tabIndex + 1); - int selectHalfWidth = Utils.getWidth(selectedTab) / 2 + Utils.getMarginEnd(selectedTab); - int nextHalfWidth = Utils.getWidth(nextTab) / 2 + Utils.getMarginStart(nextTab); - extraOffset = Math.round(positionOffset * (selectHalfWidth + nextHalfWidth)); - } + for (int i = 0; i < adapter.getCount(); i++) { - if (isLayoutRtl) { - x = -Utils.getWidthWithMargin(selectedTab) / 2 + getWidth() / 2; - x -= Utils.getPaddingStart(this); - } else { - x = Utils.getWidthWithMargin(selectedTab) / 2 - getWidth() / 2; - x += Utils.getPaddingStart(this); - } + final View tabView = (tabProvider == null) + ? createDefaultTabView(adapter.getPageTitle(i)) + : tabProvider.createTabView(tabStrip, i, adapter); - } else { + if (tabView == null) { + throw new IllegalStateException("tabView is null."); + } - if (isLayoutRtl) { - x = (tabIndex > 0 || positionOffset > 0) ? titleOffset : 0; - } else { - x = (tabIndex > 0 || positionOffset > 0) ? -titleOffset : 0; - } + if (distributeEvenly) { + LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams(); + lp.width = 0; + lp.weight = 1; + } - } + if (internalTabClickListener != null) { + tabView.setOnClickListener(internalTabClickListener); + } + + tabStrip.addView(tabView); - int start = Utils.getStart(selectedTab); - int startMargin = Utils.getMarginStart(selectedTab); - if (isLayoutRtl) { - x += start + startMargin - extraOffset - getWidth() + Utils.getPaddingHorizontally(this); - } else { - x += start - startMargin + extraOffset; + if (i == viewPager.getCurrentItem()) { + tabView.setSelected(true); + } + + } } - scrollTo(x, 0); + private void scrollToTab(int tabIndex, float positionOffset) { + final int tabStripChildCount = tabStrip.getChildCount(); + if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) { + return; + } - } + final boolean isLayoutRtl = Utils.isLayoutRtl(this); + View selectedTab = tabStrip.getChildAt(tabIndex); + int widthPlusMargin = Utils.getWidth(selectedTab) + Utils.getMarginHorizontally(selectedTab); + int extraOffset = (int) (positionOffset * widthPlusMargin); + + if (tabStrip.isIndicatorAlwaysInCenter()) { + + if (0f < positionOffset && positionOffset < 1f) { + View nextTab = tabStrip.getChildAt(tabIndex + 1); + int selectHalfWidth = Utils.getWidth(selectedTab) / 2 + Utils.getMarginEnd(selectedTab); + int nextHalfWidth = Utils.getWidth(nextTab) / 2 + Utils.getMarginStart(nextTab); + extraOffset = Math.round(positionOffset * (selectHalfWidth + nextHalfWidth)); + } + + View firstTab = tabStrip.getChildAt(0); + int x; + if (isLayoutRtl) { + int first = Utils.getWidth(firstTab) + Utils.getMarginEnd(firstTab); + int selected = Utils.getWidth(selectedTab) + Utils.getMarginEnd(selectedTab); + x = Utils.getEnd(selectedTab) - Utils.getMarginEnd(selectedTab) - extraOffset; + x -= (first - selected) / 2; + } else { + int first = Utils.getWidth(firstTab) + Utils.getMarginStart(firstTab); + int selected = Utils.getWidth(selectedTab) + Utils.getMarginStart(selectedTab); + x = Utils.getStart(selectedTab) - Utils.getMarginStart(selectedTab) + extraOffset; + x -= (first - selected) / 2; + } + + scrollTo(x, 0); + return; - /** - * Allows complete control over the colors drawn in the tab layout. Set with - * {@link #setCustomTabColorizer(TabColorizer)}. - */ - public interface TabColorizer { + } - /** - * @return return the color of the indicator used when {@code position} is selected. - */ - int getIndicatorColor(int position); + int x; + if (titleOffset == TITLE_OFFSET_AUTO_CENTER) { - /** - * @return return the color of the divider drawn to the right of {@code position}. - */ - int getDividerColor(int position); + if (0f < positionOffset && positionOffset < 1f) { + View nextTab = tabStrip.getChildAt(tabIndex + 1); + int selectHalfWidth = Utils.getWidth(selectedTab) / 2 + Utils.getMarginEnd(selectedTab); + int nextHalfWidth = Utils.getWidth(nextTab) / 2 + Utils.getMarginStart(nextTab); + extraOffset = Math.round(positionOffset * (selectHalfWidth + nextHalfWidth)); + } + + if (isLayoutRtl) { + x = -Utils.getWidthWithMargin(selectedTab) / 2 + getWidth() / 2; + x -= Utils.getPaddingStart(this); + } else { + x = Utils.getWidthWithMargin(selectedTab) / 2 - getWidth() / 2; + x += Utils.getPaddingStart(this); + } + + } else { + + if (isLayoutRtl) { + x = (tabIndex > 0 || positionOffset > 0) ? titleOffset : 0; + } else { + x = (tabIndex > 0 || positionOffset > 0) ? -titleOffset : 0; + } + + } - } + int start = Utils.getStart(selectedTab); + int startMargin = Utils.getMarginStart(selectedTab); + if (isLayoutRtl) { + x += start + startMargin - extraOffset - getWidth() + Utils.getPaddingHorizontally(this); + } else { + x += start - startMargin + extraOffset; + } + + scrollTo(x, 0); - /** - * Interface definition for a callback to be invoked when the scroll position of a view changes. - */ - public interface OnScrollChangeListener { + } /** - * Called when the scroll position of a view changes. - * - * @param scrollX Current horizontal scroll origin. - * @param oldScrollX Previous horizontal scroll origin. + * Allows complete control over the colors drawn in the tab layout. Set with + * {@link #setCustomTabColorizer(TabColorizer)}. */ - void onScrollChanged(int scrollX, int oldScrollX); - } + public interface TabColorizer { - /** - * Interface definition for a callback to be invoked when a tab is clicked. - */ - public interface OnTabClickListener { + /** + * @return return the color of the indicator used when {@code position} is selected. + */ + int getIndicatorColor(int position); + + /** + * @return return the color of the divider drawn to the right of {@code position}. + */ + int getDividerColor(int position); + + } /** - * Called when a tab is clicked. - * - * @param position tab's position + * Interface definition for a callback to be invoked when the scroll position of a view changes. */ - void onTabClicked(int position); - } + public interface OnScrollChangeListener { + + /** + * Called when the scroll position of a view changes. + * + * @param scrollX Current horizontal scroll origin. + * @param oldScrollX Previous horizontal scroll origin. + */ + void onScrollChanged(int scrollX, int oldScrollX); + } - /** - * Create the custom tabs in the tab layout. Set with - * {@link #setCustomTabView(com.ogaclejapan.smarttablayout.SmartTabLayout.TabProvider)} - */ - public interface TabProvider { + /** + * Interface definition for a callback to be invoked when a tab is clicked. + */ + public interface OnTabClickListener { + + /** + * Called when a tab is clicked. + * + * @param position tab's position + */ + void onTabClicked(int position); + } /** - * @return Return the View of {@code position} for the Tabs + * Create the custom tabs in the tab layout. Set with + * {@link #setCustomTabView(com.ogaclejapan.smarttablayout.SmartTabLayout.TabProvider)} */ - View createTabView(ViewGroup container, int position, PagerAdapter adapter); + public interface TabProvider { - } + /** + * @return Return the View of {@code position} for the Tabs + */ + View createTabView(ViewGroup container, int position, PagerAdapter adapter); - private static class SimpleTabProvider implements TabProvider { + } - private final LayoutInflater inflater; - private final int tabViewLayoutId; - private final int tabViewTextViewId; + private static class SimpleTabProvider implements TabProvider { - private SimpleTabProvider(Context context, int layoutResId, int textViewId) { - inflater = LayoutInflater.from(context); - tabViewLayoutId = layoutResId; - tabViewTextViewId = textViewId; - } + private final LayoutInflater inflater; + private final int tabViewLayoutId; + private final int tabViewTextViewId; - @Override - public View createTabView(ViewGroup container, int position, PagerAdapter adapter) { - View tabView = null; - TextView tabTitleView = null; + private SimpleTabProvider(Context context, int layoutResId, int textViewId) { + inflater = LayoutInflater.from(context); + tabViewLayoutId = layoutResId; + tabViewTextViewId = textViewId; + } - if (tabViewLayoutId != NO_ID) { - tabView = inflater.inflate(tabViewLayoutId, container, false); - } + @Override + public View createTabView(ViewGroup container, int position, PagerAdapter adapter) { + View tabView = null; + TextView tabTitleView = null; - if (tabViewTextViewId != NO_ID && tabView != null) { - tabTitleView = (TextView) tabView.findViewById(tabViewTextViewId); - } + if (tabViewLayoutId != NO_ID) { + tabView = inflater.inflate(tabViewLayoutId, container, false); + } - if (tabTitleView == null && TextView.class.isInstance(tabView)) { - tabTitleView = (TextView) tabView; - } + if (tabViewTextViewId != NO_ID && tabView != null) { + tabTitleView = (TextView) tabView.findViewById(tabViewTextViewId); + } - if (tabTitleView != null) { - tabTitleView.setText(adapter.getPageTitle(position)); - } + if (tabTitleView == null && TextView.class.isInstance(tabView)) { + tabTitleView = (TextView) tabView; + } + + if (tabTitleView != null) { + tabTitleView.setText(adapter.getPageTitle(position)); + } + + return tabView; + } - return tabView; } - } + private class InternalViewPagerListener implements ViewPager.OnPageChangeListener { - private class InternalViewPagerListener implements ViewPager.OnPageChangeListener { + private int scrollState; - private int scrollState; + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + int tabStripChildCount = tabStrip.getChildCount(); + if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) { + return; + } - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - int tabStripChildCount = tabStrip.getChildCount(); - if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) { - return; - } + tabStrip.onViewPagerPageChanged(position, positionOffset); - tabStrip.onViewPagerPageChanged(position, positionOffset); + scrollToTab(position, positionOffset); - scrollToTab(position, positionOffset); + if (viewPagerPageChangeListener != null) { + viewPagerPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels); + } + } - if (viewPagerPageChangeListener != null) { - viewPagerPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels); - } - } + @Override + public void onPageScrollStateChanged(int state) { + scrollState = state; - @Override - public void onPageScrollStateChanged(int state) { - scrollState = state; + if (viewPagerPageChangeListener != null) { + viewPagerPageChangeListener.onPageScrollStateChanged(state); + } + } - if (viewPagerPageChangeListener != null) { - viewPagerPageChangeListener.onPageScrollStateChanged(state); - } - } + @Override + public void onPageSelected(int position) { + if (scrollState == ViewPager.SCROLL_STATE_IDLE) { + tabStrip.onViewPagerPageChanged(position, 0f); + scrollToTab(position, 0); + } - @Override - public void onPageSelected(int position) { - if (scrollState == ViewPager.SCROLL_STATE_IDLE) { - tabStrip.onViewPagerPageChanged(position, 0f); - scrollToTab(position, 0); - } - - for (int i = 0, size = tabStrip.getChildCount(); i < size; i++) { - tabStrip.getChildAt(i).setSelected(position == i); - } - - if (viewPagerPageChangeListener != null) { - viewPagerPageChangeListener.onPageSelected(position); - } - } + for (int i = 0, size = tabStrip.getChildCount(); i < size; i++) { + tabStrip.getChildAt(i).setSelected(position == i); + } - } + if (viewPagerPageChangeListener != null) { + viewPagerPageChangeListener.onPageSelected(position); + } + } - private class InternalTabClickListener implements OnClickListener { - @Override - public void onClick(View v) { - for (int i = 0; i < tabStrip.getChildCount(); i++) { - if (v == tabStrip.getChildAt(i)) { - if (onTabClickListener != null) { - onTabClickListener.onTabClicked(i); - } - viewPager.setCurrentItem(i); - return; + } + + private class InternalTabClickListener implements OnClickListener { + @Override + public void onClick(View v) { + for (int i = 0; i < tabStrip.getChildCount(); i++) { + if (v == tabStrip.getChildAt(i)) { + if (onTabClickListener != null) { + onTabClickListener.onTabClicked(i); + } + viewPager.setCurrentItem(i); + return; + } + } } - } } - } } diff --git a/library/src/main/java/com/ogaclejapan/smarttablayout/SmartTabStrip.java b/library/src/main/java/com/ogaclejapan/smarttablayout/SmartTabStrip.java index 99f10b8..b3312bb 100755 --- a/library/src/main/java/com/ogaclejapan/smarttablayout/SmartTabStrip.java +++ b/library/src/main/java/com/ogaclejapan/smarttablayout/SmartTabStrip.java @@ -1,13 +1,13 @@ /** * Copyright (C) 2015 ogaclejapan * Copyright (C) 2013 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. @@ -20,8 +20,10 @@ import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.RectF; +import android.graphics.Shader; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; @@ -34,411 +36,439 @@ */ class SmartTabStrip extends LinearLayout { - private static final int GRAVITY_BOTTOM = 0; - private static final int GRAVITY_TOP = 1; - private static final int GRAVITY_CENTER = 2; - - private static final int AUTO_WIDTH = -1; - - private static final int DEFAULT_TOP_BORDER_THICKNESS_DIPS = 0; - private static final byte DEFAULT_TOP_BORDER_COLOR_ALPHA = 0x26; - private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 2; - private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26; - private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 8; - private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5; - private static final float DEFAULT_INDICATOR_CORNER_RADIUS = 0f; - private static final int DEFAULT_DIVIDER_THICKNESS_DIPS = 1; - private static final byte DEFAULT_DIVIDER_COLOR_ALPHA = 0x20; - private static final float DEFAULT_DIVIDER_HEIGHT = 0.5f; - private static final boolean DEFAULT_INDICATOR_IN_CENTER = false; - private static final boolean DEFAULT_INDICATOR_IN_FRONT = false; - private static final boolean DEFAULT_INDICATOR_WITHOUT_PADDING = false; - private static final int DEFAULT_INDICATOR_GRAVITY = GRAVITY_BOTTOM; - private static final boolean DEFAULT_DRAW_DECORATION_AFTER_TAB = false; - - private final int topBorderThickness; - private final int topBorderColor; - private final int bottomBorderThickness; - private final int bottomBorderColor; - private final Paint borderPaint; - private final RectF indicatorRectF = new RectF(); - private final boolean indicatorWithoutPadding; - private final boolean indicatorAlwaysInCenter; - private final boolean indicatorInFront; - private final int indicatorThickness; - private final int indicatorWidth; - private final int indicatorGravity; - private final float indicatorCornerRadius; - private final Paint indicatorPaint; - private final int dividerThickness; - private final Paint dividerPaint; - private final float dividerHeight; - private final SimpleTabColorizer defaultTabColorizer; - private final boolean drawDecorationAfterTab; - - private int lastPosition; - private int selectedPosition; - private float selectionOffset; - private SmartTabIndicationInterpolator indicationInterpolator; - private SmartTabLayout.TabColorizer customTabColorizer; - - SmartTabStrip(Context context, AttributeSet attrs) { - super(context); - setWillNotDraw(false); - - final float density = getResources().getDisplayMetrics().density; - - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(android.R.attr.colorForeground, outValue, true); - final int themeForegroundColor = outValue.data; - - boolean indicatorWithoutPadding = DEFAULT_INDICATOR_WITHOUT_PADDING; - boolean indicatorInFront = DEFAULT_INDICATOR_IN_FRONT; - boolean indicatorAlwaysInCenter = DEFAULT_INDICATOR_IN_CENTER; - int indicationInterpolatorId = SmartTabIndicationInterpolator.ID_SMART; - int indicatorGravity = DEFAULT_INDICATOR_GRAVITY; - int indicatorColor = DEFAULT_SELECTED_INDICATOR_COLOR; - int indicatorColorsId = NO_ID; - int indicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density); - int indicatorWidth = AUTO_WIDTH; - float indicatorCornerRadius = DEFAULT_INDICATOR_CORNER_RADIUS * density; - int overlineColor = setColorAlpha(themeForegroundColor, DEFAULT_TOP_BORDER_COLOR_ALPHA); - int overlineThickness = (int) (DEFAULT_TOP_BORDER_THICKNESS_DIPS * density); - int underlineColor = setColorAlpha(themeForegroundColor, DEFAULT_BOTTOM_BORDER_COLOR_ALPHA); - int underlineThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density); - int dividerColor = setColorAlpha(themeForegroundColor, DEFAULT_DIVIDER_COLOR_ALPHA); - int dividerColorsId = NO_ID; - int dividerThickness = (int) (DEFAULT_DIVIDER_THICKNESS_DIPS * density); - boolean drawDecorationAfterTab = DEFAULT_DRAW_DECORATION_AFTER_TAB; - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.stl_SmartTabLayout); - indicatorAlwaysInCenter = a.getBoolean( - R.styleable.stl_SmartTabLayout_stl_indicatorAlwaysInCenter, indicatorAlwaysInCenter); - indicatorWithoutPadding = a.getBoolean( - R.styleable.stl_SmartTabLayout_stl_indicatorWithoutPadding, indicatorWithoutPadding); - indicatorInFront = a.getBoolean( - R.styleable.stl_SmartTabLayout_stl_indicatorInFront, indicatorInFront); - indicationInterpolatorId = a.getInt( - R.styleable.stl_SmartTabLayout_stl_indicatorInterpolation, indicationInterpolatorId); - indicatorGravity = a.getInt( - R.styleable.stl_SmartTabLayout_stl_indicatorGravity, indicatorGravity); - indicatorColor = a.getColor( - R.styleable.stl_SmartTabLayout_stl_indicatorColor, indicatorColor); - indicatorColorsId = a.getResourceId( - R.styleable.stl_SmartTabLayout_stl_indicatorColors, indicatorColorsId); - indicatorThickness = a.getDimensionPixelSize( - R.styleable.stl_SmartTabLayout_stl_indicatorThickness, indicatorThickness); - indicatorWidth = a.getLayoutDimension( - R.styleable.stl_SmartTabLayout_stl_indicatorWidth, indicatorWidth); - indicatorCornerRadius = a.getDimension( - R.styleable.stl_SmartTabLayout_stl_indicatorCornerRadius, indicatorCornerRadius); - overlineColor = a.getColor( - R.styleable.stl_SmartTabLayout_stl_overlineColor, overlineColor); - overlineThickness = a.getDimensionPixelSize( - R.styleable.stl_SmartTabLayout_stl_overlineThickness, overlineThickness); - underlineColor = a.getColor( - R.styleable.stl_SmartTabLayout_stl_underlineColor, underlineColor); - underlineThickness = a.getDimensionPixelSize( - R.styleable.stl_SmartTabLayout_stl_underlineThickness, underlineThickness); - dividerColor = a.getColor( - R.styleable.stl_SmartTabLayout_stl_dividerColor, dividerColor); - dividerColorsId = a.getResourceId( - R.styleable.stl_SmartTabLayout_stl_dividerColors, dividerColorsId); - dividerThickness = a.getDimensionPixelSize( - R.styleable.stl_SmartTabLayout_stl_dividerThickness, dividerThickness); - drawDecorationAfterTab = a.getBoolean( - R.styleable.stl_SmartTabLayout_stl_drawDecorationAfterTab, drawDecorationAfterTab); - a.recycle(); - - final int[] indicatorColors = (indicatorColorsId == NO_ID) - ? new int[] { indicatorColor } - : getResources().getIntArray(indicatorColorsId); - - final int[] dividerColors = (dividerColorsId == NO_ID) - ? new int[] { dividerColor } - : getResources().getIntArray(dividerColorsId); - - this.defaultTabColorizer = new SimpleTabColorizer(); - this.defaultTabColorizer.setIndicatorColors(indicatorColors); - this.defaultTabColorizer.setDividerColors(dividerColors); - - this.topBorderThickness = overlineThickness; - this.topBorderColor = overlineColor; - this.bottomBorderThickness = underlineThickness; - this.bottomBorderColor = underlineColor; - this.borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - - this.indicatorAlwaysInCenter = indicatorAlwaysInCenter; - this.indicatorWithoutPadding = indicatorWithoutPadding; - this.indicatorInFront = indicatorInFront; - this.indicatorThickness = indicatorThickness; - this.indicatorWidth = indicatorWidth; - this.indicatorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - this.indicatorCornerRadius = indicatorCornerRadius; - this.indicatorGravity = indicatorGravity; - - this.dividerHeight = DEFAULT_DIVIDER_HEIGHT; - this.dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - this.dividerPaint.setStrokeWidth(dividerThickness); - this.dividerThickness = dividerThickness; - - this.drawDecorationAfterTab = drawDecorationAfterTab; - - this.indicationInterpolator = SmartTabIndicationInterpolator.of(indicationInterpolatorId); - } - - /** - * Set the alpha value of the {@code color} to be the given {@code alpha} value. - */ - private static int setColorAlpha(int color, byte alpha) { - return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)); - } - - /** - * Blend {@code color1} and {@code color2} using the given ratio. - * - * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, - * 0.0 will return {@code color2}. - */ - private static int blendColors(int color1, int color2, float ratio) { - final float inverseRation = 1f - ratio; - float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation); - float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation); - float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation); - return Color.rgb((int) r, (int) g, (int) b); - } - - void setIndicationInterpolator(SmartTabIndicationInterpolator interpolator) { - indicationInterpolator = interpolator; - invalidate(); - } - - void setCustomTabColorizer(SmartTabLayout.TabColorizer customTabColorizer) { - this.customTabColorizer = customTabColorizer; - invalidate(); - } - - void setSelectedIndicatorColors(int... colors) { - // Make sure that the custom colorizer is removed - customTabColorizer = null; - defaultTabColorizer.setIndicatorColors(colors); - invalidate(); - } - - void setDividerColors(int... colors) { - // Make sure that the custom colorizer is removed - customTabColorizer = null; - defaultTabColorizer.setDividerColors(colors); - invalidate(); - } - - void onViewPagerPageChanged(int position, float positionOffset) { - selectedPosition = position; - selectionOffset = positionOffset; - if (positionOffset == 0f && lastPosition != selectedPosition) { - lastPosition = selectedPosition; + private static final int GRAVITY_BOTTOM = 0; + private static final int GRAVITY_TOP = 1; + private static final int GRAVITY_CENTER = 2; + + private static final int AUTO_WIDTH = -1; + + private static final int DEFAULT_TOP_BORDER_THICKNESS_DIPS = 0; + private static final byte DEFAULT_TOP_BORDER_COLOR_ALPHA = 0x26; + private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 2; + private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26; + private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 8; + private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5; + private static final float DEFAULT_INDICATOR_CORNER_RADIUS = 0f; + private static final int DEFAULT_DIVIDER_THICKNESS_DIPS = 1; + private static final byte DEFAULT_DIVIDER_COLOR_ALPHA = 0x20; + private static final float DEFAULT_DIVIDER_HEIGHT = 0.5f; + private static final boolean DEFAULT_INDICATOR_IN_CENTER = false; + private static final boolean DEFAULT_INDICATOR_IN_FRONT = false; + private static final boolean DEFAULT_INDICATOR_WITHOUT_PADDING = false; + private static final int DEFAULT_INDICATOR_GRAVITY = GRAVITY_BOTTOM; + private static final boolean DEFAULT_DRAW_DECORATION_AFTER_TAB = false; + + private final int topBorderThickness; + private final int topBorderColor; + private final int bottomBorderThickness; + private final int bottomBorderColor; + private final Paint borderPaint; + private final RectF indicatorRectF = new RectF(); + private final boolean indicatorWithoutPadding; + private final boolean indicatorAlwaysInCenter; + private final boolean indicatorInFront; + private final int indicatorThickness; + private final int indicatorWidth; + private final int indicatorGravity; + private final float indicatorCornerRadius; + private final Paint indicatorPaint; + private final int dividerThickness; + private final Paint dividerPaint; + private final float dividerHeight; + private final SimpleTabColorizer defaultTabColorizer; + private final boolean drawDecorationAfterTab; + + // new variable for gradient indicator + private boolean usingGradientColor = false; + private int colorGradientStart; + private int colorGradientEnd; + + private int lastPosition; + private int selectedPosition; + private float selectionOffset; + private SmartTabIndicationInterpolator indicationInterpolator; + private SmartTabLayout.TabColorizer customTabColorizer; + + SmartTabStrip(Context context, AttributeSet attrs) { + super(context); + setWillNotDraw(false); + + final float density = getResources().getDisplayMetrics().density; + + TypedValue outValue = new TypedValue(); + context.getTheme().resolveAttribute(android.R.attr.colorForeground, outValue, true); + final int themeForegroundColor = outValue.data; + + boolean indicatorWithoutPadding = DEFAULT_INDICATOR_WITHOUT_PADDING; + boolean indicatorInFront = DEFAULT_INDICATOR_IN_FRONT; + boolean indicatorAlwaysInCenter = DEFAULT_INDICATOR_IN_CENTER; + int indicationInterpolatorId = SmartTabIndicationInterpolator.ID_SMART; + int indicatorGravity = DEFAULT_INDICATOR_GRAVITY; + int indicatorColor = DEFAULT_SELECTED_INDICATOR_COLOR; + int indicatorColorsId = NO_ID; + int indicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density); + int indicatorWidth = AUTO_WIDTH; + float indicatorCornerRadius = DEFAULT_INDICATOR_CORNER_RADIUS * density; + int overlineColor = setColorAlpha(themeForegroundColor, DEFAULT_TOP_BORDER_COLOR_ALPHA); + int overlineThickness = (int) (DEFAULT_TOP_BORDER_THICKNESS_DIPS * density); + int underlineColor = setColorAlpha(themeForegroundColor, DEFAULT_BOTTOM_BORDER_COLOR_ALPHA); + int underlineThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density); + int dividerColor = setColorAlpha(themeForegroundColor, DEFAULT_DIVIDER_COLOR_ALPHA); + int dividerColorsId = NO_ID; + int dividerThickness = (int) (DEFAULT_DIVIDER_THICKNESS_DIPS * density); + boolean drawDecorationAfterTab = DEFAULT_DRAW_DECORATION_AFTER_TAB; + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.stl_SmartTabLayout); + indicatorAlwaysInCenter = a.getBoolean( + R.styleable.stl_SmartTabLayout_stl_indicatorAlwaysInCenter, indicatorAlwaysInCenter); + indicatorWithoutPadding = a.getBoolean( + R.styleable.stl_SmartTabLayout_stl_indicatorWithoutPadding, indicatorWithoutPadding); + indicatorInFront = a.getBoolean( + R.styleable.stl_SmartTabLayout_stl_indicatorInFront, indicatorInFront); + indicationInterpolatorId = a.getInt( + R.styleable.stl_SmartTabLayout_stl_indicatorInterpolation, indicationInterpolatorId); + indicatorGravity = a.getInt( + R.styleable.stl_SmartTabLayout_stl_indicatorGravity, indicatorGravity); + indicatorColor = a.getColor( + R.styleable.stl_SmartTabLayout_stl_indicatorColor, indicatorColor); + indicatorColorsId = a.getResourceId( + R.styleable.stl_SmartTabLayout_stl_indicatorColors, indicatorColorsId); + indicatorThickness = a.getDimensionPixelSize( + R.styleable.stl_SmartTabLayout_stl_indicatorThickness, indicatorThickness); + indicatorWidth = a.getLayoutDimension( + R.styleable.stl_SmartTabLayout_stl_indicatorWidth, indicatorWidth); + indicatorCornerRadius = a.getDimension( + R.styleable.stl_SmartTabLayout_stl_indicatorCornerRadius, indicatorCornerRadius); + overlineColor = a.getColor( + R.styleable.stl_SmartTabLayout_stl_overlineColor, overlineColor); + overlineThickness = a.getDimensionPixelSize( + R.styleable.stl_SmartTabLayout_stl_overlineThickness, overlineThickness); + underlineColor = a.getColor( + R.styleable.stl_SmartTabLayout_stl_underlineColor, underlineColor); + underlineThickness = a.getDimensionPixelSize( + R.styleable.stl_SmartTabLayout_stl_underlineThickness, underlineThickness); + dividerColor = a.getColor( + R.styleable.stl_SmartTabLayout_stl_dividerColor, dividerColor); + dividerColorsId = a.getResourceId( + R.styleable.stl_SmartTabLayout_stl_dividerColors, dividerColorsId); + dividerThickness = a.getDimensionPixelSize( + R.styleable.stl_SmartTabLayout_stl_dividerThickness, dividerThickness); + drawDecorationAfterTab = a.getBoolean( + R.styleable.stl_SmartTabLayout_stl_drawDecorationAfterTab, drawDecorationAfterTab); + a.recycle(); + + final int[] indicatorColors = (indicatorColorsId == NO_ID) + ? new int[]{indicatorColor} + : getResources().getIntArray(indicatorColorsId); + + final int[] dividerColors = (dividerColorsId == NO_ID) + ? new int[]{dividerColor} + : getResources().getIntArray(dividerColorsId); + + this.defaultTabColorizer = new SimpleTabColorizer(); + this.defaultTabColorizer.setIndicatorColors(indicatorColors); + this.defaultTabColorizer.setDividerColors(dividerColors); + + this.topBorderThickness = overlineThickness; + this.topBorderColor = overlineColor; + this.bottomBorderThickness = underlineThickness; + this.bottomBorderColor = underlineColor; + this.borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + this.indicatorAlwaysInCenter = indicatorAlwaysInCenter; + this.indicatorWithoutPadding = indicatorWithoutPadding; + this.indicatorInFront = indicatorInFront; + this.indicatorThickness = indicatorThickness; + this.indicatorWidth = indicatorWidth; + this.indicatorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + this.indicatorCornerRadius = indicatorCornerRadius; + this.indicatorGravity = indicatorGravity; + + this.dividerHeight = DEFAULT_DIVIDER_HEIGHT; + this.dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + this.dividerPaint.setStrokeWidth(dividerThickness); + this.dividerThickness = dividerThickness; + + this.drawDecorationAfterTab = drawDecorationAfterTab; + + this.indicationInterpolator = SmartTabIndicationInterpolator.of(indicationInterpolatorId); } - invalidate(); - } - boolean isIndicatorAlwaysInCenter() { - return indicatorAlwaysInCenter; - } + /** + * Set the alpha value of the {@code color} to be the given {@code alpha} value. + */ + private static int setColorAlpha(int color, byte alpha) { + return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)); + } - SmartTabLayout.TabColorizer getTabColorizer() { - return (customTabColorizer != null) ? customTabColorizer : defaultTabColorizer; - } + /** + * Blend {@code color1} and {@code color2} using the given ratio. + * + * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, + * 0.0 will return {@code color2}. + */ + private static int blendColors(int color1, int color2, float ratio) { + final float inverseRation = 1f - ratio; + float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation); + float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation); + float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation); + return Color.rgb((int) r, (int) g, (int) b); + } - @Override - protected void onDraw(Canvas canvas) { - if (!drawDecorationAfterTab) { - drawDecoration(canvas); + void setIndicationInterpolator(SmartTabIndicationInterpolator interpolator) { + indicationInterpolator = interpolator; + invalidate(); } - } - @Override - protected void dispatchDraw(Canvas canvas) { - super.dispatchDraw(canvas); - if (drawDecorationAfterTab) { - drawDecoration(canvas); + void setCustomTabColorizer(SmartTabLayout.TabColorizer customTabColorizer) { + this.customTabColorizer = customTabColorizer; + invalidate(); } - } - - private void drawDecoration(Canvas canvas) { - final int height = getHeight(); - final int width = getWidth(); - final int tabCount = getChildCount(); - final SmartTabLayout.TabColorizer tabColorizer = getTabColorizer(); - final boolean isLayoutRtl = Utils.isLayoutRtl(this); - - if (indicatorInFront) { - drawOverline(canvas, 0, width); - drawUnderline(canvas, 0, width, height); + + void setSelectedIndicatorColors(int... colors) { + // Make sure that the custom colorizer is removed + customTabColorizer = null; + defaultTabColorizer.setIndicatorColors(colors); + invalidate(); } - // Thick colored underline below the current selection - if (tabCount > 0) { - View selectedTab = getChildAt(selectedPosition); - int selectedStart = Utils.getStart(selectedTab, indicatorWithoutPadding); - int selectedEnd = Utils.getEnd(selectedTab, indicatorWithoutPadding); - int left; - int right; - if (isLayoutRtl) { - left = selectedEnd; - right = selectedStart; - } else { - left = selectedStart; - right = selectedEnd; - } - - int color = tabColorizer.getIndicatorColor(selectedPosition); - float thickness = indicatorThickness; - - if (selectionOffset > 0f && selectedPosition < (getChildCount() - 1)) { - int nextColor = tabColorizer.getIndicatorColor(selectedPosition + 1); - if (color != nextColor) { - color = blendColors(nextColor, color, selectionOffset); - } + void setDividerColors(int... colors) { + // Make sure that the custom colorizer is removed + customTabColorizer = null; + defaultTabColorizer.setDividerColors(colors); + invalidate(); + } - // Draw the selection partway between the tabs - float startOffset = indicationInterpolator.getLeftEdge(selectionOffset); - float endOffset = indicationInterpolator.getRightEdge(selectionOffset); - float thicknessOffset = indicationInterpolator.getThickness(selectionOffset); - - View nextTab = getChildAt(selectedPosition + 1); - int nextStart = Utils.getStart(nextTab, indicatorWithoutPadding); - int nextEnd = Utils.getEnd(nextTab, indicatorWithoutPadding); - if (isLayoutRtl) { - left = (int) (endOffset * nextEnd + (1.0f - endOffset) * left); - right = (int) (startOffset * nextStart + (1.0f - startOffset) * right); - } else { - left = (int) (startOffset * nextStart + (1.0f - startOffset) * left); - right = (int) (endOffset * nextEnd + (1.0f - endOffset) * right); + // new function to overiding gradient + void getGradientColor(boolean isUsingGradient, int colorStart, int colorEnd) { + usingGradientColor = isUsingGradient; + colorGradientStart = colorStart; + colorGradientEnd = colorEnd; + } + + void onViewPagerPageChanged(int position, float positionOffset) { + selectedPosition = position; + selectionOffset = positionOffset; + if (positionOffset == 0f && lastPosition != selectedPosition) { + lastPosition = selectedPosition; } - thickness = thickness * thicknessOffset; - } + invalidate(); + } - drawIndicator(canvas, left, right, height, thickness, color); + boolean isIndicatorAlwaysInCenter() { + return indicatorAlwaysInCenter; + } + SmartTabLayout.TabColorizer getTabColorizer() { + return (customTabColorizer != null) ? customTabColorizer : defaultTabColorizer; } - if (!indicatorInFront) { - drawOverline(canvas, 0, width); - drawUnderline(canvas, 0, getWidth(), height); + @Override + protected void onDraw(Canvas canvas) { + if (!drawDecorationAfterTab) { + drawDecoration(canvas); + } } - // Vertical separators between the titles - drawSeparator(canvas, height, tabCount); + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (drawDecorationAfterTab) { + drawDecoration(canvas); + } + } - } + private void drawDecoration(Canvas canvas) { + final int height = getHeight(); + final int width = getWidth(); + final int tabCount = getChildCount(); + final SmartTabLayout.TabColorizer tabColorizer = getTabColorizer(); + final boolean isLayoutRtl = Utils.isLayoutRtl(this); - private void drawSeparator(Canvas canvas, int height, int tabCount) { - if (dividerThickness <= 0) { - return; - } + if (indicatorInFront) { + drawOverline(canvas, 0, width); + drawUnderline(canvas, 0, width, height); + } - final int dividerHeightPx = (int) (Math.min(Math.max(0f, dividerHeight), 1f) * height); - final SmartTabLayout.TabColorizer tabColorizer = getTabColorizer(); - - // Vertical separators between the titles - final int separatorTop = (height - dividerHeightPx) / 2; - final int separatorBottom = separatorTop + dividerHeightPx; - - final boolean isLayoutRtl = Utils.isLayoutRtl(this); - for (int i = 0; i < tabCount - 1; i++) { - View child = getChildAt(i); - int end = Utils.getEnd(child); - int endMargin = Utils.getMarginEnd(child); - int separatorX = isLayoutRtl ? end - endMargin : end + endMargin; - dividerPaint.setColor(tabColorizer.getDividerColor(i)); - canvas.drawLine(separatorX, separatorTop, separatorX, separatorBottom, dividerPaint); - } - } + // Thick colored underline below the current selection + if (tabCount > 0) { + View selectedTab = getChildAt(selectedPosition); + int selectedStart = Utils.getStart(selectedTab, indicatorWithoutPadding); + int selectedEnd = Utils.getEnd(selectedTab, indicatorWithoutPadding); + int left; + int right; + if (isLayoutRtl) { + left = selectedEnd; + right = selectedStart; + } else { + left = selectedStart; + right = selectedEnd; + } + + int color = tabColorizer.getIndicatorColor(selectedPosition); + float thickness = indicatorThickness; + + if (selectionOffset > 0f && selectedPosition < (getChildCount() - 1)) { + int nextColor = tabColorizer.getIndicatorColor(selectedPosition + 1); + if (color != nextColor) { + color = blendColors(nextColor, color, selectionOffset); + } + + // Draw the selection partway between the tabs + float startOffset = indicationInterpolator.getLeftEdge(selectionOffset); + float endOffset = indicationInterpolator.getRightEdge(selectionOffset); + float thicknessOffset = indicationInterpolator.getThickness(selectionOffset); + + View nextTab = getChildAt(selectedPosition + 1); + int nextStart = Utils.getStart(nextTab, indicatorWithoutPadding); + int nextEnd = Utils.getEnd(nextTab, indicatorWithoutPadding); + if (isLayoutRtl) { + left = (int) (endOffset * nextEnd + (1.0f - endOffset) * left); + right = (int) (startOffset * nextStart + (1.0f - startOffset) * right); + } else { + left = (int) (startOffset * nextStart + (1.0f - startOffset) * left); + right = (int) (endOffset * nextEnd + (1.0f - endOffset) * right); + } + thickness = thickness * thicknessOffset; + } + + drawIndicator(canvas, left, right, height, thickness, color); - private void drawIndicator(Canvas canvas, int left, int right, int height, float thickness, - int color) { - if (indicatorThickness <= 0 || indicatorWidth == 0) { - return; - } + } - float center; - float top; - float bottom; - - switch (indicatorGravity) { - case GRAVITY_TOP: - center = indicatorThickness / 2f; - top = center - (thickness / 2f); - bottom = center + (thickness / 2f); - break; - case GRAVITY_CENTER: - center = height / 2f; - top = center - (thickness / 2f); - bottom = center + (thickness / 2f); - break; - case GRAVITY_BOTTOM: - default: - center = height - (indicatorThickness / 2f); - top = center - (thickness / 2f); - bottom = center + (thickness / 2f); - } + if (!indicatorInFront) { + drawOverline(canvas, 0, width); + drawUnderline(canvas, 0, getWidth(), height); + } - indicatorPaint.setColor(color); - if (indicatorWidth == AUTO_WIDTH) { - indicatorRectF.set(left, top, right, bottom); - } else { - float padding = (Math.abs(left - right) - indicatorWidth) / 2f; - indicatorRectF.set(left + padding, top, right - padding, bottom); - } + // Vertical separators between the titles + drawSeparator(canvas, height, tabCount); - if (indicatorCornerRadius > 0f) { - canvas.drawRoundRect( - indicatorRectF, indicatorCornerRadius, - indicatorCornerRadius, indicatorPaint); - } else { - canvas.drawRect(indicatorRectF, indicatorPaint); } - } - private void drawOverline(Canvas canvas, int left, int right) { - if (topBorderThickness <= 0) { - return; - } - // Thin overline along the entire top edge - borderPaint.setColor(topBorderColor); - canvas.drawRect(left, 0, right, topBorderThickness, borderPaint); - } - - private void drawUnderline(Canvas canvas, int left, int right, int height) { - if (bottomBorderThickness <= 0) { - return; + private void drawSeparator(Canvas canvas, int height, int tabCount) { + if (dividerThickness <= 0) { + return; + } + + final int dividerHeightPx = (int) (Math.min(Math.max(0f, dividerHeight), 1f) * height); + final SmartTabLayout.TabColorizer tabColorizer = getTabColorizer(); + + // Vertical separators between the titles + final int separatorTop = (height - dividerHeightPx) / 2; + final int separatorBottom = separatorTop + dividerHeightPx; + + final boolean isLayoutRtl = Utils.isLayoutRtl(this); + for (int i = 0; i < tabCount - 1; i++) { + View child = getChildAt(i); + int end = Utils.getEnd(child); + int endMargin = Utils.getMarginEnd(child); + int separatorX = isLayoutRtl ? end - endMargin : end + endMargin; + dividerPaint.setColor(tabColorizer.getDividerColor(i)); + canvas.drawLine(separatorX, separatorTop, separatorX, separatorBottom, dividerPaint); + } } - // Thin underline along the entire bottom edge - borderPaint.setColor(bottomBorderColor); - canvas.drawRect(left, height - bottomBorderThickness, right, height, borderPaint); - } - private static class SimpleTabColorizer implements SmartTabLayout.TabColorizer { + private void drawIndicator(Canvas canvas, int left, int right, int height, float thickness, + int color) { + if (indicatorThickness <= 0 || indicatorWidth == 0) { + return; + } - private int[] indicatorColors; - private int[] dividerColors; + float center; + float top; + float bottom; + + switch (indicatorGravity) { + case GRAVITY_TOP: + center = indicatorThickness / 2f; + top = center - (thickness / 2f); + bottom = center + (thickness / 2f); + break; + case GRAVITY_CENTER: + center = height / 2f; + top = center - (thickness / 2f); + bottom = center + (thickness / 2f); + break; + case GRAVITY_BOTTOM: + default: + center = height - (indicatorThickness / 2f); + top = center - (thickness / 2f); + bottom = center + (thickness / 2f); + } - @Override - public final int getIndicatorColor(int position) { - return indicatorColors[position % indicatorColors.length]; + indicatorPaint.setColor(color); + if (indicatorWidth == AUTO_WIDTH) { + indicatorRectF.set(left, top, right, bottom); + } else { + float padding = (Math.abs(left - right) - indicatorWidth) / 2f; + indicatorRectF.set(left + padding, top, right - padding, bottom); + } + + // creating new paint for gradient + Paint paint = new Paint(); + paint.setStyle(Paint.Style.FILL); + paint.setShader(new LinearGradient((float) left, (float) height, (float) right, (float) height, colorGradientStart, colorGradientEnd, Shader.TileMode.CLAMP)); + + if (indicatorCornerRadius > 0f) { + // if using gradient color, use new paint + if (usingGradientColor) { + canvas.drawRoundRect( + indicatorRectF, indicatorCornerRadius, + indicatorCornerRadius, paint); + } else { + canvas.drawRoundRect( + indicatorRectF, indicatorCornerRadius, + indicatorCornerRadius, indicatorPaint); + } + } else { + // if using gradient color, use new paint + if (usingGradientColor) + canvas.drawRect(indicatorRectF, paint); + else + canvas.drawRect(indicatorRectF, indicatorPaint); + } } - @Override - public final int getDividerColor(int position) { - return dividerColors[position % dividerColors.length]; + private void drawOverline(Canvas canvas, int left, int right) { + if (topBorderThickness <= 0) { + return; + } + // Thin overline along the entire top edge + borderPaint.setColor(topBorderColor); + canvas.drawRect(left, 0, right, topBorderThickness, borderPaint); } - void setIndicatorColors(int... colors) { - indicatorColors = colors; + private void drawUnderline(Canvas canvas, int left, int right, int height) { + if (bottomBorderThickness <= 0) { + return; + } + // Thin underline along the entire bottom edge + borderPaint.setColor(bottomBorderColor); + canvas.drawRect(left, height - bottomBorderThickness, right, height, borderPaint); } - void setDividerColors(int... colors) { - dividerColors = colors; + private static class SimpleTabColorizer implements SmartTabLayout.TabColorizer { + + private int[] indicatorColors; + private int[] dividerColors; + + @Override + public final int getIndicatorColor(int position) { + return indicatorColors[position % indicatorColors.length]; + } + + @Override + public final int getDividerColor(int position) { + return dividerColors[position % dividerColors.length]; + } + + void setIndicatorColors(int... colors) { + indicatorColors = colors; + } + + void setDividerColors(int... colors) { + dividerColors = colors; + } } - } }