Android实现漂亮的波纹动画
Android实现漂亮的波纹动画
本文章讲述如何使用二维画布canvas和camera、矩阵实现二、三维波纹动画效果(波纹大小变化、画笔透明度变化、画笔粗细变化)
一、UI界面
界面主要分为三部分
第一部分:输入框,根据输入x轴、Y轴、Z轴倾斜角度绘制波纹动画立体效果
第二部分:点击按钮PLAY:开始绘制动画;点击按钮STOP:停止绘制动画
第三部分:绘制波纹动画的自定义view
activity_main.xml实现如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginBottom="8dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="X轴倾斜" />
<EditText
android:id="@+id/editText_X"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:text="0"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Y轴倾斜" />
<EditText
android:id="@+id/editText_Y"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:text="0"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Z轴倾斜" />
<EditText
android:id="@+id/editText_Z"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:text="0"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:paddingTop="16dp">
<Button
android:id="@+id/playButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Play"
android:layout_marginEnd="8dp"/>
<Button
android:id="@+id/stopButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop"
android:layout_marginEnd="8dp"/>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_gravity="center">
<!-- WaveView -->
<com.example.waveanimationbysingleview.animation.WaveView
android:id="@+id/wave_view"
android:layout_width="match_parent"
android:layout_height="606dp"
android:layout_gravity="center" />
</FrameLayout>
</LinearLayout>
二、自定义view实现
新建一个WaveView类继承自View,声明类成员变量和实现构造函数初始化
public class WaveView extends View{
private RippleAnimationInfo mRippleInfo;//动画属性类,包括最大、最小半径,光圈等
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private float centerX, centerY; //绘制画布中心点
private float[] mRadiusArray; // 存储当前绘制每圈光波的半径
private float[] mAlphaArray; //存储当前绘制每圈光波的透明度
private float[] mStrokenArray; //存储当前绘制每圈光波的画笔宽度
private final Camera mCamera = new Camera();//相机
private final Matrix mMatrix = new Matrix();//矩阵
private final RectF mRectF = new RectF();
private Boolean mIsDrawing = false;//是否绘制标志位
private Bitmap mLogoBitmap;//中心点表情😝logo
private AnimatorSet mAnimatorSet = new AnimatorSet();//多动画组合类
private List<Animator> mAnimatorList = new ArrayList<>();//存储动画列表
public WaveView(Context context) {
super(context);
init();
}
public WaveView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
构造函数初始化
添加动画
- 圆圈等比变大动画
- 透明度渐变动画
- 画笔由细变粗动画
private void initAnimation() {
int rippleDelay = mRippleInfo.durationTime/mRippleInfo.rippleCount;
for (int i = 0; i < mRippleInfo.rippleCount; i++) {
//动画1-半径变大
final int index = i;
ValueAnimator radiusAnimator = ValueAnimator.ofFloat(mRippleInfo.minRadius, mRippleInfo.maxRadius);
radiusAnimator.setDuration(mRippleInfo.durationTime); // 动画持续时间
radiusAnimator.setStartDelay(i * rippleDelay); // 延迟启动
radiusAnimator.setRepeatCount(ValueAnimator.INFINITE);
radiusAnimator.setRepeatMode(ValueAnimator.RESTART);
radiusAnimator.addUpdateListener(animation -> {
mRadiusArray[index] = (float) animation.getAnimatedValue();
invalidate(); // 重绘视图
});
//动画2-画笔变粗
ValueAnimator strokeAnimator = ObjectAnimator.ofFloat(mRippleInfo.minStrokenWidth, mRippleInfo.maxStrokenWidth);
strokeAnimator.setDuration(mRippleInfo.durationTime); // 动画持续时间
strokeAnimator.setStartDelay(i * rippleDelay); // 延迟启动
strokeAnimator.setRepeatCount(ValueAnimator.INFINITE);
strokeAnimator.setRepeatMode(ValueAnimator.RESTART);
strokeAnimator.addUpdateListener(animation -> {
mStrokenArray[index] = (float) animation.getAnimatedValue();
invalidate(); // 重绘视图
});
//动画3-颜色淡出
ValueAnimator alphaAnimator = ObjectAnimator.ofFloat( 0.1f, 0.8f, 0.8f,0.4f, 0);
alphaAnimator.setDuration(mRippleInfo.durationTime); // 动画持续时间
alphaAnimator.setStartDelay(i * rippleDelay); // 延迟启动
alphaAnimator.setRepeatCount(ValueAnimator.INFINITE);
alphaAnimator.setRepeatMode(ValueAnimator.RESTART);
alphaAnimator.addUpdateListener(animation -> {
mAlphaArray[index] = (float) animation.getAnimatedValue();
invalidate(); // 重绘视图
});
mAnimatorList.add(radiusAnimator);
mAnimatorList.add(strokeAnimator);
mAnimatorList.add(alphaAnimator);
}
mAnimatorSet.playTogether(mAnimatorList);
}
应用矩阵变换
重写ondraw
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (!mIsDrawing)
{return;}
canvas.save();
// 计算中心点
centerX = getWidth() / 2.0f;
centerY = getHeight() / 2.0f;
canvas.concat(mMatrix);// 将矩阵应用到画布上
//绘制多圈波纹
for (int i = 0; i < mRippleInfo.rippleCount; i++) {
if (mRadiusArray[i] > 0) {
paint.setStrokeWidth(mStrokenArray[i]);
paint.setAlpha((int)(255 * mAlphaArray[i]));
canvas.drawCircle(centerX, centerY,mRadiusArray[i],paint);
}
}
// 中心点绘制 logo
canvas.drawBitmap(mLogoBitmap, (getWidth()- mRippleInfo.minRadius)/2, (getHeight()- mRippleInfo.minRadius)/2, null);
canvas.restore();
}
二、二维波纹动画
waveAnimation_2D
三、三维波纹动画
waveAnimation_3D