前言:
为了熟悉android的动画,看了郑钦洪_的iOS中旋转加载动画的实现,虽然他是搞IOS的,但也是有借鉴之处的(好吧,就是他叫我写一个类似的动画,赶紧上他那里点赞喜欢!他说 每10个喜欢给我一块钱,蚊子腿再小也是肉啊)。
先上个GIF图
为了这个动画专门去下载了LICEcap,挺好用的工具
github地址,欢迎大家提出修改意见
思路
- 首先要有三个小圆
- 分别实现三个小圆的动画
- 如何方便的展示动画
一.CircleView的实现
自定义一个圆类,有设置颜色,半径,以及圆上显示的文字的方法。
protected void onDraw(Canvas canvas) {
//画笔设置颜色
mPaint.setColor(circleColor);
mPaint.setAntiAlias(true);
//画一个圆
canvas.drawCircle(mViewWidth / 2, mViewHeight / 2, circleRadius, mPaint);
//设置文字
if(mText!=null){
mPaint.setTextSize(mViewHeight*7/8);
float textWidth = mPaint.measureText(mText);
float percent = (circleRadius * 2)/textWidth;
mPaint.setColor(textColor);
canvas.drawText(mText,mViewWidth /2 - textWidth/2,
mViewHeight/2+mPaint.getTextSize()/3 ,mPaint);
}
}
** 注意重写onMeasure()
方法时,返回的高和宽要根据圆的半径来设,这样能使整个view最贴近整个圆。**
二.各个圆的动画的实现
先分解一下整个动画过程,整个动画可以分解为三个阶段
- 第一阶段
- 中间小球从1倍的大小缩放到0.7倍的大小
scale_small = new ScaleAnimation(1f, 0.7f, 1f, 0.7f, circleRadius, circleRadius);```
- 左边的小球从1倍的大小缩放到0.7倍的大小 ,并且绕着中间小球旋转360度,同时向左边4倍于半径距离移动 ,缩小的动画复用上面的
left_ratote = new RotateAnimation(359f, 0f, 3 * circleRadius, circleRadius);
left_translate_to_left = new TranslateAnimation(0, -rotatoRadius, 0, 0);
- 右边的小球从1倍的大小缩放到0.7倍的大小 ,并且绕着中间小球旋转360度,同时向右边4倍于半径距离移动 ,缩小的动画同样复用上面的
right_rotate = new RotateAnimation(359f, 0f, -circleRadius, circleRadius);
right_translate_to_right = new TranslateAnimation(0, rotatoRadius, 0, 0);
分别创建三个动画集,添加各自的动画,并且设定动画时间以及``setFillAfter(true)``,使第一阶段动画结束后保持在结束的位置,使第二阶段的动画能够连接上。分别给小球设定动画,并且给其中一个动画集设定监听事件,结束播放第二阶段的动画。
left_translate_rotate_scale.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
Log.e("wv", "left_translate_rotate_scale finish");
if (!stop) {
if (dismiss) {
//添加 消失动画
addDismissAnima(mid_scale_big, left_translate_scale, right_translate_scale);
}
clear();
// 开始第二个动画集
c1.startAnimation(mid_scale_big);
c2.startAnimation(left_translate_scale);
c3.startAnimation(right_translate_scale);
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
***
- **第二阶段**
![第二阶段.gif](http://upload-images.jianshu.io/upload_images/853620-11669339398d267c.gif?imageMogr2/auto-orient/strip)
1. 中间小球从0.7倍的大小放大到1倍的大小
scale_big = new ScaleAnimation(0.7f, 1f, 0.7f, 1f, circleRadius, circleRadius);```
- 左边的小球从0.7倍的大小放大到1倍的大小 ,同时向右边4倍于半径距离移动 ,放大的动画复用上面的
left_translate_to_right = new TranslateAnimation(-rotatoRadius, 0, 0, 0);
- 右边的小球从0.7倍的大小放大到1倍的大小 同时向左边4倍于半径距离移动 ,放大的动画同样复用上面的
right_translate_to_left = new TranslateAnimation(rotatoRadius, 0, 0, 0);
再次分别创建三个动画集,添加各自的动画,并且设定动画时间以及setFillAfter(true)
,使第二阶段动画结束后保持在结束的位置,使第一阶段的动画能够连接上。分别给小球设定动画,并且给其中一个动画集设定监听事件,结束播放第一阶段的动画,这里的监听事件类似于第一阶段的,就不贴出代码了。
-
第三阶段
- 在任意一个阶段触发了结束动画的事件(可以在前面两个阶段处看到一个布尔类型的
dismiss
标志来给动画集添加消失动画),给那个阶段的每个动画集添加如下几个动画:
让小球从1倍的大小放大到2倍的大小
scale_bigger = new ScaleAnimation(1f, 2f, 1f, 2f, circleRadius, circleRadius);
让小球透明度从 1 到 0 变化
alpha_low = new AlphaAnimation(1f, 0f);
给其中一个动画(scale_bigger /alpha_low )设定监听事件,当结束时清空所有动画,设定小球的透明度为 0(使窗口消失时不至于看到小球),同时调用对应的回调方法
scale_bigger.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
c1.setAlpha(0f);
c2.setAlpha(0f);
c3.setAlpha(0f);
clear();
stop = true;
listener.onFinish();
Toast.makeText(context, "dismiss", Toast.LENGTH_SHORT).show();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
三.实现一句话让该等待加载动画附着于页面任意一个View上
这里用到了单例模式的思想
private static WaitingView wv;
private OnFinish listener = new OnFinish() {
@Override
public void onFinish() {
popupWindow.dismiss();
wv.stop();
wv.resetAnima();
}
};
private static PopupWindow popupWindow;
public static void showWaitingView(Context context, View view,int width,int height, int thecolor, float theradius,int thebackgroundColor ) {
wv = new WaitingView(context);
color = thecolor;
circleRadius = theradius;
windowWidth = width;
windowHeight = height;
backgroundColor = thebackgroundColor;
View layoutView = LayoutInflater.from(context).inflate(R.layout.pupop, null);
layoutView.setBackgroundColor(backgroundColor);
wv = (WaitingView) layoutView.findViewById(R.id.id_wv);
wv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
wv.dismiss();
}
});
popupWindow = new PopupWindow(layoutView, windowWidth, windowHeight,
false);
popupWindow.showAtLocation(view, Gravity.CENTER, 0, 0);
wv.start();
}
public static boolean isExist() {
return wv != null;
}
public static void close() {
wv.dismiss();
}
R.layout.pupop.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<network.scau.com.asimplewaitingdemo.WaitingView
android:id="@+id/id_wv"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
先实例化一个静态的对象,通过showWaitingView()
方法来调用该实例,并实现在一个Popupwindow
中显示,该Popupwindow
附着在传来的View上。
结束语
刚开始接触android 的动画,可能有许多地方理解错误需要改进,欢迎大家留言。