最近在项目中有用到Tab,Tab下面有个指示条,一般来说可以使用用官方的TabLayout做,但官方提供的Tab指示器太不灵活,没法做到更换任意图形,,,于是自己尝试弄一下了,
先看一下效果:
20200511203638.gif
再看一下如何使用:
//第一排
scrollIndicator = findViewById(R.id.scrollIndicatorone);
llParent = findViewById(R.id.ll_parentone);
//第二排
scrollIndicatorTwo = findViewById(R.id.scrollIndicatortwo);
llParentTwo = findViewById(R.id.ll_parenttwo);
//第一排
scrollIndicator
.setWith(20)
.setHigh(4)
.setColor(ContextCompat.getColor(this, R.color.colorAccent))
.setViewGroup(llParent)
.setPosition(0);
//第二排
scrollIndicatorTwo
//宽
.setWith(40)
//高
.setHigh(4)
//圆角
.setRound(10)
//颜色
.setColor(ContextCompat.getColor(this, R.color.colorAccent))
//文字父容器
.setViewGroup(llParentTwo)
//初始显示
.setPosition(0);
scrollIndicator就是自定义的指示器,使用的时候可以设置宽度,高度,圆角,颜色等,基本满足我这项目的需求,当然,光是这样的话和官方的区别也不大, 但这个最灵活的就是scrollIndicator继承自View,可以在onDraw中任意改变形状,可以变三角形,变水滴, 变五角形,任何形状都是可以绘制的, 而且scrollIndicator和显示的文字是分离的,没有一点耦合,可以随意增删,关联只需调用
//文字父容器
.setViewGroup(llParentTwo)
将文字的父容器传进去即可,再加上属性动画,感觉也还可以。。。。
下面帖一下全部代码:
public class ScrollIndicator extends View {
private Paint paint;
private int with;
private int high;
private int round;
private RectF rectF;
private ViewGroup viewGroup;
private int startWith;
private int color;
private int defaulteWith;
private int defaulteHigh;
//父容器是否加载完
private boolean isLoad;
public ScrollIndicator(Context context) {
super(context);
init();
}
public ScrollIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ScrollIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(1);
paint.setAntiAlias(true);
paint.setDither(true);
rectF = new RectF();
defaulteWith = SizeUtils.dp2px(20);
defaulteHigh = SizeUtils.dp2px(4);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(color);
rectF.set(startWith, 0,startWith + with, high);
canvas.drawRoundRect(rectF, round, round, paint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int withModel = MeasureSpec.getMode(widthMeasureSpec);
int highModel = MeasureSpec.getMode(widthMeasureSpec);
int specWith = MeasureSpec.getSize(widthMeasureSpec);
int specHigh = MeasureSpec.getSize(heightMeasureSpec);
int currentWith;
int currentHigh;
switch (withModel){
case MeasureSpec.AT_MOST:
currentWith = defaulteWith;
break;
case MeasureSpec.EXACTLY:
default:
currentWith = specWith;
break;
}
switch (highModel){
case MeasureSpec.AT_MOST:
currentHigh = defaulteHigh;
break;
case MeasureSpec.EXACTLY:
default:
currentHigh = specHigh;
break;
}
setMeasuredDimension(currentWith, currentHigh);
}
public ScrollIndicator setWith(int with){
this.with = SizeUtils.dp2px(with);
return this;
}
public ScrollIndicator setHigh(int high){
this.high = SizeUtils.dp2px(high);
return this;
}
public ScrollIndicator setColor(int color){
this.color = color;
return this;
}
public ScrollIndicator setRound(int round){
this.round = SizeUtils.dp2px(round);
return this;
}
public ScrollIndicator setViewGroup(ViewGroup viewGroup){
this.viewGroup = viewGroup;
return this;
}
public void setPosition(final int position){
if(isLoad){
int listCenter = (viewGroup.getChildAt(position).getRight() + viewGroup.getChildAt(position).getLeft())/2;
int endWith = listCenter - with/2;
startAnim(startWith,endWith);
startWith = listCenter - with/2;
}else{
viewGroup.postDelayed(new Runnable() {
@Override
public void run() {
int listCenter = (viewGroup.getChildAt(position).getRight() + viewGroup.getChildAt(position).getLeft())/2;
int endWith = listCenter - with/2;
startAnim(startWith,endWith);
startWith = listCenter - with/2;
isLoad = true;
}
},100);
}
}
public void startAnim(int startWith, int endwith){
ValueAnimator valueAnimator = ValueAnimator.ofInt(startWith, endwith);
valueAnimator.setDuration(100);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
ScrollIndicator.this.startWith = (int) animation.getAnimatedValue();
postInvalidate();
}
});
valueAnimator.start();
}
}
完。
网友评论