android 自定义view 之 动态音频图 (二)

还是和上一篇一样,先上效果图



这次要比上次难了点,

首先我们把自定义文件贴上

/**
 * 作者:chengxiangtong on 2016/11/10 14:44
 * 邮箱:[email protected]
 * 仿音频条
 */

public class AudioView extends View {
    
    private Random mttt = new Random();
private Paint mPaint;  
private int width;    
private int height;    
private int mRectWidth = 10;    
private int mRectHeight = 60;   
 private int offset = 3;//每次画之前的左边距离   

 public AudioView(Context context, AttributeSet attrs, int defStyleAttr) {        
super(context, attrs, defStyleAttr);        init();    }    public AudioView(Context context) {        this(context, null);    }    public AudioView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    private void init() {        mPaint = new Paint();    }    @Override protected void onDraw(Canvas canvas) {        super.onDraw(canvas);	//获取padding        int left = getPaddingLeft();        int top = getPaddingTop();        int right = getPaddingRight();        int bottom = getPaddingBottom();        width = getMeasuredWidth() - left - right;        height = getMeasuredHeight() - top - bottom;        int mRectCount = 0;        for (int count = 5; count < width; count += mRectWidth) {            mRectCount++;        }        for (int i = 0; i < mRectCount; i++) {            double mRandom = Math.random();
	    //随机数产生各种画笔的颜色,当然你也可以在初始化的时候固定一种颜色
int n = mttt.nextInt(4); if (n == 0) { mPaint.setColor(Color.BLUE); } else if (n == 1) { mPaint.setColor(Color.RED); } else if (n == 2) { mPaint.setColor(Color.LTGRAY); } else { mPaint.setColor(Color.GREEN); } mRectHeight = (int) (mRandom * height);//获取每次随机的高度 canvas.drawRect(offset + mRectWidth * i, mRectHeight, mRectWidth * (i + 1), height, mPaint); } postInvalidateDelayed(500);//每间隔500ms刷新一次,这样才有动的效果 } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthsize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) { setMeasuredDimension(getMeasuredWidth() / 2, getMeasuredHeight() / 2); } else if (widthMode == MeasureSpec.AT_MOST) { setMeasuredDimension(getMeasuredWidth() / 2, heightSize); } else if (heightMode == MeasureSpec.AT_MOST) { setMeasuredDimension(widthsize, getMeasuredHeight() / 2); } }}
这个主要说说onMeasure()这个方法,这个是来测试布局的,下面就是他的全部意思啦:

onMeasure传入的两个参数是由上一层控件传入的大小,有多种情况,重写该方法时需要对计算控件的实际大小,然后调用setMeasuredDimension(int, int)设置实际大小。


onMeasure传入的widthMeasureSpec和heightMeasureSpec不是一般的尺寸数值,而是将模式和尺寸组合在一起的数值。我们需要通过int mode = MeasureSpec.getMode(widthMeasureSpec)得到模式,用int size = MeasureSpec.getSize(widthMeasureSpec)得到尺寸。

mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY, MeasureSpec.AT_MOST。


MeasureSpec.EXACTLY是精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width="50dip",或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。


MeasureSpec.AT_MOST是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。


MeasureSpec.UNSPECIFIED是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。


所以你现在对于这段代码就不陌生了

  if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
        } else if (widthMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(getMeasuredWidth() / 2, heightSize);
        } else if (heightMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(widthsize, getMeasuredHeight() / 2);
        }

分别表示什么自己对照就好了微笑,在布局中直接调用就可以啦,不在给贴布局啦,实在是不好意思,浪费时间呀,有没有发现比第一篇还简单呀,自己可以运行看看啦

github地址:https://github.com/xiangtongcheng/customerView



你可能感兴趣的:(android,view,自定义)