V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hyyou2010
V2EX  ›  Android

整理了一个 android 上的波形图及柱状图绘制控件

  •  
  •   hyyou2010 · 2016-01-13 00:38:33 +08:00 · 12160 次点击
    这是一个创建于 3267 天前的主题,其中的信息可能已经有所发展或是发生改变。

    SimpleWaveform


    [说明:以前画过波形图,最近又需要画,略不同,但还得重复写。在网上搜了一下,只找到一个复杂的框架,而我们往往只需要画简单的波形或柱状图。所以我整理提取了过去的代码,有了这个简洁的波形及柱状图控件。实现上很简单,关键在于,怎样简单,又可灵活定制来适用于通常的应用场景。比如在画图之外增加了进度条及触碰反馈功能,就可适用于录音及播音的场景]

    SimpleWaveform 显示一串数据为波形图,或者条状图

    SimpleWaveform 可以高度定制:

    (1)可以显示原始的正负数据,也可以取绝对值来显示数据的幅度
    (2)数据可以直接对应像素,也可以是满幅的百分比。控件会自动检测自己的宽度及高度像素
    (3)可以选择显示:柱状条 /峰值轮廓 /x 轴
    (4)可以选择怎样连接峰值来画出轮廓
    (5)其 x 轴可以放在控件的顶部 /中间 /底部
    (6)可以设定柱状条的宽度与间隔
    (7)可以设定所有的笔,包括柱条 /轮廓 /x 轴 /背景,前两者是两支笔
    (8)用两支笔来画前后两部分,这样就有不同的颜色来标识进度
    (9)波形图可以从左边或右边开始
    (10)如果你手指碰触视图,监听器可以返回碰触的柱条位置

    常见用法

    (1)当你录音时可以用 SimpleWaveform 来显示声波,请参考 advance demo1
    (2)嵌入为 recycler view 的元素,通过左右滑动来显示很长的波形图,请参考 advance demo2

    从 github 下载 demo apk

    在 github 上查看 SimpleWaveform 源码

    demo1: 显示正负数据
    此处输入图片的描述
    demo2: 柱状图
    此处输入图片的描述
    demo3: 显示振幅绝对值
    此处输入图片的描述
    demo4: 显示声波
    此处输入图片的描述
    advance demo1: 显示录音得到音频输入
    此处输入图片的描述
    advance demo2: 嵌入到横向的 recycler view 中显示很长时间的录音
    此处输入图片的描述

    控件用法:

    (1)直接拷贝 SimpleWaveform.java 到项目. 目前我还不懂得怎么制作一个 gradle 模块.
    (2)查看及拷贝 demo1~4 及 advance demo1~2 代码,位于文件 SimpleWaveformDemo.java 中. 使用非常的直观简单,并且有缺省设置,只要添加数据链表,然后可以省略后续设置并直接显示.

    这里是例子 demo3 ,看一下注释即可:

    private void demo3() {
    
        //restore default setting, you can omit all following setting and goto the final refresh() show
        simpleWaveform.init();
    
        LinkedList<Integer> ampList = new LinkedList<>();
        //generate random data
        for (int i = 0; i < 80; i++) {
            ampList.add(randomInt(-50, 50));
        }
        simpleWaveform.setDataList(ampList);//input data to show
    
        //define bar gap
        simpleWaveform.barGap = 30;
    
        //define x-axis direction
        simpleWaveform.modeDirection = SimpleWaveform.MODE_DIRECTION_LEFT_RIGHT;
    
        //define if draw opposite pole when show bars
        simpleWaveform.modeAmp = SimpleWaveform.MODE_AMP_ABSOLUTE;
        //define if the unit is px or percent of the view's height
        simpleWaveform.modeHeight = SimpleWaveform.MODE_HEIGHT_PERCENT;
        //define where is the x-axis in y-axis
        simpleWaveform.modeZero = SimpleWaveform.MODE_ZERO_CENTER;
        //if show bars?
        simpleWaveform.showBar = true;
    
        //define how to show peaks outline
        simpleWaveform.modePeak = SimpleWaveform.MODE_PEAK_PARALLEL;
        //if show peaks outline?
        simpleWaveform.showPeak = true;
    
        //show x-axis
        simpleWaveform.showXAxis = true;
        xAxisPencil.setStrokeWidth(1);
        xAxisPencil.setColor(0x88ffffff);//the first 0x88 is transparency, the next 0xffffff is color
        simpleWaveform.xAxisPencil = xAxisPencil;
    
        //define pencil to draw bar
        barPencilFirst.setStrokeWidth(15);
        barPencilFirst.setColor(0xff1dcf0f);
        simpleWaveform.barPencilFirst = barPencilFirst;
        barPencilSecond.setStrokeWidth(15);
        barPencilSecond.setColor(0xff1dcfcf);
        simpleWaveform.barPencilSecond = barPencilSecond;
    
        //define pencil to draw peaks outline
        peakPencilFirst.setStrokeWidth(5);
        peakPencilFirst.setColor(0xfffe2f3f);
        simpleWaveform.peakPencilFirst = peakPencilFirst;
        peakPencilSecond.setStrokeWidth(5);
        peakPencilSecond.setColor(0xfffeef3f);
        simpleWaveform.peakPencilSecond = peakPencilSecond;
    
        //the first part will be draw by PencilFirst
        simpleWaveform.firstPartNum = 20;//first 20 bars will be draw by first pencil
    
        //define how to clear screen
        simpleWaveform.clearScreenListener = new SimpleWaveform.ClearScreenListener() {
            @Override
            public void clearScreen(Canvas canvas) {
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            }
        };
        // set touch listener
        simpleWaveform.progressTouch = new SimpleWaveform.ProgressTouch() {
            @Override
            public void progressTouch(int progress, MotionEvent event) {
                Log.d("", "you touch at: " + progress);
                simpleWaveform.firstPartNum = progress;//set touch position back to its progress
                simpleWaveform.refresh();
            }
        };
        //show...
        simpleWaveform.refresh();
    
        demo_introduce.setText("demo3: amplitude bar");
    }
    
    <maxproj.com.simplewaveform.SimpleWaveform
        android:id="@+id/simplewaveform"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_margin="10dp" />
    
    第 1 条附言  ·  2016-01-17 00:03:38 +08:00
    已经上传 bintray ,使用方法改为:
    dependencies {
    compile 'com.maxproj.simplewaveform:app:1.0.0'
    }

    <com.maxproj.simplewaveform.SimpleWaveform
    android:id="@+id/simplewaveform"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:layout_margin="10dp" />
    4 条回复    2016-01-16 22:47:11 +08:00
    hpfs0
        1
    hpfs0  
       2016-01-13 08:55:28 +08:00
    不错,已 star 。至于怎么制作 gradle 模块,可以将项目打包后,在 bintray.com 上注册帐号上传就可以了。
    hyyou2010
        2
    hyyou2010  
    OP
       2016-01-13 10:22:46 +08:00
    @hpfs0 感谢!我尽快去 bintray 学习一下。
    shaobin0604
        3
    shaobin0604  
       2016-01-14 17:50:01 +08:00
    若是觉得 bentray 上传太麻烦,也可以使用 https://jitpack.io/
    hyyou2010
        4
    hyyou2010  
    OP
       2016-01-16 22:47:11 +08:00
    @shaobin0604 感谢!这个得去学习一下!的确有点麻烦的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3433 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 11:17 · PVG 19:17 · LAX 03:17 · JFK 06:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.