1. 效果
![雅虎新聞摘要載入](https://i.iter01.com/images/7126c3da22acdec3ded66325ebd03836aa2720aeb1d1d62f9bbdfaec5c0ced9e.gif)
太多太多的評論我其實是不會回的,如果要說什麼只能說抱歉。我承認很多視訊連結沒那麼好找,但是你如果留意用心了,肯定能獲取到以前所有的直播視訊連結。
2.分析和實現
2.1 效果分析:
寫了那麼多次效果,這個實現起來應該是個小 case ,留意觀察有三部分動畫 1. 旋轉動畫,六個小球在不斷地旋轉 2. 位移動畫,六個小球往中心點聚合 3. 擴散動畫,當小球移動的最中心就開始擴散
2.2 分步實現:
1. 旋轉動畫,六個小球在不斷地旋轉
/**
* 繪製小圓的旋轉動畫
*/
private class RotationState extends SplashState {
private ValueAnimator mAnimator;
public RotationState() {
// 屬性動畫
mAnimator = ValueAnimator.ofFloat(0, (float) Math.PI * 2);
mAnimator.setDuration(ROTATION_ANIMATION_TIME);
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 不斷獲取值 當前大圓旋轉的角度
mCurrentRotationAngle = (float) animation.getAnimatedValue();
// 提醒View重新繪製
invalidate();
}
});
mAnimator.setRepeatCount(-1);
mAnimator.setInterpolator(new LinearInterpolator());
// 開始計算
mAnimator.start();
}
@Override
public void draw(Canvas canvas) {
canvas.drawColor(mSplashColor);
// 繪製六個小圓 座標
float preAngle = (float) (2 * Math.PI / mCircleColors.length);
for (int i = 0; i < mCircleColors.length; i++) {
mPaint.setColor(mCircleColors[i]);
// 初始角度 + 當前旋轉的角度
double angle = i * preAngle + mCurrentRotationAngle;
float cx = (float) (mCenterX + mRotationRadius * Math.cos(angle));
float cy = (float) (mCenterY + mRotationRadius * Math.sin(angle));
canvas.drawCircle(cx, cy, mCircleRadius, mPaint);
}
}
public void cancelAnimator() {
mAnimator.cancel();
mAnimator = null;
}
}
複製程式碼
2. 位移動畫,六個小球往中心點靠攏
/**
* 繪製小圓的聚合動畫
*/
private class MergeState extends SplashState {
private ValueAnimator mAnimator;
public MergeState() {
// 屬性動畫
mAnimator = ValueAnimator.ofFloat(mRotationRadius, 0);
mAnimator.setDuration(SPLASH_ANIMATION_TIME / 2);
mAnimator.setInterpolator(new AnticipateInterpolator(6f));
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 不斷獲取值 當前大圓旋轉的角度
mCurrentRotationRadius = (float) animation.getAnimatedValue();
// 提醒View重新繪製
invalidate();
}
});
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mSplashState = new ExpandingState();
}
});
// 開始計算
mAnimator.start();
}
@Override
public void draw(Canvas canvas) {
canvas.drawColor(mSplashColor);
// 繪製六個小圓 座標
float preAngle = (float) (2 * Math.PI / mCircleColors.length);
for (int i = 0; i < mCircleColors.length; i++) {
mPaint.setColor(mCircleColors[i]);
// 初始角度 + 當前旋轉的角度
double angle = i * preAngle + mCurrentRotationAngle;
float cx = (float) (mCenterX + mCurrentRotationRadius * Math.cos(angle));
float cy = (float) (mCenterY + mCurrentRotationRadius * Math.sin(angle));
canvas.drawCircle(cx, cy, mCircleRadius, mPaint);
}
}
}
複製程式碼
3. 擴散動畫,當小球移動的最中心就開始擴散
/**
* 繪製小圓的擴散動畫
*/
private class ExpandingState extends SplashState {
private ValueAnimator mAnimator;
public ExpandingState() {
// 屬性動畫
mAnimator = ValueAnimator.ofFloat(0, mDiagonalDist);
mAnimator.setDuration(SPLASH_ANIMATION_TIME/2);
mAnimator.setInterpolator(new AccelerateInterpolator());
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 不斷獲取值 當前大圓旋轉的角度
mHoleRadius = (float) animation.getAnimatedValue();
// 提醒View重新繪製
invalidate();
}
});
// 開始計算
mAnimator.start();
}
@Override
public void draw(Canvas canvas) {
if (mHoleRadius > 0) {
float strokeWidth = mDiagonalDist - mHoleRadius;
mPaintBackground.setStrokeWidth(strokeWidth);
float radius = mHoleRadius + strokeWidth / 2;
canvas.drawCircle(mCenterX, mCenterY, radius, mPaintBackground);
} else {
canvas.drawColor(mSplashColor);
}
}
}
複製程式碼
這期是自定義 View 部分的最後一次寫效果了,寫得也比較簡單,因為畢竟前面寫過那麼多次,關於畫筆繪製和屬性動畫我就不再詳講了。
所有分享大綱:Android進階之旅 - 自定義View篇
視訊講解地址:http://pan.baidu.com/s/1mhVUimO