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

相关推荐
计算机-秋大田1 小时前
基于Spring Boot的乡村养老服务管理系统设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·课程设计
盖盖衍上1 小时前
Java 泛型(Generics)详解与使用
java·开发语言·windows
没有十八岁2 小时前
云创智城YunCharge 新能源二轮、四轮充电解决方案(云快充、万马爱充、中电联、OCPP1.6J等多个私有单车、汽车充电协议)之新能源充电行业系统说明书
java·数据库·spring·汽车
小萌新上大分3 小时前
Minio搭建并在SpringBoot中使用完成用户头像的上传
java·spring boot·后端·minio·minio搭建·头像上传·minio入门
B站计算机毕业设计超人3 小时前
计算机毕业设计SpringBoot+Vue.js校园失物招领系统(源码+文档+PPT+讲解)
java·vue.js·spring boot·后端·毕业设计·课程设计·毕设
计算机-秋大田3 小时前
基于SpringBoot的环保网站的设计与实现(源码+SQL脚本+LW+部署讲解等)
java·vue.js·spring boot·后端·课程设计
汤姆yu3 小时前
基于springboot的高校物品捐赠系统
java·spring boot·后端·高校物品捐赠
magic 2453 小时前
深入理解Java网络编程:从基础到高级应用
java·开发语言
岁岁岁平安3 小时前
spring注解开发(Spring整合JUnit+MyBatis)(7)
java·spring·junit·log4j·mybatis
剑海风云4 小时前
JVM常用概念之垃圾回收设计与停顿
java·开发语言·jvm