自定义LoadingView

始终相信一句话:书读百遍,其义自见。代码敲多了,自然而然就明白了。加油!
效果图如下:


自定义LoadingView_第1张图片
LoadingView.gif

1、加载动画效果分析:
1.1自定义一个图形变换的控件(WaitingAnim)用于由圆形、正方形、三角形相互变换。
1.2写改动画禁止状态的布局,用户加载到自定义ViewGroup中去。
1.3自定义ViewGroup实现动画
2、废话少说,上代码:
2.1自定义WaitingAnim代码如下:

public class WaitingAnim extends View {

    private int mCircleColor= Color.BLUE;
    private int mSquareColor = Color.GREEN;
    private int mTriangleColor = Color.RED;



    private Shape mCurrentShape=Shape.Circle;
    private Paint mPaint;
    private Path mPath;


    public WaitingAnim(Context context) {
        this(context,null);
    }

    public WaitingAnim(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.WaitingAnim);
        mCircleColor=array.getColor(R.styleable.WaitingAnim_CircleColor,mCircleColor);
        mSquareColor=array.getColor(R.styleable.WaitingAnim_SquareColor,mSquareColor);
        mTriangleColor=array.getColor(R.styleable.WaitingAnim_TriangleColor,mTriangleColor);
        array.recycle();
        init();
    }

    public WaitingAnim(Context context, AttributeSet attrs) {
        this(context, attrs,0);

    }
    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(mCircleColor);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        /*测量模式*/
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        /*测量尺寸*/
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        //widthMode==MeasureSpec.AT_MOST 说明width height在布局中设置得是wrap_content
        if (widthMode==MeasureSpec.AT_MOST||heightMode==MeasureSpec.AT_MOST){
            widthSize=20;
            heightSize=20;
        }
        /*如果用户设置宽高不一致时*/
        if (widthSize!=heightSize){
            widthSize=widthSize>heightSize?heightSize:widthSize;
            heightSize=widthSize>heightSize?heightSize:widthSize;
        }
        setMeasuredDimension(widthSize,heightSize);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        switch (mCurrentShape){
            /*画圆*/
            case Circle:
                mPaint.setColor(mCircleColor);
                canvas.drawCircle(getWidth()/2,getHeight()/2,getWidth()/2,mPaint);
                break;
            /*画矩形*/
            case Square:
                mPaint.setColor(mSquareColor);
                Rect rect = new Rect(0,0,getWidth(),getHeight());

                canvas.drawRect(rect,mPaint);
                break;
            /*画三角形*/
            case Triangle:
                // 画三角  Path 画路线
                mPaint.setColor(Color.RED);
                if (mPath == null) {
                    // 画路径
                    mPath = new Path();
                    mPath.moveTo(getWidth() / 2, 0);
                    mPath.lineTo(0, (float) ((getWidth()/2)*Math.sqrt(3)));
                    mPath.lineTo(getWidth(), (float) ((getWidth()/2)*Math.sqrt(3)));
                    // path.lineTo(getWidth()/2,0);
                    mPath.close();// 把路径闭合
                }
                canvas.drawPath(mPath, mPaint);
            break;
        }
    }
    public void exchange(){
        switch (mCurrentShape){
            case Circle:
                mCurrentShape=Shape.Square;
                break;
            case Square:
                mCurrentShape=Shape.Triangle;
                break;
            case Triangle:
                mCurrentShape=Shape.Circle;
                break;
        }
        invalidate();
    }
    public enum Shape{
        Circle,Square,Triangle;
    }
    public Shape getmCurrentShape() {
        return mCurrentShape;
    }
}

2.2自定义ViewGroup(LoadingView)代码如下:

public class LoadingView extends LinearLayout {
    private WaitingAnim waitingAnim;
    private View shade;
    private int mTranslationDistance;
    private int AnimaDuration=350;
    private boolean isStopAnimator=false;
    public LoadingView(Context context) {
        this(context,null);
    }
    public LoadingView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }
    public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        initLayout(context);
    }
    /**
     * 初始化加载
     */
    private void initLayout(Context context) {
        //1、写好的布局,加载进来
        //1.1实例化View
//        View loadView = inflate(getContext(),R.layout.ui_loadingview,null);
        //this代表把这个布局加载到LoadingView中
        View loadView = inflate(getContext(),R.layout.ui_loadingview,this);
        waitingAnim = (WaitingAnim) findViewById(R.id.waitingAnim);
        shade = (View) findViewById(R.id.shade);
        mTranslationDistance=Densityuitl.dip2px(context,80);
        /*写在里表示在onResume里面执行*/
        post(new Runnable() {
            @Override
            public void run() {
            startFallAninmator();
            }
        });
        /*写在这里表示在onCreatView里面执行*/
//        startFallAninmator();
    }
    /**
     * 下落的动画
     */
    public void startFallAninmator() {
        Log.e("TAG","startFallAninmator");
        if (isStopAnimator) {
            return;
        }
        //下落的位移动画
        ObjectAnimator translationAninamator=ObjectAnimator.ofFloat(waitingAnim,"translationY",0,mTranslationDistance);
//        translationAninamator.setDuration(AnimaDuration);
//        translationAninamator.start();
        //中间阴影缩小
        ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(shade,"scaleX",1f,0.3f);
//        scaleAnimator.setDuration(AnimaDuration);
//        scaleAnimator.start();
        //动画的集合
        AnimatorSet set = new AnimatorSet();
        set.setDuration(AnimaDuration);
        set.playTogether(translationAninamator,scaleAnimator);
        /*匀加速*/
        set.setInterpolator(new AccelerateInterpolator());
        //下落完成之后就开始上抛了
        set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                /*切换图片*/
                waitingAnim.exchange();
                startUpAnimator();
            }
        });
        set.start();
    }
    private void startUpAnimator() {
        if (isStopAnimator) {
            return;
        }
        //上抛的位移动画
        ObjectAnimator translationAninamator=ObjectAnimator.ofFloat(waitingAnim,"translationY",mTranslationDistance,0);
//        translationAninamator.setDuration(AnimaDuration);
//        translationAninamator.start();

        //中间阴影缩小
        ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(shade,"scaleX",0.3f,1f);
//        scaleAnimator.setDuration(AnimaDuration);
//        scaleAnimator.start();
        /*动画的集合*/
        AnimatorSet set = new AnimatorSet();
        set.setDuration(AnimaDuration);
        set.playTogether(translationAninamator,scaleAnimator);
        /*匀减速*/
        set.setInterpolator(new DecelerateInterpolator());
        //下落完成之后就开始上抛了
        set.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                startFallAninmator();
            }
            @Override
            public void onAnimationStart(Animator animation) {
                startRotationAnimator();
            }
        });
        set.start();
    }
    /**
     * 旋转的动画
     */
    private void startRotationAnimator() {
        if (isStopAnimator) {
            return;
        }
        ObjectAnimator rotationAnimator = null;
        switch (waitingAnim.getmCurrentShape()){
            case Circle:
            case Square:
                rotationAnimator=ObjectAnimator.ofFloat(waitingAnim,"rotation",0,180);
                break;
            case Triangle:
                rotationAnimator=ObjectAnimator.ofFloat(waitingAnim,"rotation",0,-180);
                break;
        }
        rotationAnimator.setDuration(AnimaDuration);
        rotationAnimator.setInterpolator(new DecelerateInterpolator());
        rotationAnimator.start();
    }
    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(View.INVISIBLE);//不再去摆放和计算,少走系统的源码
        /*清除动画*/
        waitingAnim.clearAnimation();
        shade.clearAnimation();
        /*从父布局已移除*/
        ViewGroup parent = (ViewGroup) getParent();
        if (parent!=null){
            parent.removeView(this);
            parent.removeAllViews();
        }
        isStopAnimator=true;
    }
}

最后,在Activity使用该自定义控件就好了,要是想让该自定义控件消失不显示,直接设置该控件为GONE。该自定义控件重写了setVisibility()方法。在方法中实现清除动画等操作。

你可能感兴趣的:(自定义LoadingView)