自定义view确实不好学,刚开始比较慢,今天搞了一下午,不断地调,算是音频条形图做了一个效果图出来。

效果图如下:

语音条动画效果 android_android

这是在genymotion里面的展示的效果图,其实做出来比较简单啦。
自己不熟,搞了比较久的时间。
废话不多说,直接上代码:

package com.husy.rectanimation;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by husy on 2015/10/15. 
 * @description:
 */
public class RectAnimationView extends View {
    private Paint rectP;
    private Paint rectK;
    private int rectW = 30;//每个矩形的宽度
    private int count = 0;//矩形的个数
    private int viewW;//组件的宽度
    private int viewH;//组件的高度
    private LinearGradient linearGradient;//线性渐变
    public RectAnimationView(Context context) {
        super(context);
        init();
    }

    public RectAnimationView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RectAnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    private void init(){
        rectP = new Paint();//初始化矩形的画笔
        rectP.setAntiAlias(true);
        rectP.setStyle(Paint.Style.FILL);

        rectK = new Paint();//初始化边框的画笔
        rectK.setAntiAlias(true);
        rectK.setStyle(Paint.Style.STROKE);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int modeW = MeasureSpec.getMode(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int modeH = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (modeW==MeasureSpec.UNSPECIFIED){
            width = 250;
        }
        if (modeH==MeasureSpec.UNSPECIFIED){
            height = 250;
        }//当宽高不指定的时候,指定默认值
        setMeasuredDimension(width,height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //计算组件绘制区域的宽高
        viewH = getHeight()-getPaddingLeft()-getPaddingRight();
        viewW = getWidth()-getPaddingTop()-getPaddingBottom();
        int bottom = viewH;//计算view底部距离
        count = viewW /(rectW+10);//计算矩形的个数 10位矩形的间距
        Rect rectw = new Rect(0,0, viewW,bottom);//外边框矩形
        canvas.drawRect(rectw, rectK);
        //循环绘制矩形
        for (int i=0;i<count;i++){
            linearGradient = new LinearGradient(
                    0,
                    0,
                    rectW,
                    randomH(),
                    new int[]{Color.BLUE,Color.YELLOW,Color.CYAN,Color.GREEN},
                    new float[]{0.3f,0.5f,0.7f,0.9f},
                    Shader.TileMode.CLAMP);
            rectP.setShader(linearGradient);
            Rect rect = new Rect(
                    (int)(viewW *0.03f+i*(rectW+10)),
                    bottom-randomH(),
                    (int)(viewW *0.03f+(i)*(rectW+10)+rectW),
                    bottom);
            canvas.drawRect(rect,rectP);
        }
        canvas.save();
        postInvalidateDelayed(300);
    }
    //随机生成矩形的高度,形成梯度
    private int randomH(){
        double rand = Math.random();
        return (int)(rand* viewH);
    }
}

如果你是牛人,直接就可以过了,不用往下看啦。都是比较简单的东西。
其中值的提的东西是,LinearGradient类,这是个线性渐变的效果。
他的构造方法有两种:

//参数x0表示渐变的起始点x坐标;
//参数y0表示渐变的起始点y坐标;
//参数x1表示渐变的终点x坐标;
//参数y1表示渐变的终点y坐标 ;
//color0表示渐变开始颜色;
//color1表示渐变结束颜色;
//参数tile表示平铺方式。
public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],
            TileMode tile)


        // 创建LinearGradient并设置渐变颜色数组  
        // 第一个,第二个参数表示渐变起点 可以设置起点终点在对角等任意位置  
        // 第三个,第四个参数表示渐变终点  
        // 第五个参数表示渐变颜色  
        // 第六个参数可以为空,表示坐标,值为0-1 new float[] {0.25f, 0.5f, 0.75f, 1 }  
        // 如果这是空的,颜色均匀分布,沿梯度线。  
        // 第七个表示平铺方式  
        // CLAMP重复最后一个颜色至最后  
        // MIRROR重复着色的图像水平或垂直方向已镜像方式填充会有翻转效果  
        // REPEAT重复着色的图像水平或垂直方向  
 public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,
            TileMode tile)

别的地方就没有什么说的了,剩下的就是onDraw方法中进行绘制矩形就可以了。
主要在onDraw方法中使用了postInvalidateDelayed(300);方法,这样设置是300ms刷新一次,不要调用Invalidate()方法,这样的话 刷新太过频繁,消耗太大。
定义好自定义view之后,就是使用了,xml布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <com.husy.rectanimation.RectAnimationView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</RelativeLayout>

然后activiey中直接引用布局就可以了,没什么说的,这样就实现了上文章开始的效果图了。

下面改一下布局的大小,如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <com.husy.rectanimation.RectAnimationView
        android:layout_width="250dp"
        android:layout_height="250dp"
        />
</RelativeLayout>

效果图如下:

语音条动画效果 android_语音条动画效果 android_02

可以看到效果图随着设置的大小而变化啦。

总之来说,比较简单,github地址:
https://github.com/longyinzaitian/RectAnimation


欢迎交流!【握手~~】