Hello,小夥伴們大家好,今天介紹一個很簡單的倒數計時動畫,仿酷狗音樂的啟動頁倒數計時效果,也是大多數APP在用的一個動畫,來看看效果圖:
實現思路
看看是不是很簡單,畫個圈圈動起來,整體的思路就是用一個平滑的幀動畫來畫圓弧就行了。
這篇文章學到什麼?
- 瞭解屬性動畫
ValueAnimator
的用法 - 瞭解動畫屬性插值
Interpolator
,讓動畫過度得更自然 - 如何畫圓弧
開始準備
新建一個類繼承TextView
,因為中間還有跳過
的文字,所以選擇用TextView
來畫個動起來的背景圖。
/**
* 倒數計時文字
* Created by ChenRui on 2017/10/31 0031 23:01.
*/
public class CountDownTextView extends RaeTextView {
// 倒數計時動畫時間
private int duration = 5000;
// 動畫掃過的角度
private int mSweepAngle = 360;
// 屬性動畫
private ValueAnimator animator;
// 矩形用來儲存位置大小資訊
private final RectF mRect = new RectF();
// 圓弧的畫筆
private Paint mBackgroundPaint;
public CountDownTextView(Context context) {
super(context);
}
public CountDownTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CountDownTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
void init() {
super.init();
// 設定畫筆平滑
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
// 設定畫筆顏色
mBackgroundPaint.setColor(Color.WHITE);
// 設定畫筆邊框寬度
mBackgroundPaint.setStrokeWidth(dp2px(2));
// 設定畫筆樣式為邊框型別
mBackgroundPaint.setStyle(Paint.Style.STROKE);
}
複製程式碼
開始動畫
原理: 利用圓的360度角來做屬性動畫,讓它平滑的分配做每幀動畫的角度值,然後呼叫invalidate()
來重繪自己本身,從而進入到本身的onDraw()
方法來畫圖。
/**
* 開始倒數計時
*/
public void start() {
// 在動畫中
if (mSweepAngle != 360) return;
// 初始化屬性動畫
animator = ValueAnimator.ofInt(mSweepAngle).setDuration(duration);
// 設定插值
animator.setInterpolator(new LinearInterpolator());
// 設定動畫監聽
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 獲取屬性動畫返回的動畫值
mSweepAngle = (int) animation.getAnimatedValue();
// 重繪自己
invalidate();
}
});
// 開始動畫
animator.start();
}
複製程式碼
畫圓弧
畫圓弧比較簡單, 從效果圖來看,有的同學可能剛開始以為要畫兩個圓,一個背景的內圓和一個白色邊框的大圓,其實這裡可以利用畫筆設定畫筆樣式paint.setStyle()
和寬度大小paint.setStrokeWidth()
的特性來實現。程式碼很簡單,開始的角度選擇-90,從頭頂開始畫。這樣實現的是一個順時針的倒數計時效果。如果你想實現酷狗的逆時針效果,就控制mSweepAngle
的值用mSweepAngle = 360 - mSweepAngle
開始就可以了。
@Override
protected void onDraw(Canvas canvas) {
int padding = dp2px(4);
mRect.top = padding;
mRect.left = padding;
mRect.right = getWidth() - padding;
mRect.bottom = getHeight() - padding;
// 畫倒數計時線內圓
canvas.drawArc(mRect, //弧線所使用的矩形區域大小
-90, //開始角度
mSweepAngle, //掃過的角度
false, //是否使用中心
mBackgroundPaint); // 設定畫筆
super.onDraw(canvas);
}
複製程式碼
什麼是插值動畫?
為了讓動畫過度的更加自然或者新增一些動畫效果,比如勻速運動、加速運動、減速運動、彈跳運動等等,這些的動畫的效果就是靠插值來實現的。在Android中系統內建了一些插值,這裡做下搬運工記錄一下。推薦一個能線上執行Interpolator的效果以及數學公式定義的網站 inloop.github.io/interpolato… 更加直觀的展示下面介紹的動畫效果。
插值 | 說明 |
---|---|
LinearInterpolator | 以常量速率改變 |
BounceInterpolator | 動畫結束的時候彈起 |
CycleInterpolator | 動畫迴圈播放特定的次數,速率改變沿著正弦曲線 |
DecelerateInterpolator | 在動畫開始的地方快然後慢 |
OvershootInterpolator | 向前甩一定值後再回到原來位置 |
AccelerateInterpolator | 在動畫開始的地方速率改變比較慢,然後開始加速 |
AnticipateInterpolator | 開始的時候向後然後向前甩 |
AccelerateDecelerateInterpolator | 在動畫開始與介紹的地方速率改變比較慢,在中間的時候加速 |
AnticipateOvershootInterpolator | 開始的時候向後然後向前甩一定值後返回最後的值 |
專案使用
這裡要定義文字的寬高,因為沒有畫底部的黑色圓背景,還要設定一下背景圖。
<com.rae.cnblogs.widget.CountDownTextView
android:id="@+id/tv_skip"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/bg_count_down"
android:text="跳過"
android:textColor="#ffffff"
android:textSize="12sp" />
複製程式碼
背景圖
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="oval">
<solid android:color="#302d2d2d" />
</shape>
</item>
<item>
<shape android:shape="oval">
<solid android:color="#7F2d2d2d" />
</shape>
</item>
</selector>
複製程式碼
到這裡結束啦,希望對你有幫助,本篇文章的原始碼都在開源的部落格園Android客戶端這裡。 喜歡的給個start~~