前言:
為了熟悉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) {
}
});
***
- **第二階段**

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)
,使第二階段動畫結束后保持在結束的位置,使第一階段的動畫能夠連接上。分別給小球設定動畫,并且給其中一個動畫集設定監聽事件,結束播放第一階段的動畫,這里的監聽事件類似于第一階段的,就不貼出代碼了。
-
第三階段
第三階段.gif - 在任意一個階段觸發了結束動畫的事件(可以在前面兩個階段處看到一個布爾類型的
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 的動畫,可能有許多地方理解錯誤需要改進,歡迎大家留言。