推荐这个库,很好用!
https://github.com/hackware1993/MagicIndicator
基于该库做的封装,以备之后用到
需求有点特别,颜色扩展是为了以备其他页面用到,最重要的是位置扩展,一般的指示器是在底部居中,如下图(该库中的界面):
而我们的设计稿是这样的:(靠左居中)
所以做了下列扩展,真心说,这个库真不错!扩展也很多!
1 颜色扩展
/**
* 设置tab标题的 正常状态 颜色,在 initView() 之前调用,否则不生效
* 不设置则使用默认颜色
*/
fun setColorNormal(color: String){
color_title_normal = color
invalidate()
}
/**
* 设置tab标题的 选中状态 颜色,在 initView() 之前调用,否则不生效
* 不设置则使用默认颜色
*/
fun setColorSelected(color: String){
color_title_selected = color
invalidate()
}
/**
* 设置指示器颜色,在 initView() 之前调用,否则不生效
* 不设置则使用默认颜色
*/
fun setColorLine(color: String){
color_line = color
invalidate()
}
2 位置扩展 LinePagerIndicator
// 修改了最终绘制的矩形区域,以达到移动的目的
private int transToLeft = 0;
private int transToTop = 0;
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
...
this.mLineRect.left = leftX + (nextLeftX - leftX) * this.mStartInterpolator.getInterpolation(positionOffset) + transToLeft;
this.mLineRect.right = rightX + (nextRightX - rightX) * this.mEndInterpolator.getInterpolation(positionOffset) + transToLeft;
this.mLineRect.top = (float) this.getHeight() - this.mLineHeight - this.mYOffset + transToTop;
this.mLineRect.bottom = (float) this.getHeight() - this.mYOffset + transToTop ;
this.invalidate();
}
}
另外要说一下,一开始我打算继承 LinePagerIndicator ,进行修改。
最后发现一个简单方法,聊以记录:
- 1 找到要修改的文件LinePagerIndicator,因为在jar包中,无法直接修改,
- 2 可以直接复制该类全部代码,新建一个类并粘贴
- 3 在使用该类的地方,去除原来jar包中的引用,就可以直接使用新类了
- 4 现在就可以直接对新建的类进行修改了(我的位置扩展就是在新类中修改的)
代码
1 View封装,暴露设置正常状态与选中状态颜色的方法
/**
*
* author : jake
* time : 2018/05/08
* function : 动效切换效果的tabView,可以通过传参改变相关颜色及便签内容
* version: 1.0
*
*/
class AllCourseTabView(context: Context?, attrs: AttributeSet? = null) : MagicIndicator(context, attrs) {
// 标题颜色
private var color_title_normal = "#787878"
private var color_title_selected = "#180438"
// 指示器颜色
private var color_line = "#F5A623"
/**
* 设置tab标题的 正常状态 颜色,在 initView() 之前调用,否则不生效
* 不设置则使用默认颜色
*/
fun setColorNormal(color: String){
color_title_normal = color
invalidate()
}
/**
* 设置tab标题的 选中状态 颜色,在 initView() 之前调用,否则不生效
* 不设置则使用默认颜色
*/
fun setColorSelected(color: String){
color_title_selected = color
invalidate()
}
/**
* 设置指示器颜色,在 initView() 之前调用,否则不生效
* 不设置则使用默认颜色
*/
fun setColorLine(color: String){
color_line = color
invalidate()
}
/**
* mDataList 指Tab的标签名的集合
*/
fun initView(vp:ViewPager,mDataList:List?){
val magicIndicator = findViewById(R.id.tab_all_course) as MagicIndicator
magicIndicator.setBackgroundColor(Color.WHITE)
val commonNavigator = CommonNavigator(context)
commonNavigator.scrollPivotX = 0.65f
commonNavigator.adapter = object : CommonNavigatorAdapter() {
override fun getCount(): Int {
return if (mDataList == null) 0 else mDataList.size
}
override fun getTitleView(context: Context, index: Int): IPagerTitleView {
val simplePagerTitleView = ColorFlipPagerTitleView(context)
simplePagerTitleView.text = mDataList!![index]
simplePagerTitleView.textSize = 16f
simplePagerTitleView.normalColor = Color.parseColor(color_title_normal)
simplePagerTitleView.selectedColor = Color.parseColor(color_title_selected)
simplePagerTitleView.setOnClickListener {
vp.setCurrentItem(index)
}
return simplePagerTitleView
}
override fun getIndicator(context: Context): IPagerIndicator {
val indicator = LinePagerIndicator(context)
indicator.mode = LinePagerIndicator.MODE_EXACTLY
indicator.lineHeight = UIUtil.dip2px(context, 4.0).toFloat()
indicator.lineWidth = UIUtil.dip2px(context, 36.0).toFloat()
indicator.roundRadius = UIUtil.dip2px(context, 2.0).toFloat()
indicator.startInterpolator = AccelerateInterpolator() as Interpolator?
indicator.endInterpolator = DecelerateInterpolator(2.0f)
// 将线条向上移动16,不在底部
indicator.transToLeft = 20.dp
indicator.transToTop = 8.dp
indicator.setColors(Color.parseColor(color_line))
return indicator
}
}
magicIndicator.navigator = commonNavigator
ViewPagerHelper.bind(magicIndicator, vp)
}
}
2 设置指示器的位置,可以上下左右移动,而不是仅底部居中
/**
*
* author : jake
* time : 2018/05/08
* function : 暴露getTransToLeft & getTransToTop方法,可以调节指示器的位置(向右或向下输入负值)
* version: 1.0
*
*/
public class LinePagerIndicator extends View implements IPagerIndicator {
public static final int MODE_MATCH_EDGE = 0;
public static final int MODE_WRAP_CONTENT = 1;
public static final int MODE_EXACTLY = 2;
private int mMode;
private Interpolator mStartInterpolator = new LinearInterpolator();
private Interpolator mEndInterpolator = new LinearInterpolator();
private float mYOffset;
private float mLineHeight;
private float mXOffset;
private float mLineWidth;
private float mRoundRadius;
private Paint mPaint;
private List mPositionDataList;
private List mColors;
private RectF mLineRect = new RectF();
private int transToLeft = 0;
private int transToTop = 0;
public LinePagerIndicator(Context context) {
super(context);
this.init(context);
}
private void init(Context context) {
this.mPaint = new Paint(1);
this.mPaint.setStyle(Style.FILL);
this.mLineHeight = (float) UIUtil.dip2px(context, 3.0D);
this.mLineWidth = (float) UIUtil.dip2px(context, 10.0D);
}
protected void onDraw(Canvas canvas) {
canvas.drawRoundRect(this.mLineRect, this.mRoundRadius, this.mRoundRadius, this.mPaint);
}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (this.mPositionDataList != null && !this.mPositionDataList.isEmpty()) {
if (this.mColors != null && this.mColors.size() > 0) {
int currentColor = (Integer) this.mColors.get(Math.abs(position) % this.mColors.size());
int nextColor = (Integer) this.mColors.get(Math.abs(position + 1) % this.mColors.size());
int color = ArgbEvaluatorHolder.eval(positionOffset, currentColor, nextColor);
this.mPaint.setColor(color);
}
PositionData current = FragmentContainerHelper.getImitativePositionData(this.mPositionDataList, position);
PositionData next = FragmentContainerHelper.getImitativePositionData(this.mPositionDataList, position + 1);
float nextLeftX;
float rightX;
float nextRightX;
float leftX;
if (this.mMode == 0) {
leftX = (float) current.mLeft + this.mXOffset;
nextLeftX = (float) next.mLeft + this.mXOffset;
rightX = (float) current.mRight - this.mXOffset;
nextRightX = (float) next.mRight - this.mXOffset;
} else if (this.mMode == 1) {
leftX = (float) current.mContentLeft + this.mXOffset;
nextLeftX = (float) next.mContentLeft + this.mXOffset;
rightX = (float) current.mContentRight - this.mXOffset;
nextRightX = (float) next.mContentRight - this.mXOffset;
} else {
leftX = (float) current.mLeft + ((float) current.width() - this.mLineWidth) / 2.0F;
nextLeftX = (float) next.mLeft + ((float) next.width() - this.mLineWidth) / 2.0F;
rightX = (float) current.mLeft + ((float) current.width() + this.mLineWidth) / 2.0F;
nextRightX = (float) next.mLeft + ((float) next.width() + this.mLineWidth) / 2.0F;
}
this.mLineRect.left = leftX + (nextLeftX - leftX) * this.mStartInterpolator.getInterpolation(positionOffset) + transToLeft;
this.mLineRect.right = rightX + (nextRightX - rightX) * this.mEndInterpolator.getInterpolation(positionOffset) + transToLeft;
this.mLineRect.top = (float) this.getHeight() - this.mLineHeight - this.mYOffset + transToTop;
this.mLineRect.bottom = (float) this.getHeight() - this.mYOffset + transToTop ;
this.invalidate();
}
}
public void onPageSelected(int position) {
}
public void onPageScrollStateChanged(int state) {
}
public void onPositionDataProvide(List dataList) {
this.mPositionDataList = dataList;
}
public float getYOffset() {
return this.mYOffset;
}
public void setYOffset(float yOffset) {
this.mYOffset = yOffset;
}
public float getXOffset() {
return this.mXOffset;
}
public void setXOffset(float xOffset) {
this.mXOffset = xOffset;
}
public float getLineHeight() {
return this.mLineHeight;
}
public void setLineHeight(float lineHeight) {
this.mLineHeight = lineHeight;
}
public float getLineWidth() {
return this.mLineWidth;
}
public void setLineWidth(float lineWidth) {
this.mLineWidth = lineWidth;
}
public float getRoundRadius() {
return this.mRoundRadius;
}
public void setRoundRadius(float roundRadius) {
this.mRoundRadius = roundRadius;
}
public int getMode() {
return this.mMode;
}
public int getTransToLeft() { return transToLeft; }
public void setTransToLeft(int transToLeft) { this.transToLeft = transToLeft*(-1); }
public int getTransToTop() { return transToTop; }
public void setTransToTop(int transToTop) { this.transToTop = transToTop*(-1); }
public void setMode(int mode) {
if (mode != 2 && mode != 0 && mode != 1) {
throw new IllegalArgumentException("mode " + mode + " not supported.");
} else {
this.mMode = mode;
}
}
public Paint getPaint() {
return this.mPaint;
}
public List getColors() {
return this.mColors;
}
public void setColors(Integer... colors) {
this.mColors = Arrays.asList(colors);
}
public Interpolator getStartInterpolator() {
return this.mStartInterpolator;
}
public void setStartInterpolator(Interpolator startInterpolator) {
this.mStartInterpolator = startInterpolator;
if (this.mStartInterpolator == null) {
this.mStartInterpolator = new LinearInterpolator();
}
}
public Interpolator getEndInterpolator() {
return this.mEndInterpolator;
}
public void setEndInterpolator(Interpolator endInterpolator) {
this.mEndInterpolator = endInterpolator;
if (this.mEndInterpolator == null) {
this.mEndInterpolator = new LinearInterpolator();
}
}
}