一个简单的Android自定义View

来源:互联网 发布:淘宝店芥末和小镇姗姗 编辑:程序博客网 时间:2024/06/11 22:21

       最近有个项目中需要录音,参考了一个APP,录音实时用声波图显示声音大小,并且录音结束后可通过拖拽定位修改其中某一段时间的声音。这两天比较闲了,写了个没任何技术含量的波形图自定义view(就是在画线),欢迎指教。

因为音频录制的方式很多,所以这个view只负责接收表示音量大小的值,具体传过来的值多大多小不限制,取所有的值中最大值按比例缩放。




代码如下:

public class WaveView extends View {    public WaveView(Context context) {        super(context);    }    public WaveView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        init(attrs);    }    public WaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(attrs);    }    private Integer waveType;//波形展示类型    private int centerLineColor = Color.BLACK;    private int centerLineWidth = 1;    private int lineColor = Color.GREEN;    private int lineWidth = 10;//竖线的宽度    private int lineSpace = 30;//竖线之间的间隔宽度    public static final int WVTYPE_CENTER_LINE = 0;//竖线从中间开始 向上向下长度相同    public static final int WVTYPE_SINGLE = 1;//竖线从底部开始向上计算    private List<Integer> values;//存放数值    private int fullValue = 100;//相对最大值    private float mScale = 0;//传入值转换为有效数值需要使用的比例    private int maxValue = 1;//当前数组中的最大值 该值乘以scale应等于fullValue    private int maxLineCount ;    private boolean hasOver;//值记录是否已完毕    Paint paintCenterLine,paintLine;    private void init(AttributeSet attrs){        final TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.WaveView);        waveType = typedArray.getInt(R.styleable.WaveView_wvType, 0);        centerLineColor = typedArray.getColor(R.styleable.WaveView_wvCenterLineColor,Color.BLACK);        centerLineWidth = typedArray.getDimensionPixelSize(R.styleable.WaveView_wvCenterLineWidth,1);        lineColor = typedArray.getColor(R.styleable.WaveView_wvLineColor,Color.GREEN);        lineWidth = typedArray.getDimensionPixelSize(R.styleable.WaveView_wvLineWidth,10);        lineSpace = typedArray.getDimensionPixelSize(R.styleable.WaveView_wvLineSpace,30);        paintCenterLine = new Paint();        paintCenterLine.setStrokeWidth(centerLineWidth);        paintCenterLine.setColor(centerLineColor);        paintLine = new Paint();        paintLine.setStrokeWidth(lineWidth);        paintLine.setAntiAlias(true);        paintLine.setColor(lineColor);    }    public void putValue(int value){        if (value>maxValue){            maxValue = value;            mScale = (float) fullValue/maxValue;        }        if (values==null){            values = new ArrayList<>();        }else {//            values.add(value);//            invalidate();        }        values.add(value);        invalidate();    }    public void setHasOver(boolean over){        hasOver = over;    }    public boolean hasOver(){        return hasOver;    }    private int lastX,moveX;    private boolean hasBeenEnd=false;    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                lastX = (int) (event.getRawX());                break;            case MotionEvent.ACTION_MOVE:                int x = (int) event.getRawX();                //到达边缘时不能向该方向继续移动                if (!hasBeenEnd || (moveX>0&&(lastX-x)<0 ||(moveX<0&&(lastX-x)>0)))  {                    moveX += (lastX-x)*0.7;                    lastX = x;                    invalidate();                }                break;        }        return true;    }    @Override    protected void onDraw(Canvas canvas) {        int yCenter = getHeight() / 2;        if (maxLineCount==0){            maxLineCount = getWidth()/(lineSpace+lineWidth);        }        if (waveType==WVTYPE_CENTER_LINE){            /***************画中线*****************/            canvas.drawLine(0,yCenter,getWidth(),yCenter,paintCenterLine);        }        /***************画竖线*****************/        //判断当前数组中的数据是否超出了可画竖线最大条数        if(values!=null){            /**找出当前第一条竖线以及偏移量*/            int startIndex = 0;//第一条线            int startOffset = 0;//第一条线的偏移            if (!hasOver || moveX==0){//仍在记录中或未手动滑动过                //线条数量超出最大数 只画后面的线                if(values.size()>maxLineCount){                    startIndex = values.size()-maxLineCount;                }            }else {//已结束录值 且x轴有过移动                //先得到第一条线原本应该的位置                if(values.size()>maxLineCount){                    startIndex = values.size()-maxLineCount;                }                //计算移动线条数                int moveLineSize = moveX/(lineWidth+lineSpace);                startOffset = moveX%(lineWidth+lineSpace);                int currentIndex = startIndex+moveLineSize;                if (currentIndex<0){//到达最左边                    startIndex = 0;                    startOffset = 0;                    hasBeenEnd = true;                }else if (currentIndex>=values.size()){                    startIndex = values.size()-1;                    startOffset=0;                    hasBeenEnd = true;                }else {                    startIndex = currentIndex;                    hasBeenEnd = false;                }                Log.d("XXXXXXX","move-x:"+moveX+"   moveLineSize:"+moveLineSize                        +"   startIndex:"+startIndex+"  startOffset:"+startOffset);            }            //画竖线            for (int i=startIndex;i<values.size();i++){                int startX =0;                int endX =0;                int startY =0;                int endY =0;                int lineHeight = (int) ((((float)values.get(i)*mScale)/fullValue)*getHeight());                switch (waveType){                    case WVTYPE_CENTER_LINE:                        startX = (i-startIndex)*(lineSpace+lineWidth)+lineWidth/2 - startOffset ;                        endX =  startX;                        startY = (getHeight()-lineHeight)/2;                        endY = (getHeight()-lineHeight)/2+lineHeight;                        break;                    case WVTYPE_SINGLE:                        startX = (i-startIndex)*(lineSpace+lineWidth)+lineWidth/2 - startOffset ;                        endX =  startX;                        startY = getHeight()-lineHeight;                        endY = getHeight();                        break;                }                canvas.drawLine(startX,startY,endX,endY,paintLine);               // Paint pNum = new Paint();               // pNum.setColor(Color.RED);               // canvas.drawText(""+i,startX,yCenter,pNum); 画出竖线index便于测试            }        }    }}
样式相关:

<resources>    <declare-styleable name="WaveView">        <attr name="wvType" format="enum">            <enum name="centerLine" value="0"/>            <enum name="single" value="1"/>        </attr>        <attr name="wvCenterLineColor" format="color" />        <attr name="wvCenterLineWidth" format="dimension" />        <attr name="wvLineColor" format="color" />        <attr name="wvLineWidth" format="dimension" />        <attr name="wvLineSpace" format="dimension" />    </declare-styleable></resources>

源码下载:github源码

原创粉丝点击