Android仿百度地圖小度語音助手的貝塞爾曲線動(dòng)畫
本文為大家分享了Android仿小度語音助手的貝塞爾曲線動(dòng)畫,供大家參考,具體內(nèi)容如下
廢話不多說,看下面的動(dòng)圖,和百度的還是有點(diǎn)點(diǎn)差別,我也不修改了,很簡單,我實(shí)在是沒有多余的時(shí)間,還要學(xué)習(xí)其他的東西。

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;
/**
* 仿百度的語音助手--波浪動(dòng)畫控件
*/
public class VolumeWaveView extends View {
private static final String TAG = "VolumeWaveView";
private static final int HEIGHT = 400;//整個(gè)控件的高度
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;//波動(dòng)的幅度,你可以動(dòng)態(tài)改變這個(gè)值,比如麥克風(fēng)錄入的音量的高低
private static final int splitWidth = -200;//扇形的交錯(cuò)距離
private Path path;
private Paint paint1,paint2,paint3,paint4;
private LinearGradient linearGradient1,linearGradient2,linearGradient3,linearGradient4;//四種漸變色
private ValueAnimator animator1,animator2,animator3,animator4,animator5;//五種動(dòng)畫
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方法中不要?jiǎng)?chuàng)建大量對象,盡量復(fù)用對象
* @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);//起點(diǎn)
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);//起點(diǎn)
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);
}
/**
* 添加屬性動(dòng)畫
*/
public void startAnimation() {
Random random = new Random();
range = random.nextInt(100)%(100-10+1) + 10;//波動(dòng)的幅度,模擬動(dòng)態(tài)音量輸入,你可以自己設(shè)置
animator1 = ValueAnimator.ofInt(0,HEIGHT1,0);
animator1.setDuration(1400);
animator1.setInterpolator(new DecelerateInterpolator());
//無限循環(huán)
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());
//無限循環(huán)
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());
//無限循環(huán)
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());
//無限循環(huán)
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());
//無限循環(huán)
animator5.setRepeatCount(ValueAnimator.INFINITE);
animator5.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
h5 = (int) animation.getAnimatedValue();
invalidate();
}
});
animator5.start();
}
/**
* 關(guān)閉動(dòng)畫
*/
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中的貝塞爾曲線,然后加上屬性動(dòng)畫,動(dòng)態(tài)改變曲線的高度就可以了
喜歡的話,就去github給個(gè)star吧
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android 利用三階貝塞爾曲線繪制運(yùn)動(dòng)軌跡的示例
- Android Path繪制貝塞爾曲線實(shí)現(xiàn)QQ拖拽泡泡
- Android貝塞爾曲線初步學(xué)習(xí)第三課 Android實(shí)現(xiàn)添加至購物車的運(yùn)動(dòng)軌跡
- Android貝塞爾曲線實(shí)現(xiàn)直播點(diǎn)贊效果
- Android貝塞爾曲線初步學(xué)習(xí)第一課
- Android利用二階貝塞爾曲線實(shí)現(xiàn)添加購物車動(dòng)畫詳解
- Android貝塞爾曲線實(shí)現(xiàn)填充不規(guī)則圖形并隨手指運(yùn)動(dòng)
- Android使用貝塞爾曲線仿QQ聊天消息氣泡拖拽效果
- Android貝塞爾曲線實(shí)現(xiàn)消息拖拽消失
- Android自定義view實(shí)現(xiàn)圓形waveview
相關(guān)文章
android?studio項(xiàng)目:綁定服務(wù)和線程實(shí)現(xiàn)計(jì)時(shí)器
這篇文章主要介紹了android?studio項(xiàng)目:綁定服務(wù)和線程實(shí)現(xiàn)計(jì)時(shí)器,完成一個(gè)秒表,具備啟停功能,通過綁定服務(wù)實(shí)現(xiàn)功能,通過Thread+handler更新界面,需要的朋友可以參考一下2021-12-12
Android自定義控件實(shí)現(xiàn)UC瀏覽器語音搜索效果
這篇文章主要為大家詳細(xì)介紹了Android自定義控件實(shí)現(xiàn)UC瀏覽器語音搜索效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
Android利用方向傳感器獲得手機(jī)的相對角度實(shí)例說明
下面以實(shí)例向大家介紹喜愛Android利用方向傳感器獲得手機(jī)的相對角度,不了解的朋友可以參考下2013-06-06
Android實(shí)現(xiàn)手機(jī)定位的案例代碼
今天小編就為大家分享一篇關(guān)于Android實(shí)現(xiàn)手機(jī)定位的案例代碼,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03
通過案例分析Android WindowManager解析與騙取QQ密碼的過程
Windows Manager是一款窗口管理終端,可以遠(yuǎn)程連接到Linux的X桌面進(jìn)行管理,與服務(wù)器端產(chǎn)生一個(gè)session相互通信,通過本文給大家分享Android WindowManager解析與騙取QQ密碼的過程,需要的朋友參考下2016-01-01
使用CMake構(gòu)建OpenCV項(xiàng)目過程解析
這篇文章主要介紹了使用CMake構(gòu)建OpenCV項(xiàng)目過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
Android 中Crash時(shí)如何獲取異常信息詳解及實(shí)例
這篇文章主要介紹了Android 中Crash時(shí)如何獲取異常信息詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02

