还是和上一篇一样,先上效果图
这次要比上次难了点,
首先我们把自定义文件贴上
/** * 作者:chengxiangtong on 2016/11/10 14:44 * 邮箱:[email protected] * 仿音频条 */ public class AudioView extends View {private Paint mPaint;private Random mttt = new Random();
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();这个主要说说onMeasure()这个方法,这个是来测试布局的,下面就是他的全部意思啦://随机数产生各种画笔的颜色,当然你也可以在初始化的时候固定一种颜色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传入的两个参数是由上一层控件传入的大小,有多种情况,重写该方法时需要对计算控件的实际大小,然后调用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