当前位置: 首页 > article >正文

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();
    }

构造函数初始化

添加动画

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


http://www.kler.cn/a/565797.html

相关文章:

  • 如何在Node.js中处理文件上传?
  • 【Docker】Dify教程(配置文件,附知识库上传15MB限制解决方案)
  • 神经网络AI原理回顾
  • 如何使用Docker搭建哪吒监控面板程序
  • MaxCompute x DataWorks × DeepSeek,实现使用自定义数据集微调DeepSeek-R1蒸馏模型
  • KubeSphere 企业版 v4.1.3 发布!可观测性深度优化,管理策略更灵活更安全
  • PyTorch深度学习框架60天进阶计划第11天:过拟合解决方案深度实践
  • 【六祎 - Note】SQL备忘录;DDL,DML,DQL,DCL
  • 大模型原理与技术(毛玉仁)
  • 头歌实验---C/C++程序设计:实验2:顺序结构程序设计
  • 【Git】版本控制系统Git命令详解
  • 团队协作中的分支合并:构建高效开发流程的关键
  • rust学习~tokio的io
  • 爱普生可编程晶振 SG-8101CE 在智能家居领域展现出的优势
  • CSS中文本属性使用详情
  • 智科技赋能宠物关怀新时代
  • IDEA提示将方法形参更改为(什么什么类型),要检查对应的实体类中的字段类型是否正确
  • 浏览器访问https站点的过程
  • 【azure openai】用tts实现语音对话【demo】
  • 前端项目中脚本文件打包,vscode中如何正确使用gtar命令