package com.flyco.tablayout;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.flyco.tablayout.listener.OnTabSelectListener;
import com.flyco.tablayout.utils.UnreadMsgUtils;
import com.flyco.tablayout.widget.MsgView;
import java.util.ArrayList;
import java.util.Collections;
/** 滑动TabLayout,对于ViewPager的依赖性强 */
public class SlidingTabLayout extends HorizontalScrollView implements ViewPager.OnPageChangeListener {
private Context mContext;
private ViewPager mViewPager;
private ArrayList<String> mTitles;
private LinearLayout mTabsContainer;
private int mCurrentTab;
private float mCurrentPositionOffset;
private int mTabCount;
/** 用于绘制显示器 */
private Rect mIndicatorRect = new Rect();
/** 用于实现滚动居中 */
private Rect mTabRect = new Rect();
private GradientDrawable mIndicatorDrawable = new GradientDrawable();
private Paint mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Paint mDividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Paint mTrianglePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Path mTrianglePath = new Path();
private static final int STYLE_NORMAL = 0;
private static final int STYLE_TRIANGLE = 1;
private static final int STYLE_BLOCK = 2;
private int mIndicatorStyle = STYLE_NORMAL;
private float mTabPadding;
private boolean mTabSpaceEqual;
private float mTabWidth;
/** indicator */
private int mIndicatorColor;
private float mIndicatorHeight;
private float mIndicatorWidth;
private float mIndicatorCornerRadius;
private float mIndicatorMarginLeft;
private float mIndicatorMarginTop;
private float mIndicatorMarginRight;
private float mIndicatorMarginBottom;
private int mIndicatorGravity;
private boolean mIndicatorWidthEqualTitle;
/** underline */
private int mUnderlineColor;
private float mUnderlineHeight;
private int mUnderlineGravity;
/** divider */
private int mDividerColor;
private float mDividerWidth;
private float mDividerPadding;
/** title */
private static final int TEXT_BOLD_NONE = 0;
private static final int TEXT_BOLD_WHEN_SELECT = 1;
private static final int TEXT_BOLD_BOTH = 2;
private float mTextsize;
private int mTextSelectColor;
private int mTextUnselectColor;
private int mTextBold;
private boolean mTextAllCaps;
private int mLastScrollX;
private int mHeight;
private boolean mSnapOnTabClick;
public SlidingTabLayout(Context context) {
this(context, null, 0);
}
public SlidingTabLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SlidingTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setFillViewport(true);//设置滚动视图是否可以伸缩其内容以填充视口
setWillNotDraw(false);//重写onDraw方法,需要调用这个方法来清除flag
setClipChildren(false);
setClipToPadding(false);
this.mContext = context;
mTabsContainer = new LinearLayout(context);
addView(mTabsContainer);
obtainAttributes(context, attrs);
//get layout_height
String height = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_height");
if (height.equals(ViewGroup.LayoutParams.MATCH_PARENT + "")) {
} else if (height.equals(ViewGroup.LayoutParams.WRAP_CONTENT + "")) {
} else {
int[] systemAttrs = {android.R.attr.layout_height};
TypedArray a = context.obtainStyledAttributes(attrs, systemAttrs);
mHeight = a.getDimensionPixelSize(0, ViewGroup.LayoutParams.WRAP_CONTENT);
a.recycle();
}
}
private void obtainAttributes(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingTabLayout);
mIndicatorStyle = ta.getInt(R.styleable.SlidingTabLayout_tl_indicator_style, STYLE_NORMAL);
mIndicatorColor = ta.getColor(R.styleable.SlidingTabLayout_tl_indicator_color, Color.parseColor(mIndicatorStyle == STYLE_BLOCK ? "#4B6A87" : "#ffffff"));
mIndicatorHeight = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_height,
dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 4 : (mIndicatorStyle == STYLE_BLOCK ? -1 : 2)));
mIndicatorWidth = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_width, dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 10 : -1));
mIndicatorCornerRadius = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_corner_radius, dp2px(mIndicatorStyle == STYLE_BLOCK ? -1 : 0));
mIndicatorMarginLeft = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_left, dp2px(0));
mIndicatorMarginTop = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_top, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0));
mIndicatorMarginRight = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_right, dp2px(0));
mIndicatorMarginBottom = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_bottom, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0));
mIndicatorGravity = ta.getInt(R.styleable.SlidingTabLayout_tl_indicator_gravity, Gravity.BOTTOM);
mIndicatorWidthEqualTitle = ta.getBoolean(R.styleable.SlidingTabLayout_tl_indicator_width_equal_title, false);
mUnderlineColor = ta.getColor(R.styleable.SlidingTabLayout_tl_underline_color, Color.parseColor("#ffffff"));
mUnderlineHeight = ta.getDimension(R.styleable.SlidingTabLayout_tl_underline_height, dp2px(0));
mUnderlineGravity = ta.getInt(R.styleable.SlidingTabLayout_tl_underline_gravity, Gravity.BOTTOM);
mDividerColor = ta.getColor(R.styleable.SlidingTabLayout_tl_divider_color, Color.parseColor("#ffffff"));
mDividerWidth = ta.getDimension(R.styleable.SlidingTabLayout_tl_divider_width, dp2px(0));
mDividerPadding = ta.getDimension(R.styleable.SlidingTabLayout_tl_divider_padding, dp2px(12));
mTextsize = ta.getDimension(R.styleable.SlidingTabLayout_tl_textsize, sp2px(14));
mTextSelectColor = ta.getColor(R.styleable.SlidingTabLayout_tl_textSelectColor, Color.parseColor("#ffffff"));
mTextUnselectColor = ta.getColor(R.styleable.SlidingTabLayout_tl_textUnselectColor, Color.parseColor("#AAffffff"));
mTextBold = ta.getInt(R.styleable.SlidingTabLayout_tl_textBold, TEXT_BOLD_NONE);
mTextAllCaps = ta.getBoolean(R.styleable.SlidingTabLayout_tl_textAllCaps, false);
mTabSpaceEqual = ta.getBoolean(R.styleable.SlidingTabLayout_tl_tab_space_equal, false);
mTabWidth = ta.getDimension(R.styleable.SlidingTabLayout_tl_tab_width, dp2px(-1));
mTabPadding = ta.getDimension(R.styleable.SlidingTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? dp2px(0) : dp2px(20));
ta.recycle();
}
/** 关联ViewPager */
public void setViewPager(ViewPager vp) {
if (vp == null || vp.getAdapter() == null) {
throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !");
}
this.mViewPager = vp;
this.mViewPager.removeOnPageChangeListener(this);
this.mViewPager.addOnPageChangeListener(this);
notifyDataSetChanged();
}
/** 关联ViewPager,用于不想在ViewPager适配器中设置titles数据的情况 */
public void setViewPager(ViewPager vp, String[] titles) {
if (vp == null || vp.getAdapter() == null) {
throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !");
}
if (titles == null || titles.length == 0) {
throw new IllegalStateException("Titles can not be EMPTY !");
}
if (titles.length != vp.getAdapter().getCount()) {
throw new IllegalStateException("Titles length must be the same as the page count !");
}
this.mViewPager = vp;
mTitles = new ArrayList<>();
Collections.addAll(mTitles, titles);
this.mViewPager.removeOnPageChangeListener(this);
this.mViewPager.addOnPageChangeListener(this);
notifyDataSetChanged();
}
/** 关联ViewPager,用于连适配器都不想自己实例化的情况 */
public void setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList<Fragment> fragments) {
if (vp == null) {
throw new IllegalStateException("ViewPager can not be NULL !");
}
if (titles == null || titles.length == 0) {
throw new IllegalStateException("Titles can not be EMPTY !");
}
this.mViewPager = vp;
this.mViewPager.setAdapter(new InnerPagerAdapter(fa.getSupportFragmentManager(), fragments, titles));
this.mViewPager.removeOnPageChangeListener(this);
this.mViewPager.addOnPageChangeListener(this);
notifyDataSetChanged();
}
/** 更新数据 */
public void notifyDataSetChanged() {
mTabsContainer.removeAllViews();
this.mTabCount = mTitles == null ? mViewPager.getAdapter().getCount() : mTitles.size();
View tabView;
for (int i = 0; i < mTabCount; i++) {
tabView = View.inflate(mContext, R.layout.layout_tab, null);
CharSequence pageTitle = mTitles == null ? mViewPager.getAdapter().getPageTitle(i) : mTitles.get(i);
addTab(i, pageTitle.toString(), tabView);
}
updateTabStyles();
}
public void addNewTab(String title) {
View tabView = View.inflate(mContext, R.layout.layout_tab, null);
if (mTitles != null) {
mTitles.add(title);
}
CharSequence pageTitle = mTitles == null ? mViewPager.getAdapter().getPageTitle(mTabCount) : mTitles.get(mTabCount);
addTab(mTabCount, pageTitle.toString(), tabView);
this.mTabCount = mTitles == null ? mViewPager.getAdapter().getCount() : mTitles.size();
updateTabStyles();
}
/** 创建并添加tab */
private void addTab(final int position, String title, View tabView) {
TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
if (tv_tab_title != null) {
if (title != null) tv_tab_title.setText(title);
}
tabView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int position = mTabsContainer.indexOfChild(v);
if (position != -1) {
if (mViewPager.getCurrentItem() != position) {
if (mSnapOnTabClick) {
mViewPager.setCurrentItem(position, false);
} else {
mViewPager.setCurrentItem(position);
}
if (mListener != null) {
mListener.onTabSelect(position);
}
} else {
if (mListener != null) {
mListener.onTabReselect(position);
}
}
}
}
});
/** 每一个Tab的布局参数 */
LinearLayout.LayoutParams lp_tab = mTabSpaceEqual ?
new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f) :
new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
if (mTabWidth > 0) {
lp_tab = new LinearLayout.LayoutParams((int) mTabWidth, LayoutParams.MATCH_PARENT);
}
mTabsContainer.addView(tabView, position, lp_tab);
}
private void updateTabStyles() {
for (int i = 0; i < mTabCount; i++) {
View v = mTabsContainer.getChildAt(i);
// v.setPadding((int) mTabPadding, v.getPaddingTop(), (int) mTabPadding, v.getPaddingBottom());
TextView tv_tab_title = (TextView) v.findViewById(R.id.tv_tab_title);
if (tv_tab_title != null) {
tv_tab_title.setTextColor(i == mCurrentTab ? mTextSelectColor : mTextUnselectColor);
tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextsize);
tv_tab_title.setPadding((int) mTabPadding, 0, (int) mTabPadding, 0);
if (mTextAllCaps) {
tv_tab_title.setText(tv_tab_title.getText().toString().toUpperCase());
}
if (mTextBold == TEXT_BOLD_BOTH) {
tv_tab_title.getPaint().setFakeBoldText(true);
} else if (mTextBold == TEXT_BOLD_NONE) {
tv_tab_title.getPaint().setFakeBoldText(false);
}
}
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
/**
* position:当前View的位置
* mCurrentPositionOffset:当前View的偏移量比例.[0,1)
*/
this.mCurrentTab = position;
this.mCurrentPositionOffset = positionOffset;
scrollToCurrentTab();
invalidate();
}
@Override
public void onPageSelected(int position) {
updateTabSelection(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
/** HorizontalScrollView滚到当前tab,并且居中显示 */
private void scrollToCurrentTab() {
if (mTabCount <= 0) {
return;
}
int offset = (int) (mCurrentPositionOffset * mTabsContainer.getChildAt(mCurrentTab).getWidth());
/**当前Tab的left+当前Tab的Width乘以positionOffset*/
int newScrollX = mTabsContainer.getChildAt(mCurrentTab).getLeft() + offset;
if (mCurrentTab > 0 || offset > 0) {
/**HorizontalScrollView移动到当前tab,并居中*/
newScrollX -= getWidth() / 2 - getPaddingLeft();
calcIndicatorRect();
newScrollX += ((mTabRect.right - mTabRect.left) / 2);
}
if (newScrollX != mLastScrollX) {
mLastScrollX = newScrollX;
/** scrollTo(int x,int y):x,y代表的不是坐标点,而是偏移量
* x:表示离起始位置的x水平方向的偏移量
* y:表示离起始位置的y垂直方向的偏移量
*/
scrollTo(newScrollX, 0);
}
}
private void updateTabSelection(int position) {
for (int i = 0; i < mTabCount; ++i) {
View tabView = mTabsContainer.getChildAt(i);
final boolean isSelect = i == position;
TextView tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
if (tab_title != null) {
tab_title.setTextColor(isSelect ? mTextSelectColor : mTextUnselectColor);
if (mTextBold == TEXT_BOLD_WHEN_SELECT) {
tab_title.getPaint().setFakeBoldText(isSelect);
}
}
}
}
private float margin;
private void calcIndicatorRect() {
View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab);
float left = currentTabView.getLeft();
float right = currentTabView.getRight();
//for mIndicatorWidthEqualTitle
if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) {
TextView tab_title = (TextView) currentTabView.findViewById(R.id.tv_tab_title);
mTextPaint.setTextSize(mTextsize);
float textWidth = mTextPaint.measureText(tab_title.getText().toString());
margin = (right - left - textWidth) / 2;
}
if (this.mCurrentTab < mTabCount - 1) {
View nextTabView = mTabsContainer.getChildAt(this.mCurrentTab + 1);
float nextTabLeft = nextTabView.getLeft();
float nextTabRight = nextTabView.getRight();
left = left + mCurrentPositionOffset * (nextTabLeft - left);
right = right + mCurrentPositionOffset * (nextTabRight - right);
//for mIndicatorWidthEqualTitle
if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) {
TextView next_tab_title = (TextView) nextTabView.findViewById(R.id.tv_tab_title);
mTextPaint.setTextSize(mTextsize);
float nextTextWidth = mTextPaint.measureText(next_tab_title.getText().toString());
float nextMargin = (nextTabRight - nextTabLeft - nextTextWidth) / 2;
margin = margin + mCurrentPositionOffset * (nextMargin - margin);
}
}
mIndicatorRect.left = (int) left;
mIndicatorRect.right = (int) right;
//for mIndicatorWidthEqualTitle
if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) {
mIndicatorRect.left = (int) (left + margin - 1);
mIndicatorRect.right = (int) (right - margin - 1);
}
mTabRect.left = (int) left;
mTabRect.right = (int) right;
if (mIndicatorWidth < 0) { //indicatorWidth小于0时,原jpardogo's PagerSlidingTabStrip
} else {//indicatorWidth大于0时,圆角矩形以及三角形
float indicatorLeft = currentTabView.getLeft() + (currentTabView.getWidth() - mIndicatorWidth) / 2;
if (this.mCurrentTab < mTabCount - 1) {
View nextTab = mTabsContainer.getChildAt(this.mCurrentTab + 1);
indicatorLeft = indicatorLeft + mCurrentPositionOffset * (currentTabView.getWidth() / 2 + nextTab.getWidth() / 2);
}
mIndicatorRect.left = (int) indicatorLeft;
mIndicatorRect.right = (int) (mIndicatorRect.left + mIndicatorWidth);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isInEditMode() || mTabCount <= 0) {
return;
}
int height = getHeight();
int paddingLeft = getPaddingLeft();
// draw divider
if (mDividerWidth > 0) {
mDividerPaint.setStrokeWidth(mDividerWidth);
mDividerPaint.setColor(mDividerColor);
for (int i = 0; i < mTabCount - 1; i++) {
View tab = mTabsContainer.getChildAt(i);
canvas.drawLine(paddingLeft + tab.getRight(), mDividerPadding, paddingLeft + tab.getRight(), height - mDividerPadding, mDividerPaint);
}
}
// draw underline
if (mUnderlineHeight > 0) {
mRectPaint.setColor(mUnderlineColor);
if (mUnderlineGravity == Gravity.BOTTOM) {
canvas.drawRect(paddingLeft, height - mUnderlineHeight, mTabsContainer.getWidth() + paddingLeft, height, mRectPaint);
} else {
canvas.drawRect(paddingLeft, 0, mTabsContainer.getWidth() + paddingLeft, mUnderlineHeight, mRectPaint);
}
}
//draw indicator line
calcIndicatorRect();
if (mIndicatorStyle == STYLE_TRIANGLE) {
if (mIndicatorHeight > 0) {
mTrianglePaint.setColor(mIndicatorColor);
mTrianglePath.reset();
mTrianglePath.moveTo(paddingLeft + mIndicatorRect.left, height);
mTrianglePath.lineTo(paddingLeft + mIndicatorRect.left / 2 + mIndicatorRect.right / 2, height - mIndicatorHeight);
mTrianglePath.lineTo(paddingLeft + mIndicatorRect.right, height);
mTrianglePath.close();
canvas.drawPath(mTrianglePath, mTrianglePaint);
}
} else if (mIndicatorStyle == STYLE_BLOCK) {
if (mIndicatorHeight < 0) {
mIndicatorHeight = height - mIndicatorMarginTop - mIndicatorMarginBottom;
} else {
}
if (mIndicatorHeight > 0) {
if (mIndicatorCornerRadius < 0 || mIndicatorCornerRadius > mIndicatorHeight / 2) {
mIndicatorCornerRadius = mIndicatorHeight / 2;
}
mIndicatorDrawable.setColor(mIndicatorColor);
mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left,
(int) mIndicatorMarginTop, (int) (paddingLeft + mIndicatorRect.right - mIndicatorMarginRight),
(int) (mIndicatorMarginTop + mIndicatorHeight));
mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius);
mIndicatorDrawable.draw(canvas);
}
} else {
/* mRectPaint.setColor(mIndicatorColor);
calcIndicatorRect();
canvas.drawRect(getPaddingLeft() + mIndicatorRect.left, getHeight() - mIndicatorHeight,
mIndicatorRect.right + getPaddingLeft(), getHeight(), mRectPaint);*/
if (mIndicatorHeight > 0) {
mIndicatorDrawable.setColor(mIndicatorColor);
if (mIndicatorGravity == Gravity.BOTTOM) {
mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left,
height - (int) mIndicatorHeight - (int) mIndicatorMarginBottom,
paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight,
height - (int) mIndicatorMarginBottom);
} else {
mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left,
(int) mIndicatorMarginTop,
paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight,
(int) mIndicatorHeight + (int) mIndicatorMarginTop);
}
mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius);
mIndicatorDrawable.draw(canvas);
}
}
}
//setter and getter
public void setCurrentTab(int currentTab) {
this.mCurrentTab = currentTab;
mViewPager.setCurrentItem(currentTab);
}
public void setCurrentTab(int currentTab, boolean smoothScroll) {
this.mCurrentTab = currentTab;
mViewPager.setCurrentItem(currentTab, smoothScroll);
}
public void setIndicatorStyle(int indicatorStyle) {
this.mIndicatorStyle = indicatorStyle;
invalidate();
}
public void setTabPadding(float tabPadding) {
this.mTabPadding = dp2px(tabPadding);
updateTabStyles();
}
public void setTabSpaceEqual(boolean tabSpaceEqual) {
this.mTabSpaceEqual = tabSpaceEqual;
updateTabStyles();
}
public void setTabWidth(float tabWidth) {
this.mTabWidth = dp2px(tabWidth);
updateTabStyles();
}
public void setIndicatorColor(int indicatorColor) {
this.mIndicatorColor = indicatorColor;
invalidate();
}
public void setIndicatorHeight(float indicatorHeight) {
this.mIndicatorHeight = dp2px(indicatorHeight);
invalidate();
}
public void setIndicatorWidth(float indicatorWidth) {
this.mIndicatorWidth = dp2px(indicatorWidth);
invalidate();
}
public void setIndicatorCornerRadius(float indicatorCornerRadius) {
this.mIndicatorCornerRadius = dp2px(indicatorCornerRadius);
invalidate();
}
public void setIndicatorGravity(int indicatorGravity) {
this.mIndicatorGravity = indicatorGravity;
invalidate();
}
public void setIndicatorMargin(float indicatorMarginLeft, float indicatorMarginTop,
float indicatorMarginRight, float indicatorMarginBottom) {
this.mIndicatorMarginLeft = dp2px(indicatorMarginLeft);
this.mIndicatorMarginTop = dp2px(indicatorMarginTop);
this.mIndicatorMarginRight = dp2px(indicatorMarginRight);
this.mIndicatorMarginBottom = dp2px(indicatorMarginBottom);
invalidate();
}
public void setIndicatorWidthEqualTitle(boolean indicatorWidthEqualTitle) {
this.mIndicatorWidthEqualTitle = indicatorWidthEqualTitle;
invalidate();
}
public void setUnderlineColor(int underlineColor) {
this.mUnderlineColor = underlineColor;
invalidate();
}
public void setUnderlineHeight(float underlineHeight) {
this.mUnderlineHeight = dp2px(underlineHeight);
invalidate();
}
public void setUnderlineGravity(int underlineGravity) {
this.mUnderlineGravity = underlineGravity;
invalidate();
}
public void setDividerColor(int dividerColor) {
this.mDividerColor = dividerColor;
invalidate();
}
public void setDividerWidth(float dividerWidth) {
this.mDividerWidth = dp2px(dividerWidth);
invalidate();
}
public void setDividerPadding(float dividerPadding) {
this.mDividerPadding = dp2px(dividerPadding);
invalidate();
}
public void setTextsize(float textsize) {
this.mTextsize = sp2px(textsize);
updateTabStyles();
}
public void setTextSelectColor(int textSelectColor) {
this.mTextSelectColor = textSelectColor;
updateTabStyles();
}
public void setTextUnselectColor(int textUnselectColor) {
this.mTextUnselectColor = textUnselectColor;
updateTabStyles();
}
public void setTextBold(int textBold) {
this.mTextBold = textBold;
updateTabStyles();
}
public void setTextAllCaps(boolean textAllCaps) {
this.mTextAllCaps = textAllCaps;
updateTabStyles();
}
public void setSnapOnTabClick(boolean snapOnTabClick) {
mSnapOnTabClick = snapOnTabClick;
}
public int getTabCount() {
return mTabCount;
}
public int getCurrentTab() {
return mCurrentTab;
}
public int getIndicatorStyle() {
return mIndicatorStyle;
}
public float getTabPadding() {
return mTabPadding;
}
public boolean isTabSpaceEqual() {
return mTabSpaceEqual;
}
public float getTabWidth() {
return mTabWidth;
}
public int getIndicatorColor() {
return mIndicatorColor;
}
public float getIndicatorHeight() {
return mIndicatorHeight;
}
public float getIndicatorWidth() {
return mIndicatorWidth;
}
public float getIndicatorCornerRadius() {
return mIndicatorCornerRadius;
}
public float getIndicatorMarginLeft() {
return mIndicatorMarginLeft;
}
public float getIndicatorMarginTop() {
return mIndicatorMarginTop;
}
public float getIndicatorMarginRight() {
return mIndicatorMarginRight;
}
public float getIndicatorMarginBottom() {
return mIndicatorMarginBottom;
}
public int getUnderlineColor() {
return mUnderlineColor;
}
public float getUnderlineHeight() {
return mUnderlineHeight;
}
public int getDividerColor() {
return mDividerColor;
}
public float getDividerWidth() {
return mDividerWidth;
}
public float getDividerPadding() {
return mDividerPadding;
}
public float getTextsize() {
return mTextsize;
}
public int getTextSelectColor() {
return mTextSelectColor;
}
public int getTextUnselectColor() {
return mTextUnselectColor;
}
public int getTextBold() {
return mTextBold;
}
public boolean isTextAllCaps() {
return mTextAllCaps;
}
public TextView getTitleView(int tab) {
View tabView = mTabsContainer.getChildAt(tab);
TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
return tv_tab_title;
}
//setter and getter
// show MsgTipView
private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private SparseArray<Boolean> mInitSetMap = new SparseArray<>();
/**
* 显示未读消息
*
* @param position 显示tab位置
* @param num num小于等于0显示红点,num大于0显示数字
*/
public void showMsg(int position, int num) {
if (position >= mTabCount) {
position = mTabCount - 1;
}
View tabView = mTabsContainer.getChildAt(position);
MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip);
if (tipView != null) {
UnreadMsgUtils.show(tipView, num);
if (mInitSetMap.get(position) != null && mInitSetMap.get(position)) {
return;
}
setMsgMargin(position, 4, 2);
mInitSetMap.put(position, true);
}
}
/**
* 显示未读红点
*
* @param position 显示tab位置
*/
public void showDot(int position) {
if (position >= mTabCount) {
position = mTabCount - 1;
}
showMsg(position, 0);
}
/** 隐藏未读消息 */
public void hideMsg(int position) {
if (position >= mTabCount) {
position = mTabCount - 1;
}
View tabView = mTabsContainer.getChildAt(position);
MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip);
if (tipView != null) {
tipView.setVisibility(View.GONE);
}
}
/** 设置未读消息偏移,原点为文字的右上角.当控件高度固定,消息提示位置易控制,显示效果佳 */
public void setMsgMargin(int position, float leftPadding, float bottomPadding) {
if (position >= mTabCount) {
position = mTabCount - 1;
}
View tabView = mTabsContainer.getChildAt(position);
MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip);
if (tipView != null) {
TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
mTextPaint.setTextSize(mTextsize);
float textWidth = mTextPaint.measureText(tv_tab_title.getText().toString());
float textHeight = mTextPaint.descent() - mTextPaint.ascent();
MarginLayoutParams lp = (MarginLayoutParams) tipView.getLayoutParams();
lp.leftMargin = mTabWidth >= 0 ? (int) (mTabWidth / 2 + textWidth / 2 + dp2px(leftPadding)) : (int) (mTabPadding + textWidth + dp2px(leftPadding));
lp.topMargin = mHeight > 0 ? (int) (mHeight - textHeight) / 2 - dp2px(bottomPadding) : 0;
tipView.setLayoutParams(lp);
}
}
/** 当前类只提供了少许设置未读消息属性的方法,可以通过该方法获取MsgView对象从而各种设置 */
public MsgView getMsgView(int position) {
if (position >= mTabCount) {
position = mTabCount - 1;
}
View tabView = mTabsContainer.getChildAt(position);
MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip);
return tipView;
}
private OnTabSelectListener mListener;
public void setOnTabSelectListener(OnTabSelectListener listener) {
this.mListener = listener;
}
class InnerPagerAdapter extends FragmentPagerAdapter {
private ArrayList<Fragment> fragments = new ArrayList<>();
private String[] titles;
public InnerPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragments, String[] titles) {
super(fm);
this.fragments = fragments;
this.titles = titles;
}
@Override
public int getCount() {
return fragments.size();
}
@Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// 覆写destroyItem并且空实现,这样每个Fragment中的视图就不会被销毁
// super.destroyItem(container, position, object);
}
@Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE;
}
}
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
bundle.putParcelable("instanceState", super.onSaveInstanceState());
bundle.putInt("mCurrentTab", mCurrentTab);
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
mCurrentTab = bundle.getInt("mCurrentTab");
state = bundle.getParcelable("instanceState");
if (mCurrentTab != 0 && mTabsContainer.getChildCount() > 0) {
updateTabSelection(mCurrentTab);
scrollToCurrentTab();
}
}
super.onRestoreInstanceState(state);
}
protected int dp2px(float dp) {
final float scale = mContext.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
protected int sp2px(float sp) {
final float scale = this.mContext.getResources().getDisplayMetrics().scaledDensity;
return (int) (sp * scale + 0.5f);
}
}