最近自己動手實現了一個像網易雲鯨雲特效的自定義view,這是實現效果。
目錄
主要分為2個方面:
- 旋轉和剪下
- 水波紋的擴散
1.旋轉和剪下
圖片剪下,主要利用ImageView的setOutlineProvider
這個方法,
roundImage.setOutlineProvider(new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
int width = roundImage.getWidth();
int height = roundImage.getHeight();
outline.setOval(0, 0, width, height);
}
});
roundImage.setClipToOutline(true);
複製程式碼
然後通過屬性動畫來旋轉
//屬性動畫讓roundImage旋轉起來
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(roundImage, "rotation", 0, 360);
objectAnimator.setDuration(15000);
objectAnimator.setRepeatMode(ValueAnimator.RESTART);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatCount(-1);
objectAnimator.start();
複製程式碼
關於ObjectAnimator可參考這篇文章
2.水波紋的擴散
主要是在 DiffuseView 這個類下面逐步畫圈,然後延時重新整理。
-
首先需要在
mMaxRadiusWidth
和mMinRadiusWidth
這兩個引數來取得畫圈半徑的最小值和最大值,其中mMaxRadiusWidth
可以在onMeasure
中獲取在onMeasure中獲得寬高
mMaxRadiusWidth = Math.min(getMeasuredHeight() / 2, getMeasuredWidth() / 2); 複製程式碼
ps:注意,使用
getWidth
和getHeight
方法可能會出現問題 -
然後用這兩個引數代表圓圈半徑,和對應透明度
private List<Integer> mAlphas = new ArrayList<>(); private List<Integer> mWidths = new ArrayList<>(); 複製程式碼
-
可能需要:如何將dp轉換成pixels
float twelveDp = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 12, mContext.getResources().getDisplayMetrics() ); 複製程式碼
-
然後就在
onDraw
中畫圓,每畫一次更新mAlphas
和mWidths
中的值,同時需要處理好擴散圓的增加和刪除for (int i = 0; i < mAlphas.size(); i++) { Integer alpha = mAlphas.get(i); mPaint.setAlpha(alpha); Integer width = mWidths.get(i); canvas.drawCircle(getWidth() / 2, getHeight() / 2, width, mPaint); if (alpha >= 2 && width <= mMaxRadiusWidth) { mAlphas.set(i, alpha - 2); mWidths.set(i, width + 1); } else if (width <= mMinRadiusWidth) { mWidths.set(i, width + 1); } } 複製程式碼
-
然後延時重新整理
if (mIsDiffuse) { postInvalidateDelayed(30); } 複製程式碼
-
注意:通過設定mIsDiffuse引數來控制擴散圓動畫的開啟和關閉
在activity中這樣開啟動畫:
diffuseView.start(); 複製程式碼
這是我的github地址,如果有什麼問題和建議,歡迎通過issue提問,同時歡迎star,我會不定期地更新自己寫的自定義view在github上
本文還參考了: