版权声明: https://blog.csdn.net/xu_coding/article/details/81224607
加载动画有很多,常见有转圈圈的,(主要是菊花图太难看了)。但是这种一般适合在屏幕中间显示,如果是下拉刷新这种,就需要使用某个动画来实现加载的动画效果。
这里分装了一个,还可以参考 天猫app刷新完成之后,控件消失的动画(此部分没实现 ,可以自己去绘制)。
效果图如下
public class LoadingView extends View {
private Paint paint;
private Context mcontext;
private int reacWidth;
private int ovalHeight; //椭圆高度
private int ovalHeightTop; //椭圆距离可动区域的高度
private int distance; //可以滑动的位置大小
private int mheight; //整个view高度
private int mwidth; //整个view宽度
private LoadingShape shape;
private ValueAnimator shapeAnimator;
private int centery; //中心点y轴高度 三角形或者方形 或者圆形 y轴上的最高点(最小y值) 如果需要修改,不让 动画每次都撞到控件边界可以修改,动画取值的范围。
private int minOvalWidth;
private boolean isUp = true;
public LoadingView(Context context) {
this(context,null);
}
public LoadingView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mcontext = context;
init();
initAnimator();
}
private void initAnimator() {
shapeAnimator =ValueAnimator.ofInt(distance,0);
shapeAnimator.setRepeatCount(-1);
shapeAnimator.setRepeatMode(ValueAnimator.REVERSE);
shapeAnimator.setDuration(500);
final TimeInterpolator upInterpolator = new DecelerateInterpolator(); //减速插值器
final TimeInterpolator downInterpolator = new AccelerateInterpolator();
shapeAnimator.setInterpolator(upInterpolator); //由于插值器是根据事件流失的百分比来影响值得,没办法做到快速下降,缓慢上升
shapeAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
isUp = true;
Log.d("xulc","onStart");
}
@Override
public void onAnimationEnd(Animator animation) {
Log.d("xulc","结束了");
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
isUp=!isUp;
if(isUp){ //切换图形
shapeAnimator.setInterpolator(upInterpolator);
switch(shape){
case CIR:
shape = LoadingShape.RECT;
break;
case RECT:
shape = LoadingShape.TRI;
break;
case TRI:
shape = LoadingShape.CIR;
break;
}
}else{
shapeAnimator.setInterpolator(downInterpolator);
}
}
});
shapeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
centery = (int)animation.getAnimatedValue();
invalidate();
}
});
shapeAnimator.start();
}
private void init() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLUE);
paint.setColor(mcontext.getResources().getColor(R.color.rect));
reacWidth = DensityUtil.dip2px(mcontext,20); //20dp
ovalHeight = DensityUtil.dip2px(mcontext,4); //椭圆高度
ovalHeightTop = DensityUtil.dip2px(mcontext,10); //椭圆距离可动区域的高度
distance = DensityUtil.dip2px(mcontext,50); //可以滑动的位置大小
minOvalWidth = reacWidth/4;
centery = distance;
shape = LoadingShape.TRI;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = reacWidth;
int height = reacWidth+distance+ovalHeight+ovalHeightTop;
setMeasuredDimension(width,height);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mwidth = w;
mheight = h;
}
@Override
protected void onDraw(Canvas canvas) {
switch(shape){
case CIR:
paint.setColor(getResources().getColor(R.color.circle));
canvas.drawCircle(mwidth/2,centery+mwidth/2,mwidth/2,paint);
break;
case TRI:
Path triPath = new Path();
paint.setColor(getResources().getColor(R.color.triangle));
triPath.moveTo(0,centery+reacWidth);
triPath.lineTo(reacWidth,centery+reacWidth);
triPath.lineTo(reacWidth/2,centery);
triPath.close();
canvas.drawPath(triPath,paint);
break;
case RECT:
paint.setColor(getResources().getColor(R.color.rect));
canvas.drawRect(0,centery,mwidth,centery+reacWidth,paint);
break;
}
paint.setColor(getResources().getColor(R.color.color_666666));
int startx = (int)(((mwidth - minOvalWidth)/2.0f)*((distance-centery)*1.0f/distance));
canvas.drawOval(startx,mheight-ovalHeight,mwidth-startx,mheight,paint); //centery 减小 //向上的过程中缩小
//减去这个得到实际显示的宽度
super.onDraw(canvas);
}
private enum LoadingShape{
TRI,RECT,CIR
}
}
当前的loadingView 适合放在下拉刷新的位置。