自定义LoadingView

加载动画有很多,常见有转圈圈的,(主要是菊花图太难看了)。但是这种一般适合在屏幕中间显示,如果是下拉刷新这种,就需要使用某个动画来实现加载的动画效果。
这里分装了一个,还可以参考 天猫app刷新完成之后,控件消失的动画(此部分没实现 ,可以自己去绘制)。
效果图如下
自定义LoadingView_第1张图片

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 适合放在下拉刷新的位置。

你可能感兴趣的:(android)