效果制作的不是很好。
这篇文章,也是在网上搜了很多资源参考,对 SlidingTabLayout.java和SlidingTabStrip.java进行了修改。大家可以更改他的格式字体大小、选中状态,分割线调整等等。先上传这两个文件,改动支出都做了注释。
SlidingTabLayout.java
/* * 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. * See the License for the specific language governing permissions and * limitations under the License. */package com.example.my.slidingtablayout;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Color;import android.graphics.Typeface;import android.os.Build;import android.support.v4.view.PagerAdapter;import android.support.v4.view.ViewPager;import android.util.AttributeSet;import android.util.TypedValue;import android.view.Gravity;import android.view.LayoutInflater;import android.view.View;import android.widget.HorizontalScrollView;import android.widget.LinearLayout;import android.widget.TextView;/** * To be used with ViewPager to provide a tab indicator component which give constant feedback as to * the user"s scroll progress. * <p> * To use the component, simply add it to your view hierarchy. Then in your * {@link android.app.Activity} or {@link android.support.v4.app.Fragment} call * {@link #setViewPager(ViewPager)} providing it the ViewPager this layout is being used for. * <p> * The colors can be customized in two ways. The first and simplest is to provide an array of colors * via {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)}. The * alternative is via the {@link TabColorizer} interface which provides you complete control over * which color is used for any individual position. * <p> * The views used as tabs can be customized by calling {@link #setCustomTabView(int, int)}, * providing the layout ID of your custom layout. */public class SlidingTabLayout extends HorizontalScrollView { /*** 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);/** * @return return the color of the divider drawn to the right of {@code position}. */int getDividerColor(int position); } private static final int TITLE_OFFSET_DIPS = 24; private static final int TAB_VIEW_PADDING_DIPS = 16; //内边距 private static int TAB_VIEW_TEXT_SIZE_SP = 16; //字体大小 private int mTitleOffset; private int mTabViewLayoutId; private int mTabViewTextViewId; // 定义两种需要添加的选项卡颜色 private int mDefaultTextColor; private int mSelectedTextColor; private ViewPager mViewPager; private ViewPager.OnPageChangeListener mViewPagerPageChangeListener; private final SlidingTabStrip mTabStrip; public SlidingTabLayout(Context context) {this(context, null); } public SlidingTabLayout(Context context, AttributeSet attrs) {this(context, attrs, 0); } public SlidingTabLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);// 获取选项卡颜色,如果未定义的话,则使用主题默认的颜色TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.SlidingTabLayout);int defaultTextColor = a.getColor(R.styleable.SlidingTabLayout_android_textColorPrimary, 0);mDefaultTextColor = a.getColor(R.styleable.SlidingTabLayout_textColorTabDefault, defaultTextColor);mSelectedTextColor = a.getColor(R.styleable.SlidingTabLayout_textColorTabSelected ,defaultTextColor);a.recycle();// Disable the Scroll BarsetHorizontalScrollBarEnabled(false);// Make sure that the Tab Strips fills this ViewsetFillViewport(true);mTitleOffset = (int) (TITLE_OFFSET_DIPS * getResources().getDisplayMetrics().density);mTabStrip = new SlidingTabStrip(context);addView(mTabStrip, LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); } // 在每次选项改变时更新选项卡文本颜色的新方法 private void updateSelectedTitle(int position) {final PagerAdapter adapter = mViewPager.getAdapter();for (int i = 0; i < adapter.getCount(); i++) { final View tabView = mTabStrip.getChildAt(i); if (TextView.class.isInstance(tabView)) {TextView titleView = (TextView)tabView;boolean isSelected = i == position;titleView.setTextColor(isSelected ? mSelectedTextColor : mDefaultTextColor); }} } /*** Set the custom {@link TabColorizer} to be used.* <p>* If you only require simple custmisation then you can use* {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve* similar effects.*/ public void setCustomTabColorizer(TabColorizer tabColorizer) {mTabStrip.setCustomTabColorizer(tabColorizer); } /*** 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) {mTabStrip.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) {mTabStrip.setDividerColors(colors); } //...设置字体大小 public void setTitleSize(int size) {this.TAB_VIEW_TEXT_SIZE_SP = size; } /*** Set the {@link ViewPager.OnPageChangeListener}. When using {@link SlidingTabLayout} 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) {mViewPagerPageChangeListener = 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 TextView} in the inflated view*/ public void setCustomTabView(int layoutResId, int textViewId) {mTabViewLayoutId = layoutResId;mTabViewTextViewId = textViewId; } /*** 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) {mTabStrip.removeAllViews();mViewPager = viewPager;if (viewPager != null) { viewPager.setOnPageChangeListener(new InternalViewPagerListener()); populateTabStrip();} } /*** 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(Context context) {TextView textView = new TextView(context);textView.setGravity(Gravity.CENTER);textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP);textView.setTypeface(Typeface.DEFAULT_BOLD);//...这会移除 Holo 的默认背景强调以及选项卡的粗体文本if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // 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(true);}int padding = (int) (TAB_VIEW_PADDING_DIPS * getResources().getDisplayMetrics().density);textView.setPadding(padding, padding, padding, padding);return textView; } private void populateTabStrip() {final PagerAdapter adapter = mViewPager.getAdapter();final OnClickListener tabClickListener = new TabClickListener();for (int i = 0; i < adapter.getCount(); i++) { View tabView = null; TextView tabTitleView = null; if (mTabViewLayoutId != 0) {// If there is a custom tab view layout id set, try and inflate ittabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,false);tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId); } if (tabView == null) {tabView = createDefaultTabView(getContext()); } if (tabTitleView == null && TextView.class.isInstance(tabView)) {tabTitleView = (TextView) tabView; } tabTitleView.setText(adapter.getPageTitle(i)); //... 设置头部均分 LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(0, LayoutParams.WRAP_CONTENT, 1.0f); tabView.setLayoutParams(layoutParams); tabView.setOnClickListener(tabClickListener); mTabStrip.addView(tabView);} } @Override protected void onAttachedToWindow() {super.onAttachedToWindow();if (mViewPager != null) { scrollToTab(mViewPager.getCurrentItem(), 0);} } private void scrollToTab(int tabIndex, int positionOffset) {final int tabStripChildCount = mTabStrip.getChildCount();if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) { return;}View selectedChild = mTabStrip.getChildAt(tabIndex);if (selectedChild != null) { // 调用在每次选项改变时更新文本颜色的新方案 updateSelectedTitle(tabIndex); int targetScrollX = selectedChild.getLeft() + positionOffset; if (tabIndex > 0 || positionOffset > 0) {// If we"re not at the first child and are mid-scroll, make sure we obey the offsettargetScrollX -= mTitleOffset; } scrollTo(targetScrollX, 0);} } private class InternalViewPagerListener implements ViewPager.OnPageChangeListener {private int mScrollState;@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { int tabStripChildCount = mTabStrip.getChildCount(); if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {return; } mTabStrip.onViewPagerPageChanged(position, positionOffset); View selectedTitle = mTabStrip.getChildAt(position); int extraOffset = (selectedTitle != null) ? (int) (positionOffset * selectedTitle.getWidth()) : 0; scrollToTab(position, extraOffset); if (mViewPagerPageChangeListener != null) {mViewPagerPageChangeListener.onPageScrolled(position, positionOffset,positionOffsetPixels); }}@Overridepublic void onPageScrollStateChanged(int state) { mScrollState = state; if (mViewPagerPageChangeListener != null) {mViewPagerPageChangeListener.onPageScrollStateChanged(state); }}@Overridepublic void onPageSelected(int position) { if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {mTabStrip.onViewPagerPageChanged(position, 0f);scrollToTab(position, 0); } if (mViewPagerPageChangeListener != null) {mViewPagerPageChangeListener.onPageSelected(position); }} } private class TabClickListener implements OnClickListener {@Overridepublic void onClick(View v) { for (int i = 0; i < mTabStrip.getChildCount(); i++) {if (v == mTabStrip.getChildAt(i)) { mViewPager.setCurrentItem(i); return;} }} }}SlidingTabStrip.java
/* * 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. * See the License for the specific language governing permissions and * limitations under the License. */package com.example.my.slidingtablayout;import android.R;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.util.TypedValue;import android.view.View;import android.widget.LinearLayout;class SlidingTabStrip extends LinearLayout { private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 0; //去除阴影 private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26; private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 4;//设置滚动条的高度 private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5; 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 final int mBottomBorderThickness; private final Paint mBottomBorderPaint; private final int mSelectedIndicatorThickness; private final Paint mSelectedIndicatorPaint; private final int mDefaultBottomBorderColor; private final Paint mDividerPaint; private final float mDividerHeight; private int mSelectedPosition; private float mSelectionOffset; private SlidingTabLayout.TabColorizer mCustomTabColorizer; private final SimpleTabColorizer mDefaultTabColorizer; SlidingTabStrip(Context context) {this(context, null); } SlidingTabStrip(Context context, AttributeSet attrs) {super(context, attrs);setWillNotDraw(false);final float density = getResources().getDisplayMetrics().density;TypedValue outValue = new TypedValue();context.getTheme().resolveAttribute(R.attr.colorForeground, outValue, true);final int themeForegroundColor = outValue.data;mDefaultBottomBorderColor = setColorAlpha(themeForegroundColor,DEFAULT_BOTTOM_BORDER_COLOR_ALPHA);mDefaultTabColorizer = new SimpleTabColorizer();mDefaultTabColorizer.setIndicatorColors(DEFAULT_SELECTED_INDICATOR_COLOR);mDefaultTabColorizer.setDividerColors(setColorAlpha(themeForegroundColor,DEFAULT_DIVIDER_COLOR_ALPHA));mBottomBorderThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density);mBottomBorderPaint = new Paint();mBottomBorderPaint.setColor(mDefaultBottomBorderColor);mSelectedIndicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density);mSelectedIndicatorPaint = new Paint();mDividerHeight = DEFAULT_DIVIDER_HEIGHT;mDividerPaint = new Paint();mDividerPaint.setStrokeWidth((int) (DEFAULT_DIVIDER_THICKNESS_DIPS * density)); } void setCustomTabColorizer(SlidingTabLayout.TabColorizer customTabColorizer) {mCustomTabColorizer = customTabColorizer;invalidate(); } void setSelectedIndicatorColors(int... colors) {// Make sure that the custom colorizer is removedmCustomTabColorizer = null;mDefaultTabColorizer.setIndicatorColors(colors);invalidate(); } void setDividerColors(int... colors) {// Make sure that the custom colorizer is removedmCustomTabColorizer = null;mDefaultTabColorizer.setDividerColors(colors);invalidate(); } void onViewPagerPageChanged(int position, float positionOffset) {mSelectedPosition = position;mSelectionOffset = positionOffset;invalidate(); } @Override protected void onDraw(Canvas canvas) {final int height = getHeight();final int childCount = getChildCount();final int dividerHeightPx = (int) (Math.min(Math.max(0f, mDividerHeight), 1f) * height);final SlidingTabLayout.TabColorizer tabColorizer = mCustomTabColorizer != null? mCustomTabColorizer: mDefaultTabColorizer;// Thick colored underline below the current selectionif (childCount > 0) { View selectedTitle = getChildAt(mSelectedPosition); int left = selectedTitle.getLeft(); int right = selectedTitle.getRight(); int color = tabColorizer.getIndicatorColor(mSelectedPosition); if (mSelectionOffset > 0f && mSelectedPosition < (getChildCount() - 1)) {int nextColor = tabColorizer.getIndicatorColor(mSelectedPosition + 1);if (color != nextColor) { color = blendColors(nextColor, color, mSelectionOffset);}// Draw the selection partway between the tabsView nextTitle = getChildAt(mSelectedPosition + 1);left = (int) (mSelectionOffset * nextTitle.getLeft() +(1.0f - mSelectionOffset) * left);right = (int) (mSelectionOffset * nextTitle.getRight() +(1.0f - mSelectionOffset) * right); } mSelectedIndicatorPaint.setColor(color); canvas.drawRect(left, height - mSelectedIndicatorThickness, right, height, mSelectedIndicatorPaint);}// Thin underline along the entire bottom edgecanvas.drawRect(0, height - mBottomBorderThickness, getWidth(), height, mBottomBorderPaint);// Vertical separators between the titlesint separatorTop = (height - dividerHeightPx) / 2;for (int i = 0; i < childCount - 1; i++) { View child = getChildAt(i); mDividerPaint.setColor(tabColorizer.getDividerColor(i)); canvas.drawLine(child.getRight(), separatorTop, child.getRight(), separatorTop + dividerHeightPx, mDividerPaint);} } /*** 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); } private static class SimpleTabColorizer implements SlidingTabLayout.TabColorizer {private int[] mIndicatorColors; //private int[] mDividerColors;//@Overridepublic final int getIndicatorColor(int position) { return mIndicatorColors[position % mIndicatorColors.length];}@Overridepublic final int getDividerColor(int position) { return mDividerColors[position % mDividerColors.length];}void setIndicatorColors(int... colors) { mIndicatorColors = colors;}void setDividerColors(int... colors) { mDividerColors = colors;} }}上边因为使用了自定义的颜色,所以这里要在attrs.xml声明一下,不然找不到:
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="SlidingTabLayout"><attr name="android:textColorPrimary" /><attr name="textColorTabDefault" format="color" /><attr name="textColorTabSelected" format="color" /> </declare-styleable></resources>布局文件也要用到自定义:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.my.slidingtablayout.MainActivity"> <!-- 在上方就在上面,在下方就在下面(tab栏) --> <com.example.my.slidingtablayout.SlidingTabLayoutandroid:id="@+id/sliding"android:layout_width="match_parent"android:layout_height="wrap_content"app:textColorTabDefault="#000000"app:textColorTabSelected="@color/colorAccent"/> <android.support.v4.view.ViewPagerandroid:id="@+id/view_pager"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout>最后一道就是在你的Activity运用这种开源:可以调整之处也做了说明
package com.example.my.slidingtablayout;import android.graphics.Color;import android.os.Bundle;import android.support.v4.view.PagerAdapter;import android.support.v4.view.ViewPager;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.view.ViewGroup;import android.widget.LinearLayout;import java.util.ArrayList;public class MainActivity extends AppCompatActivity { //创建 颜色数组 用来做viewpager的背景 @Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ViewPager pager = (ViewPager) findViewById(R.id.view_pager);SlidingTabLayout tab = (SlidingTabLayout) findViewById(R.id.sliding);tab.setDividerColors(Color.TRANSPARENT); //设置标题的分割线tab.setSelectedIndicatorColors(Color.rgb(51, 181, 229)); //设置滚动条的颜色tab.setTitleSize(18); //...设置字体的颜色,默认16MyAdapte adapter = new MyAdapte();pager.setAdapter(adapter);tab.setViewPager(pager); } int[] colors = {0xFF123456, 0xFF654321, 0xFF336699}; class MyAdapte extends PagerAdapter {//可以考虑把这个数组添加到集合里面String[] titles = {"AA", "BB", "CC"};ArrayList<LinearLayout> layouts = new ArrayList<LinearLayout>();MyAdapte() { for (int i = 0; i < 3; i++) {LinearLayout l = new LinearLayout(MainActivity.this);l.setBackgroundColor(colors[i]);l.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));layouts.add(l); }}@Overridepublic int getCount() { return layouts.size();}@Overridepublic boolean isViewFromObject(View view, Object o) { return view == o;}@Overridepublic Object instantiateItem(ViewGroup container, int position) { LinearLayout l = layouts.get(position); container.addView(l); return l;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) { container.removeView(layouts.get(position));}@Overridepublic CharSequence getPageTitle(int position) { //...可以返回集合list.get(position); return titles[position];} }}以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。