一个以动画形式显示返回结果的对话框 (支持loading、打勾、打叉、感叹号)

大家一定看过支付宝支付成功时显示的那个打勾的动画,这次就带来这样一个控件,把动画封装成一个控件,再二次封装在对话

框里,调用时只需要写一句话,很方便。先看一下效果吧:  


                                                                


首先还是惯例的简单说一下原理吧。其实很简单,本质就是画一个图案,勾的图案就是画个圆弧,再画一段折线,其它图案同

理。然后所谓动画就是把这个图案绘制的过程一帧一帧迭代,这里直接用了系统提供的属性动画类ValueAnimator来实现迭代过

程。关于属性动画这里就不多说了,不了解的童鞋可以自行度娘。


废话了一堆,开始正题。这次的文件数量有点多,我们一个一个来。


我把loading、打勾、打叉、感叹号四个动画每一个单独封装成一个View的子类,分别叫LoadingView、SucceedView、

FailedView、WarningView。上本体:

LoadingView.java:

public class LoadingView extends View {
    private Context context;

    // 动画播放周期
    private int duration = 1000;

    // 动画控制器
    private Interpolator interpolator = new LinearInterpolator();

    // 是否正在播放loading动画
    private boolean isLoading;

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

    public LoadingView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public LoadingView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        this.context = context;

        setBackgroundDrawable(context.getResources().getDrawable(R.drawable.circle_loading));
    }

    /**
     * 开始播放动画
     */
    public void start() {
        if (isLoading) {
            return;
        }
        isLoading = true;
        RotateAnimation animation = new RotateAnimation(0, 360,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        animation.setDuration(duration);
        animation.setInterpolator(interpolator);
        animation.setRepeatCount(-1);
        startAnimation(animation);
    }

    /**
     * 停止播放动画
     */
    public void stop() {
        clearAnimation();
        isLoading = false;
    }

    /**
     * 设置动画播放周期
     * @param duration 播放周期,单位毫秒
     */
    public void setDuration(int duration) {
        this.duration = duration;
    }

    /**
     * 设置动画控制器
     * @param interpolator
     */
    public void setInterpolator(Interpolator interpolator) {
        this.interpolator = interpolator;
    }

    /**
     * 获取是否正在播放loading动画
     * @return
     */
    public boolean isLoading() {
        return isLoading;
    }
}

SucceedView.java:

public class SucceedView extends View {
    private Context context;

    private int width;
    private int height;
    private int radius;

    private float startX;
    private float startY;
    private float middleX;
    private float middleY;
    private float endX;
    private float endY;

    // 图案线宽
    private int lineWidth;

    // 图案线颜色
    private int lineColor = Color.parseColor("#ADE584");

    // 动画播放时间
    private int duration = 1500;

    // 动画控制器
    private Interpolator interpolator = new AccelerateDecelerateInterpolator();

    private Paint circlePaint;
    private Paint linePaint;
    private float progress;
    private boolean isDraw;

    // 动画播放回调
    private OnShowAnimationListener listener;

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

    public SucceedView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public SucceedView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
    }

    private void init() {
        if (lineWidth == 0) lineWidth = dp2px(3);

        if (circlePaint == null) circlePaint = new Paint();
        circlePaint.setStrokeWidth(lineWidth);
        circlePaint.setColor(lineColor);
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setAntiAlias(true);
        circlePaint.setStrokeCap(Paint.Cap.ROUND);

        if (linePaint == null) linePaint = new Paint();
        linePaint.setStrokeWidth(1.5f * lineWidth);
        linePaint.setColor(lineColor);
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setAntiAlias(true);
        linePaint.setStrokeCap(Paint.Cap.ROUND);

        startX = lineWidth / 2 + radius * 2 / 5;
        startY = lineWidth / 2 + radius;
        middleX = lineWidth / 2 + radius - 2 * lineWidth;
        middleY = lineWidth / 2 + radius * 7 / 5;
        endX = lineWidth / 2 + radius + radius * (float) Math.cos(2 * Math.PI * 37.5 / 360);
        endY = lineWidth + radius - radius * (float) Math.sin(2 * Math.PI * 37.5 / 360);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        width = getMeasuredWidth();
        height = width;
        radius = (width / 2 - lineWidth / 2);
        getLayoutParams().height = height;
        init();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        doDraw(canvas);
    }

    /**
     * 绘制图案
     *
     * @param canvas
     */
    private void doDraw(Canvas canvas) {
        if (progress > 0) {
            // 画外面的圈
            if (progress <= 0.5) {
                canvas.drawArc(new RectF(lineWidth / 2, lineWidth / 2, width - lineWidth / 2, height - lineWidth / 2), -60, -315 * (progress / (float) 0.6), false, circlePaint);
                // 画勾的左半部分
            } else if (progress <= 0.7) {
                canvas.drawArc(new RectF(lineWidth / 2, lineWidth / 2, width - lineWidth / 2, height - lineWidth / 2), -60, -315, false, circlePaint);
                canvas.drawLine(startX, startY, startX + (middleX - startX) * (progress - 0.5f) / 0.2f, startY + (middleY - startY) * (progress - 0.5f) / 0.2f, linePaint);
                // 画勾的右半部分
            } else {
                canvas.drawArc(new RectF(lineWidth / 2, lineWidth / 2, width - lineWidth / 2, height - lineWidth / 2), -60, -315, false, circlePaint);
                canvas.drawLine(startX, startY, middleX, middleY, linePaint);
                canvas.drawLine(middleX, middleY, middleX + (endX - middleX) * (progress - 0.7f) / 0.3f, middleY + (endY - middleY) * (progress - 0.7f) / 0.3f, linePaint);
            }
        }
    }

    /**
     * 开始播放动画
     */
    public void start() {
        if (isDraw) {
            return;
        }
        isDraw = true;
        ValueAnimator animator = new ValueAnimator().ofFloat(0, 1, 1);
        animator.setDuration(duration);
        animator.setInterpolator(interpolator);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                if (isDraw) {
                    progress = (float) animation.getAnimatedValue();
                    invalidate();
                }
            }
        });
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                if (listener != null) listener.onStart();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                super.onAnimationCancel(animation);
                isDraw = false;
                if (listener != null) listener.onCancel();
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                isDraw = false;
                if (listener != null) listener.onFinish();
            }
        });
        animator.start();
    }

    /**
     * 停止播放动画方法
     */
    public void stop() {
        isDraw = false;
    }

    /**
     * 清除动画及图案
     */
    public void clear() {
        isDraw = false;
        progress = 0;
        invalidate();
    }

    /**
     * 设置动画播放时间
     *
     * @param duration 播放时间,单位毫秒
     */
    public void setDuration(int duration) {
        this.duration = duration;
    }

    /**
     * 设置图案线颜色
     *
     * @param lineColor 颜色值
     */
    public void setLineColor(int lineColor) {
        this.lineColor = lineColor;
    }

    /**
     * 设置图案线宽
     *
     * @param lineWidth 线宽,单位dp
     */
    public void setLineWidth(int lineWidth) {
        this.lineWidth = dp2px(lineWidth);
    }

    /**
     * 设置动画控制器
     *
     * @param interpolator
     */
    public void setInterpolator(Interpolator interpolator) {
        this.interpolator = interpolator;
    }

    /**
     * 设置动画回调接口
     *
     * @param listener
     */
    public void setOnShowAnimationListener(OnShowAnimationListener listener) {
        this.listener = listener;
    }

    /**
     * 动画回调接口
     */
    public interface OnShowAnimationListener {
        /**
         * 动画开始播放时回调
         */
        void onStart();

        /**
         * 动画播放结束时回调
         */
        void onFinish();

        /**
         * 动画播放取消时回调
         */
        void onCancel();
    }

    private int dp2px(float dipValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }
}

FailedView.java:

public class FailedView extends View {
    private Context context;

    private int width;
    private int height;
    private int radius;

    private float leftStartX;
    private float leftStartY;
    private float leftEndX;
    private float leftEndY;
    private float rightStartX;
    private float rightStartY;
    private float rightEndX;
    private float rightEndY;
    private float length;

    // 图案线宽
    private int lineWidth;

    // 动画线颜色
    private int lineColor = Color.parseColor("#fc5c63");

    // 红叉端点到边界的距离
    private int magin;

    // 动画播放时间
    private int duration = 1500;

    // 动画控制器
    private Interpolator interpolator = new AccelerateDecelerateInterpolator();

    private Paint circlePaint;
    private Paint linePaint;
    private float progress;
    private boolean isDraw;

    // 动画播放回调
    private OnShowAnimationListener listener;

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

    public FailedView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public FailedView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
    }

    private void init() {
        if (lineWidth == 0) lineWidth = dp2px(3);
        if (magin == 0) magin = dp2px(6);

        if (circlePaint == null) circlePaint = new Paint();
        circlePaint.setStrokeWidth(lineWidth);
        circlePaint.setColor(lineColor);
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setAntiAlias(true);
        circlePaint.setStrokeCap(Paint.Cap.ROUND);

        if (linePaint == null) linePaint = new Paint();
        linePaint.setStrokeWidth(1.5f * lineWidth);
        linePaint.setColor(lineColor);
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setAntiAlias(true);
        linePaint.setStrokeCap(Paint.Cap.ROUND);

        length = 2 * radius - lineWidth - 2 * magin;
        leftStartX = width / 2 - length / 2 * (float) Math.cos(Math.PI / 4);
        leftStartY = height / 2 - length / 2 * (float) Math.sin(Math.PI / 4);
        leftEndX = width / 2 + length / 2 * (float) Math.cos(Math.PI / 4);
        leftEndY = height / 2 + length / 2 * (float) Math.sin(Math.PI / 4);
        rightStartX = width / 2 + length / 2 * (float) Math.cos(Math.PI / 4);
        rightStartY = height / 2 - length / 2 * (float) Math.sin(Math.PI / 4);
        rightEndX = width / 2 - length / 2 * (float) Math.cos(Math.PI / 4);
        rightEndY = height / 2 + length / 2 * (float) Math.sin(Math.PI / 4);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        width = getMeasuredWidth();
        height = width;
        radius = (width / 2 - lineWidth / 2);
        getLayoutParams().height = height;
        init();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        doDraw(canvas);
    }

    /**
     * 绘制图案
     *
     * @param canvas
     */
    private void doDraw(Canvas canvas) {
        if (progress > 0) {
            // 画圆圈
            if (progress <= 0.5) {
                canvas.drawArc(new RectF(lineWidth / 2, lineWidth / 2, width - lineWidth / 2, height - lineWidth / 2), -90, -360 * (progress / (float) 0.5), false, circlePaint);
                // 画红叉左上到右下的线
            } else if (progress <= 0.75) {
                canvas.drawArc(new RectF(lineWidth / 2, lineWidth / 2, width - lineWidth / 2, height - lineWidth / 2), -90, -360, false, circlePaint);
                canvas.drawLine(leftStartX, leftStartY, (float) (leftStartX +
                                length * ((progress - 0.5) / 0.25) * Math.cos(Math.PI / 4)),
                        (float) (leftStartY + length * ((progress - 0.5) / 0.25) * Math.sin(Math.PI / 4)), linePaint);
                // 画红叉右上到左下的线
            } else {
                canvas.drawArc(new RectF(lineWidth / 2, lineWidth / 2, width - lineWidth / 2, height - lineWidth / 2), -90, -360, false, circlePaint);
                canvas.drawLine(leftStartX, leftStartY, leftEndX, leftEndY, linePaint);
                canvas.drawLine(rightStartX, rightStartY, (float) (rightStartX -
                                length * ((progress - 0.75) / 0.25) * Math.cos(Math.PI / 4)),
                        (float) (rightStartY + length * ((progress - 0.75) / 0.25) * Math.sin(Math.PI / 4)), linePaint);
            }
        }
    }

    /**
     * 开始播放动画
     */
    public void start() {
        if (isDraw) {
            return;
        }
        isDraw = true;
        ValueAnimator animator = new ValueAnimator().ofFloat(0, 1, 1);
        animator.setDuration(duration);
        animator.setInterpolator(interpolator);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                if (isDraw) {
                    progress = (float) animation.getAnimatedValue();
                    invalidate();
                }
            }
        });
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                if (listener != null) listener.onStart();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                super.onAnimationCancel(animation);
                isDraw = false;
                if (listener != null) listener.onCancel();
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                isDraw = false;
                if (listener != null) listener.onFinish();
            }
        });
        animator.start();
    }

    /**
     * 停止播放动画
     */
    public void stop() {
        isDraw = false;
    }

    /**
     * 清除动画及图案
     */
    public void clear() {
        isDraw = false;
        progress = 0;
        invalidate();
    }

    /**
     * 设置动画时间
     *
     * @param duration 播放时间,单位毫秒
     */
    public void setDuration(int duration) {
        this.duration = duration;
    }

    /**
     * 设置图案线颜色
     *
     * @param lineColor 颜色值
     */
    public void setLineColor(int lineColor) {
        this.lineColor = lineColor;
    }

    /**
     * 设置图案线宽
     *
     * @param lineWidth 线宽,单位dp
     */
    public void setLineWidth(int lineWidth) {
        this.lineWidth = dp2px(lineWidth);
    }

    /**
     * 设置红叉端点到边界的距离
     *
     * @param magin 距离,单位dp
     */
    public void setMagin(int magin) {
        this.magin = dp2px(magin);
    }

    /**
     * 设置动画播放器
     *
     * @param interpolator
     */
    public void setInterpolator(Interpolator interpolator) {
        this.interpolator = interpolator;
    }

    /**
     * 设置动画播放回调
     *
     * @param listener
     */
    public void setOnShowAnimationListener(OnShowAnimationListener listener) {
        this.listener = listener;
    }

    /**
     * 动画播放回调
     */
    public interface OnShowAnimationListener {
        /**
         * 动画开始播放时回调
         */
        void onStart();

        /**
         * 动画播放结束时回调
         */
        void onFinish();

        /**
         * 动画播放取消时回调
         */
        void onCancel();
    }

    private int dp2px(float dipValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }
}

WarningView.java:

public class WarningView extends View {
    Context context;

    private int width;
    private int height;
    private int radius;

    private float length;
    private float lineStartX;
    private float lineStartY;
    private float lineEndX;
    private float lineEndY;
    private float dotX;
    private float dotY;

    // 图案线宽
    private int lineWidth;

    // 图案线颜色
    private int lineColor = Color.parseColor("#fc5c63");

    // 感叹号端点到边界的距离
    private int magin;

    // 动画播放时间
    private int duration = 1500;

    // 动画控制器
    private Interpolator interpolator = new AccelerateDecelerateInterpolator();

    private Paint circlePaint;
    private Paint linePaint;
    private float progress;
    private boolean isDraw;

    // 动画播放回调
    private OnShowAnimationListener listener;

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

    public WarningView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public WarningView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
    }

    private void init() {
        if (lineWidth == 0) lineWidth = dp2px(3);
        if (magin == 0) magin = dp2px(6);

        if (circlePaint == null) circlePaint = new Paint();
        circlePaint.setStrokeWidth(lineWidth);
        circlePaint.setColor(lineColor);
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setAntiAlias(true);
        circlePaint.setStrokeCap(Paint.Cap.ROUND);

        if (linePaint == null) linePaint = new Paint();
        linePaint.setStrokeWidth(1.5f * lineWidth);
        linePaint.setColor(lineColor);
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setAntiAlias(true);
        linePaint.setStrokeCap(Paint.Cap.ROUND);

        lineStartX = radius + lineWidth / 2;
        lineStartY = magin + lineWidth / 2;
        lineEndX = radius + lineWidth / 2;
        lineEndY = 2 * radius - magin - 2.5f * lineWidth;
        length = lineEndY - lineStartY;
        dotX = radius + lineWidth / 2;
        dotY = 2 * radius - magin + lineWidth / 2;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        width = getMeasuredWidth();
        height = width;
        radius = (width / 2 - lineWidth / 2);
        getLayoutParams().height = height;
        init();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        doDraw(canvas);
    }

    /**
     * 绘制图案
     *
     * @param canvas
     */
    private void doDraw(Canvas canvas) {
        if (progress > 0) {
            // 绘制圆圈
            if (progress <= 0.6) {
                canvas.drawArc(new RectF(lineWidth / 2, lineWidth / 2, width - lineWidth / 2, height - lineWidth / 2), -60, -315 * (progress / (float) 0.6), false, circlePaint);
                // 绘制感叹号的一竖
            } else if (progress <= 0.95) {
                canvas.drawArc(new RectF(lineWidth / 2, lineWidth / 2, width - lineWidth / 2, height - lineWidth / 2), -60, -315, false, circlePaint);
                canvas.drawLine(lineStartX, lineStartY, lineEndX, lineStartY + length * (progress - 0.6f) / 0.35f, linePaint);
                // 绘制感叹号的一点
            } else {
                canvas.drawArc(new RectF(lineWidth / 2, lineWidth / 2, width - lineWidth / 2, height - lineWidth / 2), -60, -315, false, circlePaint);
                canvas.drawLine(lineStartX, lineStartY, lineEndX, lineEndY, linePaint);
                canvas.drawLine(dotX, dotY, dotX, dotY + 1, linePaint);
            }
        }
    }

    /**
     * 开始播放动画
     */
    public void start() {
        if (isDraw) {
            return;
        }
        isDraw = true;
        ValueAnimator animator = new ValueAnimator().ofFloat(0, 1, 1);
        animator.setDuration(duration);
        animator.setInterpolator(interpolator);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                if (isDraw) {
                    progress = (float) animation.getAnimatedValue();
                    invalidate();
                }
            }
        });
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                if (listener != null) listener.onStart();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                super.onAnimationCancel(animation);
                isDraw = false;
                if (listener != null) listener.onCancel();
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                isDraw = false;
                if (listener != null) listener.onFinish();
            }
        });
        animator.start();
    }

    /**
     * 停止播放动画
     */
    public void stop() {
        isDraw = false;
    }

    /**
     * 清除动画及图案
     */
    public void clear() {
        isDraw = false;
        progress = 0;
        invalidate();
    }

    /**
     * 设置动画时间
     *
     * @param duration 动画时间,单位毫秒
     */
    public void setDuration(int duration) {
        this.duration = duration;
    }

    /**
     * 设置动画控制器
     *
     * @param interpolator
     */
    public void setInterpolator(Interpolator interpolator) {
        this.interpolator = interpolator;
    }

    /**
     * 设置图案线颜色
     *
     * @param lineColor 颜色值
     */
    public void setLineColor(int lineColor) {
        this.lineColor = lineColor;
    }

    /**
     * 设置图案线宽
     *
     * @param lineWidth 线宽,单位dp
     */
    public void setLineWidth(int lineWidth) {
        this.lineWidth = dp2px(lineWidth);
    }

    /**
     * 感叹号端点到边界的距离
     *
     * @param magin 距离,单位dp
     */
    public void setMagin(int magin) {
        this.magin = dp2px(magin);
    }

    /**
     * 设置动画播放回调
     *
     * @param listener
     */
    public void setOnShowAnimationListener(OnShowAnimationListener listener) {
        this.listener = listener;
    }

    /**
     * 动画播放回调
     */
    public interface OnShowAnimationListener {
        /**
         * 动画开始播放时回调
         */
        void onStart();

        /**
         * 动画播放结束时回调
         */
        void onFinish();

        /**
         * 动画播放取消时回调
         */
        void onCancel();
    }

    private int dp2px(float dipValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

}


其中loading图案是一个资源文件:

circle_loading.xml:




    

    


到这里就已经可以用了,四个控件都是独立工作的,调用方法和参数设置源码里都有注释,大家可以根据需要在想用的地方调用。

 

我这里做了一个二次封装,用一个对话框来装这四个动画,起个名字叫ResultDialog,这样就能直接呼出对话框来显示这几个动画,话不多说下面开始:


首先还是需要自定义一个对话框的style,在styles文件下添加如下代码:


然后需要一张对话框背景图片:(额,图片是白色的,在白色背景下看不到。。大家在上面右键应该有反应。。)

dialog_loading_white_background.png:

一个以动画形式显示返回结果的对话框 (支持loading、打勾、打叉、感叹号)_第1张图片


然后就可以上本体了:

ResultDialog.java:

public class ResultDialog extends Dialog {
    public static final int LOADING = 1;
    public static final int SUCCEED = 2;
    public static final int FAILED = 3;
    public static final int WARNING = 4;

    private Context context;

    private TextView resultTextView;
    private LoadingView loadingView;
    private SucceedView succeedView;
    private FailedView failedView;
    private WarningView warningView;
    private View view;

    // 会话框出现位置
    private int gravity;

    // 对话款宽度
    private int width;

    // 对话框高度
    private int height;

    // 对话框显示回调
    private OnShowingListener listener;

    public ResultDialog(Context context) {
        super(context, R.style.CustomDialog);
        this.context = context;
    }

    public ResultDialog(Context context, int theme) {
        super(context, theme);
        this.context = context;
    }

    private ResultDialog createDialog() {
        view = LayoutInflater.from(context).inflate(R.layout.dialog_result, null);

        resultTextView = (TextView) view.findViewById(R.id.result_textview);
        loadingView = (LoadingView) view.findViewById(R.id.loading_view);
        succeedView = (SucceedView) view.findViewById(R.id.succeed_view);
        failedView = (FailedView) view.findViewById(R.id.failed_view);
        warningView = (WarningView) view.findViewById(R.id.warning_view);

        show();
        setContentView(view);
        getWindow().getAttributes().gravity = gravity != 0 ? gravity : Gravity.CENTER;
        getWindow().setLayout(width != 0 ? width : WindowManager.LayoutParams.WRAP_CONTENT,
                height != 0 ? height : WindowManager.LayoutParams.WRAP_CONTENT);
        setCanceledOnTouchOutside(false);
        setCancelable(true);

        return this;
    }

    /**
     * 开始播放动画
     *
     * @param type 动画类型,可选项:LOADING、SUCCEED、FAILED、WARNING
     * @param text
     */
    public void start(int type, String text) {
        if (loadingView != null && loadingView.isLoading()) {
            loadingView.stop();
        }
        transform(type);
        resultTextView.setText(text);
        if (type == LOADING) {
            loadingView.start();
        } else if (type == SUCCEED) {
            succeedView.setOnShowAnimationListener(new SucceedView.OnShowAnimationListener() {
                @Override
                public void onStart() {
                    if (listener != null) listener.onStart();
                }

                @Override
                public void onFinish() {
                    if (listener != null) listener.onFinish();
                }

                @Override
                public void onCancel() {
                    if (listener != null) listener.onCancel();
                }
            });
            succeedView.start();
        } else if (type == FAILED) {
            failedView.setOnShowAnimationListener(new FailedView.OnShowAnimationListener() {
                @Override
                public void onStart() {
                    if (listener != null) listener.onStart();
                }

                @Override
                public void onFinish() {
                    if (listener != null) listener.onFinish();
                }

                @Override
                public void onCancel() {
                    if (listener != null) listener.onCancel();
                }
            });
            failedView.start();
        } else if (type == WARNING) {
            warningView.setOnShowAnimationListener(new WarningView.OnShowAnimationListener() {
                @Override
                public void onStart() {
                    if (listener != null) listener.onStart();
                }

                @Override
                public void onFinish() {
                    if (listener != null) listener.onFinish();
                }

                @Override
                public void onCancel() {
                    if (listener != null) listener.onCancel();
                }
            });
            warningView.start();
        }
    }

    public void stop() {
        succeedView.stop();
        failedView.stop();
        warningView.stop();
    }

    public void clear() {
        succeedView.clear();
        failedView.clear();
        warningView.clear();
    }

    /**
     * 根据动画类型显示相应的View
     *
     * @param type 动画类型
     */
    private void transform(int type) {
        loadingView.setVisibility(View.GONE);
        succeedView.setVisibility(View.GONE);
        failedView.setVisibility(View.GONE);
        warningView.setVisibility(View.GONE);
        if (type == LOADING) {
            loadingView.setVisibility(View.VISIBLE);
        } else if (type == SUCCEED) {
            succeedView.setVisibility(View.VISIBLE);
        } else if (type == FAILED) {
            failedView.setVisibility(View.VISIBLE);
        } else if (type == WARNING) {
            warningView.setVisibility(View.VISIBLE);
        }
    }

    private void setGravity(int gravity) {
        this.gravity = gravity;
    }

    private void setDialogSize(int width, int height) {
        this.width = dp2px(width);
        this.height = dp2px(height);
    }

    /**
     * 对话框建造者
     */
    public static class DialogBuilder {
        ResultDialog dialog;

        public DialogBuilder(Context context) {
            dialog = new ResultDialog(context);
        }

        /**
         * 设置对话框位置
         *
         * @param gravity
         * @return
         */
        public DialogBuilder setGravity(int gravity) {
            dialog.setGravity(gravity);
            return this;
        }

        /**
         * 对话框宽高
         *
         * @param width  宽度值,单位dp
         * @param height 高度值,单位dp
         * @return
         */
        public DialogBuilder setDialogSize(int width, int height) {
            dialog.setDialogSize(width, height);
            return this;
        }

        /**
         * 创建对话框
         *
         * @return
         */
        public ResultDialog create() {
            return dialog.createDialog();
        }
    }

    /**
     * 动画回调
     */
    public interface OnShowingListener {
        /**
         * 动画开始播放时回调
         */
        void onStart();

        /**
         * 动画播放结束时回调
         */
        void onFinish();

        /**
         * 动画播放取消时回调
         */
        void onCancel();
    }

    public void setOnShowingListener(OnShowingListener listener) {
        this.listener = listener;
    }

    private int dp2px(float dipValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }
}


这个对话框控件还是建造者模式的写法,创建出对话框后直接调用start()方法就能播放动画了。但是这里我建议大家再封装一

层,把创建对话框、播放动画的方法写在BaseActivity里,这样再任何一个activity里这需要一句话就能调用了,非常方便。

上BaseActivity的代码:

BaseActivity.class:

public abstract class BaseActivity extends Activity {
    private ResultDialog resultDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    private void showResultDialog(int type, String text, final boolean isFinishAfterShowing, final DialogShowingCallBack callBack) {
        if (resultDialog == null) {
            resultDialog = new ResultDialog.DialogBuilder(this)
                    .setDialogSize(145, 145)
                    .create();
        }
        resultDialog.setOnShowingListener(new ResultDialog.OnShowingListener() {
            @Override
            public void onStart() {

            }

            @Override
            public void onFinish() {
                if (callBack != null) {
                    callBack.onFinish();
                } else if (isFinishAfterShowing) {
                    finish();
                }
                dismissResultDialog();
            }

            @Override
            public void onCancel() {

            }
        });
        if (!resultDialog.isShowing()) resultDialog.show();
        resultDialog.start(type, text);
    }

    public void showResultDialog(int type, String text) {
        showResultDialog(type, text, false, null);
    }

    public void showResultDialog(int type, String text, boolean isFinishAfterShowing) {
        showResultDialog(type, text, isFinishAfterShowing, null);
    }

    public void showResultDialog(int type, String text, DialogShowingCallBack callBack) {
        showResultDialog(type, text, true, callBack);
    }

    public void dismissResultDialog() {
        if (resultDialog != null && resultDialog.isShowing()) {
            resultDialog.dismiss();
        }
    }
}

其中DialogShowingCallBack是一个回调接口:

DialogShowingCallBack.java

/**
 * 对话框回调接口
 */
public interface DialogShowingCallBack {
    /**
     * 在对话框中的动画播放完毕后回调
     */
    void onFinish();
}


最后的最后,就可以调用了,上MainActivity.java和activity_main.xml:

MainActivity.java:

public class MainActivity extends BaseActivity {
    private Button loadingButton, succeedButton, failedButton, warningButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();
    }

    private void initData() {

    }

    private void initView() {
        loadingButton = (Button) findViewById(R.id.loading_button);
        succeedButton = (Button) findViewById(R.id.succeed_button);
        failedButton = (Button) findViewById(R.id.failed_button);
        warningButton = (Button) findViewById(R.id.warning_button);

        loadingButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showResultDialog(ResultDialog.LOADING, "LOADING");
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        dismissResultDialog();
                    }
                }, 3000);
            }
        });
        succeedButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showResultDialog(ResultDialog.SUCCEED, "SUCCEED", new DialogShowingCallBack() {
                    @Override
                    public void onFinish() {
                        Toast.makeText(MainActivity.this, "FINISH", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
        failedButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showResultDialog(ResultDialog.FAILED, "FAILED", new DialogShowingCallBack() {
                    @Override
                    public void onFinish() {
                        Toast.makeText(MainActivity.this, "FINISH", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
        warningButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showResultDialog(ResultDialog.WARNING, "WARNING", new DialogShowingCallBack() {
                    @Override
                    public void onFinish() {
                        Toast.makeText(MainActivity.this, "FINISH", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }
}

activity_main.xml:




    

    

调用方法非常简单,只需要showResultDialog这一句话就搞定了。运行一下,就可以看到开头所示的效果了。

showResultDialog有三种构造方法,大家看注释应该很好懂,这里就不再多说了。

 

最后附上源码地址:点击打开链接

 

这次的内容就到这里,我们下次再见。
















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