最近自己动手实现了一个像网易云鲸云特效的自定义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上
本文还参考了:
转载于:https://juejin.im/post/5d033e46e51d4550723b13e6