大家一定看过支付宝支付成功时显示的那个打勾的动画,这次就带来这样一个控件,把动画封装成一个控件,再二次封装在对话
框里,调用时只需要写一句话,很方便。先看一下效果吧:
首先还是惯例的简单说一下原理吧。其实很简单,本质就是画一个图案,勾的图案就是画个圆弧,再画一段折线,其它图案同
理。然后所谓动画就是把这个图案绘制的过程一帧一帧迭代,这里直接用了系统提供的属性动画类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:
然后就可以上本体了:
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有三种构造方法,大家看注释应该很好懂,这里就不再多说了。
最后附上源码地址:点击打开链接
这次的内容就到这里,我们下次再见。