Android实现漂亮的波纹动画

Android实现漂亮的波纹动画

本文章讲述如何使用二维画布canvas和camera、矩阵实现二、三维波纹动画效果(波纹大小变化、画笔透明度变化、画笔粗细变化)

一、UI界面

界面主要分为三部分
第一部分 :输入框,根据输入x轴、Y轴、Z轴倾斜角度绘制波纹动画立体效果
第二部分 :点击按钮PLAY:开始绘制动画;点击按钮STOP:停止绘制动画
第三部分 :绘制波纹动画的自定义view

activity_main.xml实现如下:

java 复制代码
<?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,声明类成员变量和实现构造函数初始化

java 复制代码
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();
    }

构造函数初始化

添加动画

  1. 圆圈等比变大动画
  2. 透明度渐变动画
  3. 画笔由细变粗动画
java 复制代码
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

java 复制代码
@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

相关推荐
q***614118 分钟前
Spring中Aware的用法以及实现
java·数据库·spring
e***877034 分钟前
windows配置永久路由
android·前端·后端
代码or搬砖39 分钟前
SpringMVC的执行流程
java·spring boot·后端
Appreciate(欣赏)1 小时前
JAVA使用poi类读取xlxs文件内容拼接成添加数据SQL
java·开发语言·sql
极光代码工作室1 小时前
基于SpringBoot的流浪狗管理系统的设计与实现
java·spring boot·后端
毕设源码-朱学姐2 小时前
【开题答辩全过程】以 基于JAVA的恒星酒店客房管理系统为例,包含答辩的问题和答案
java·开发语言
思密吗喽2 小时前
景区行李寄存管理系统
java·开发语言·spring boot·毕业设计·课程设计
fouryears_234172 小时前
现代 Android 后台应用读取剪贴板最佳实践
android·前端·flutter·dart
gladiator+2 小时前
Redis之BigKey的常见问题以及大厂相关面试题
java·数据库·redis
Controller-Inversion3 小时前
岛屿问题(dfs典型问题求解)
java·算法·深度优先