本文为大家分享了Android仿小度语音助手的贝塞尔曲线动画,供大家参考,具体内容如下

废话不多说,看下面的动图,和百度的还是有点点差别,我也不修改了,很简单,我实在是没有多余的时间,还要学习其他的东西。

package com.example.helang.volumewave;

import android.animation.ValueAnimator;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.LinearGradient;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.Shader;

import android.support.annotation.Nullable;

import android.util.AttributeSet;

import android.view.View;

import android.view.animation.DecelerateInterpolator;

import java.util.Random;

/**

* 仿百度的语音助手--波浪动画控件

*/

public class VolumeWaveView extends View {

private static final String TAG = "VolumeWaveView";

private static final int HEIGHT = 400;//整个控件的高度

private static final int HEIGHT1 = 200;//第一层曲线的高度

private static final int HEIGHT2 = 400;//第二层曲线的高度

private static final int HEIGHT3 = 350;//第三层曲线的高度

private float h1 = 200,h2 = 200, h3 = 300,h4 = 300,h5 = 200;

private int range = 0;//波动的幅度,你可以动态改变这个值,比如麦克风录入的音量的高低

private static final int splitWidth = -200;//扇形的交错距离

private Path path;

private Paint paint1,paint2,paint3,paint4;

private LinearGradient linearGradient1,linearGradient2,linearGradient3,linearGradient4;//四种渐变色

private ValueAnimator animator1,animator2,animator3,animator4,animator5;//五种动画

public VolumeWaveView(Context context) {

this(context,null);

}

public VolumeWaveView(Context context, @Nullable AttributeSet attrs) {

this(context,attrs,0);

}

public VolumeWaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs,defStyleAttr);

initPaint();

}

private void initPaint(){

path = new Path();

paint1 = new Paint();

paint1.setStyle(Paint.Style.FILL);

paint1.setAntiAlias(true);//抗锯齿

//渐变色1

linearGradient1 = new LinearGradient(0, 0, 0, HEIGHT1,

Color.parseColor("#e652a6d2"), Color.parseColor("#e652d5a1"), Shader.TileMode.MIRROR);

paint1.setShader(linearGradient1);

paint2 = new Paint();

paint2.setAntiAlias(true);//抗锯齿

paint2.setStyle(Paint.Style.FILL);

//渐变色2

linearGradient2 = new LinearGradient(0, 0, 0, HEIGHT2,

Color.parseColor("#e68952d5"), Color.parseColor("#e6525dd5"), Shader.TileMode.MIRROR);

paint2.setShader(linearGradient2);

paint3 = new Paint();

paint3.setAntiAlias(true);//抗锯齿

paint3.setStyle(Paint.Style.FILL);

//渐变色3

linearGradient3 = new LinearGradient(0, 0, 0, HEIGHT3,

Color.parseColor("#e66852d5"), Color.parseColor("#e651b9d2"), Shader.TileMode.MIRROR);

paint3.setShader(linearGradient3);

paint4 = new Paint();

paint4.setAntiAlias(true);//抗锯齿

paint4.setStyle(Paint.Style.FILL);

//渐变色4

linearGradient4 = new LinearGradient(0, 0, 0, HEIGHT2,

Color.parseColor("#e6d5527e"), Color.parseColor("#e6bf52d5"), Shader.TileMode.MIRROR);

paint4.setShader(linearGradient4);

}

/**

* draw方法中不要创建大量对象,尽量复用对象

* @param canvas

*/

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

drawLayer3(canvas);

drawLayer2(canvas);

drawLayer1(canvas);

}

/**

* 绘制第一层

* @param canvas

*/

private void drawLayer1(Canvas canvas){

path.reset();//重置path

path.moveTo(0, HEIGHT);//起点

path.quadTo(getWidth()/4, HEIGHT-h1, getWidth()/2, HEIGHT);//第一条二阶贝塞尔曲线

path.moveTo(getWidth()/2+splitWidth,HEIGHT);

path.quadTo(getWidth()/2+splitWidth+getWidth()/4, HEIGHT-h2, getWidth(), HEIGHT);//第二条二阶贝塞尔曲线

canvas.drawPath(path,paint1);

}

/**

* 绘制第二层

* @param canvas

*/

private void drawLayer2(Canvas canvas){

path.reset();//重置path

path.moveTo(0, HEIGHT);//起点

path.quadTo(getWidth()/4, HEIGHT-h3, getWidth()/2, HEIGHT);//第一条二阶贝塞尔曲线

canvas.drawPath(path,paint2);

path.reset();

path.moveTo(getWidth()/2+splitWidth,HEIGHT);

path.quadTo(getWidth()/2+getWidth()/4, HEIGHT-h4, getWidth(), HEIGHT);//第二条二阶贝塞尔曲线

canvas.drawPath(path,paint4);

}

/**

* 绘制第三层

* @param canvas

*/

private void drawLayer3(Canvas canvas){

path.reset();//重置path

path.moveTo(200,HEIGHT);

path.quadTo(200+getWidth()/3, HEIGHT-h5, getWidth(), HEIGHT);//二阶贝塞尔曲线

canvas.drawPath(path,paint3);

}

/**

* 添加属性动画

*/

public void startAnimation() {

Random random = new Random();

range = random.nextInt(100)%(100-10+1) + 10;//波动的幅度,模拟动态音量输入,你可以自己设置

animator1 = ValueAnimator.ofInt(0,HEIGHT1,0);

animator1.setDuration(1400);

animator1.setInterpolator(new DecelerateInterpolator());

//无限循环

animator1.setRepeatCount(ValueAnimator.INFINITE);

animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

h1 = (int) animation.getAnimatedValue();

invalidate();

}

});

animator1.start();

animator2 = ValueAnimator.ofInt(0,HEIGHT1,0);

animator2.setDuration(1700);

animator2.setInterpolator(new DecelerateInterpolator());

//无限循环

animator2.setRepeatCount(ValueAnimator.INFINITE);

animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

h2 = (int) animation.getAnimatedValue();

invalidate();

}

});

animator2.start();

animator3 = ValueAnimator.ofInt(0,HEIGHT2,0);

animator3.setDuration(1600);

animator3.setInterpolator(new DecelerateInterpolator());

//无限循环

animator3.setRepeatCount(ValueAnimator.INFINITE);

animator3.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

h3 = (int) animation.getAnimatedValue() + range;

invalidate();

}

});

animator3.start();

animator4 = ValueAnimator.ofInt(0,HEIGHT2,0);

animator4.setDuration(1300);

animator4.setInterpolator(new DecelerateInterpolator());

//无限循环

animator4.setRepeatCount(ValueAnimator.INFINITE);

animator4.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

h4 = (int) animation.getAnimatedValue();

invalidate();

}

});

animator4.start();

animator5 = ValueAnimator.ofInt(0,HEIGHT2,0);

animator5.setDuration(1250);

animator5.setInterpolator(new DecelerateInterpolator());

//无限循环

animator5.setRepeatCount(ValueAnimator.INFINITE);

animator5.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

h5 = (int) animation.getAnimatedValue();

invalidate();

}

});

animator5.start();

}

/**

* 关闭动画

*/

public void removeAnimation(){

if (animator1 != null){

animator1.cancel();

animator1 = null;

}

if (animator2 != null){

animator2.cancel();

animator2 = null;

}

if (animator3 != null){

animator3.cancel();

animator3 = null;

}

if (animator4 != null){

animator4.cancel();

animator4 = null;

}

if (animator5 != null){

animator5.cancel();

animator5 = null;

}

}

}

主要是利用Path中的贝塞尔曲线,然后加上属性动画,动态改变曲线的高度就可以了

喜欢的话,就去github给个star吧

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

android 布局中绘制语音曲线,Android仿百度地图小度语音助手的贝塞尔曲线动画相关推荐

  1. 仿百度地图小度语音助手的贝塞尔曲线动画

    废话不多说,看下面的动图,和百度的还是有点点差别,我也不修改了,很简单,我实在是没有多余的时间,还要学习其他的东西,累啊,(复杂的动态View,可以使用SurfaceView,效率更高,我这里就简单使 ...

  2. android 布局中绘制语音曲线,基于android平台的老年人用药助手软件的开发-仪器仪表工程专业论文.docx...

    基于android平台的老年人用药助手软件的开发-仪器仪表工程专业论文 Classified Index: TP319 U.D.C: 004.45 Dissertation for the Degre ...

  3. android 布局 站位符,基于android布局中的常用占位符介绍

    大家在做布局文件是肯定会遇到过下面的这种情况 填充出现问题,所以需要用到占位符规范填充 汉字常用占位符: android:layout_width="wrap_content" a ...

  4. Android布局中涉及的一些属性

    Android:gravity属性 线性布局常见的就是利用LinearLayout进行布局,其中有个比较重要的属性就是android:gravity,在官方文档中是这么描述这个属性的:指定一个元素怎么 ...

  5. Android布局中的空格以及占一个汉字宽度的空格的实现

    在Android布局中进行使用到空格,以便实现文字的对齐.那么在Android中如何表示一个空格呢? 空格: 窄空格:  一个汉字宽度的空格:   [用两个空格(  )占一个汉字的宽度时,两个空格比一 ...

  6. android布局中使用include及需注意点

    在android布局中,使用include,将另一个xml文件引入,可作为布局的一部分,但在使用include时,需注意以下问题:一.使用include引入如现有标题栏布局block_header.x ...

  7. android 多个占位符,基于android布局中的常用占位符介绍

    大家在做布局文件是肯定会遇到过下面的这种情况 填充出现问题,所以需要用到占位符规范填充 汉字常用占位符: android:layout_width="wrap_content" a ...

  8. 详解Android布局中gravity与layout_gravity属性

    在android布局中,我们经常会用到"重心"-gravity这个属性.但是gravity有不同的类型: gravity layout_gravity 相对布局中的layout_c ...

  9. android 继承类图,Android Studio中绘制UML类图介绍

    Android Studio中绘制UML类图介绍 Android Studio中绘制UML类图介绍 动机 最近开始阅读项目源码,从其中一个模块开始看,奈何大项目中的一个模块,对于萌新而言,也太过于复杂 ...

最新文章

  1. Oracle编程入门经典 第6章 在Oracle中处理语句
  2. 初探Stage3D(一) 3D渲染基础原理
  3. Tidb集群加mysql_TiDB - 快速入门,集群搭建
  4. GridView 点滴
  5. 浅析设计模式(三)——抽象工厂模式
  6. php和xml区别,php和XML
  7. ITester软件测试小栈,点击领取你的能量值!
  8. YII2 save 和 insert 循环保存数据,出现间隔性丢失值 (这些值是共有相同的值) 解决: // 每次保存需要用 clone 不能使用直接用一个 实例化的model....
  9. 发现三个很赞的英语学习网站
  10. sqlmap使用教程
  11. CMM3 正式评估全过程
  12. c语言程序分数化简,【C/C++】分数化简
  13. Python 爬虫超详细讲解(零基础入门,老年人都看的懂)
  14. 注册苹果开发者账号遇到问题汇总
  15. 倒杨辉三角4行c语言,倒杨辉三角
  16. java 软键盘_【学习笔记】【java appium】软键盘搜索、回车按钮
  17. android exchange同步日程,OPPO手机的日历怎么同步Exchange邮箱日程的方法
  18. Halcon示例程序Circle 解析
  19. python中语法错误英文提示解析(可能没有解决方案)
  20. 旋转矩阵、欧拉角、四元数、旋转向量(旋转角)

热门文章

  1. c语言正则表达式查找字符串长度,c语言实现正则表达式匹配
  2. Delphi 7移植到Delphi XE5碰到及解决的问题 (1)
  3. JVM调优的基本配置参数
  4. Python动态满屏爱心形代码
  5. 知识付费「四大天王」走下神坛?
  6. 英文计算机简历,计算机英文简历范文
  7. 关联规则算法学习—Apriori
  8. 塔望消费本位战略之食品品牌核心价值提炼与塑造模型
  9. 安卓图形化开发!Android插件化主流框架和实现原理,值得收藏!
  10. 使用递归实现归并排序及归并排序的时间复杂度