android群英传笔记——音频条形图(仿音频动画,无监听音频输入)

音频条形图

如下图所示就是这次的音频条形图:

音频条形图

由于只是自定义View的用法,我们就不去真实地监听音频输入了,随机模拟一些数字即可。

如果要实现一个如上图的静态音频条形图,相信大家应该可以很快找到思路,也就是绘制一个个的矩形,每个矩形之间稍微偏移一点距离即可。如下代码就展示了一种计算坐标的方法。

        for (int i = 0; i < mRectCount; i++) {
            // 矩形的绘制是从左边开始到上、右、下边(左右边距离左边画布边界的距离,上下边距离上边画布边界的距离)
            canvas.drawRect(
                    (float) (mRectWidth * i + offset),
                    currentHeight,
                    (float) ( mRectWidth * (i + 1)),
                    mRectHeight,
                    mRectPaint
            );
        }

如上代码中,我们通过循环创建这些小的矩形,其中currentHeight就是每个小矩形的高,通过横坐标的不断偏移,就绘制出了这些静态的小矩形。下面再通过矩形的高度随机变化模拟音频,这里直接利用Math.randoom()方法来随机改变这些高度,并赋值给currentHeight,代码如下所示。

            // 由于只是简单的案例就不监听音频输入,随机模拟一些数字即可
            mRandom = Math.random();
            currentHeight = (float) (mRectHeight * mRandom);

这样就能实现静态效果了,但是如何实现动态效果呢?其实也是非常简单的,只要在onDraw()方法中再去调用invalidate()方法通知View进行重绘就可以了。不过这里不需要每次一绘制完新的矩形就通知View进行重绘,这样会因为刷新速度太快反而影响效果。因此,我们可以使用如下代码来进行View的延迟重绘,代码如下:

posInvalidateDelayed(300);

这样每隔300ms通知View进行重绘,就可以得到一个比较好的视觉效果了。最后添加一个渐变效果可以使View更加逼真,代码如下所示:

    @Override
    protected void onSizeChanged(int w,int h,int oldW,int oldH) {
        super.onSizeChanged(w, h, oldW, oldH);
        // 渐变效果
        LinearGradient mLinearGradient;
        // 画布的宽
        int mWidth;
        // 获取画布的宽
        mWidth = getWidth();
        // 获取矩形的最大高度
        mRectHeight = getHeight();
        // 获取单个矩形的宽度(减去的部分为到右边界的间距)
        mRectWidth = (mWidth-offset) / mRectCount;
        // 实例化一个线性渐变
        mLinearGradient = new LinearGradient(
                0,
                0,
                mRectWidth,
                mRectHeight,
                topColor,
                downColor,
                Shader.TileMode.CLAMP
        );
        // 添加进画笔的着色器
        mRectPaint.setShader(mLinearGradient);
    }

从这个例子中,我们可以知道,在创建自定义View的时候,需要一步一步来,从一个基本的效果开始,慢慢地添加功能,绘制更复杂的效果。不论是多么复杂的自定义View都一定是慢慢迭代起来的功能,所以不要觉得自定义View有多难。千里之行始于足下,只要开始做,慢慢地就能越来越熟练。

代码

以下是这次的完整代码:

package com.example.customaf;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;

import com.example.afanalog.R;


/**
 * 自定义的音频模拟条形图
 * Created by shize on 2016/9/5.
 */
public class MyAF extends View {
    // 音频矩形的数量
    private int mRectCount;
    // 音频矩形的画笔
    private Paint mRectPaint;
    // 渐变颜色的两种
    private int topColor, downColor;
    // 音频矩形的宽和高
    private int mRectWidth, mRectHeight;
    // 偏移量
    private int offset;
    // 频率速度
    private int mSpeed;
    public MyAF(Context context) {
        super(context);
    }

    public MyAF(Context context, AttributeSet attrs) {
        super(context, attrs);
        setPaint(context, attrs);
    }

    public MyAF(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setPaint(context, attrs);
    }

    public void setPaint(Context context, AttributeSet attrs){
        // 将属性存储到TypedArray中
        TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyAF);
        mRectPaint = new Paint();
        // 添加矩形画笔的基础颜色
        mRectPaint.setColor(ta.getColor(R.styleable.MyAF_AFTopColor,
                ContextCompat.getColor(context, R.color.top_color)));
        // 添加矩形渐变色的上面部分
        topColor=ta.getColor(R.styleable.MyAF_AFTopColor,
                ContextCompat.getColor(context, R.color.top_color));
        // 添加矩形渐变色的下面部分
        downColor=ta.getColor(R.styleable.MyAF_AFDownColor,
                ContextCompat.getColor(context, R.color.down_color));
        // 设置矩形的数量
        mRectCount=ta.getInt(R.styleable.MyAF_AFCount, 10);
        // 设置重绘的时间间隔,也就是变化速度
        mSpeed=ta.getInt(R.styleable.MyAF_AFSpeed, 300);
        // 每个矩形的间隔
        offset=ta.getInt(R.styleable.MyAF_AFOffset, 5);
        // 回收TypeArray
        ta.recycle();
    }

    @Override
    protected void onSizeChanged(int w,int h,int oldW,int oldH) {
        super.onSizeChanged(w, h, oldW, oldH);
        // 渐变效果
        LinearGradient mLinearGradient;
        // 画布的宽
        int mWidth;
        // 获取画布的宽
        mWidth = getWidth();
        // 获取矩形的最大高度
        mRectHeight = getHeight();
        // 获取单个矩形的宽度(减去的部分为到右边界的间距)
        mRectWidth = (mWidth-offset) / mRectCount;
        // 实例化一个线性渐变
        mLinearGradient = new LinearGradient(
                0,
                0,
                mRectWidth,
                mRectHeight,
                topColor,
                downColor,
                Shader.TileMode.CLAMP
        );
        // 添加进画笔的着色器
        mRectPaint.setShader(mLinearGradient);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        double mRandom;
        float currentHeight;
        for (int i = 0; i < mRectCount; i++) {
            // 由于只是简单的案例就不监听音频输入,随机模拟一些数字即可
            mRandom = Math.random();
            currentHeight = (float) (mRectHeight * mRandom);

            // 矩形的绘制是从左边开始到上、右、下边(左右边距离左边画布边界的距离,上下边距离上边画布边界的距离)
            canvas.drawRect(
                    (float) (mRectWidth * i + offset),
                    currentHeight,
                    (float) ( mRectWidth * (i + 1)),
                    mRectHeight,
                    mRectPaint
            );
        }
        // 使得view延迟重绘
        postInvalidateDelayed(mSpeed);
    }

}

布局文件的完整代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.afanalog.MainActivity">

    <com.example.customaf.MyAF
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        custom:AFCount="15"
        custom:AFDownColor="@color/down_color"
        custom:AFSpeed="300"
        custom:AFTopColor="@color/top_color"
        custom:AFOffset="15"
        />
</LinearLayout>

感谢阅读,下次再见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值