wordpress 企业站 模板,做情书直接点网站,wordpress主题门户一号,网站建设补充协议范本Android给我们提供了大量的View控件#xff0c;但这还是远远满足不了我们的要求#xff0c;有时候开发所需要的控件形式是在Android提供的控件中是不存在#xff0c;这就需要我们自己去定义一个。那么如何自定义控件#xff1f;学习自定义控件#xff0c;首先要先掌握Canv…Android给我们提供了大量的View控件但这还是远远满足不了我们的要求有时候开发所需要的控件形式是在Android提供的控件中是不存在这就需要我们自己去定义一个。那么如何自定义控件学习自定义控件首先要先掌握Canvas类的使用。CanvasCanvas 我们称之为“画布“主要适用于绘制View的。Canvas中提供了大量绘制图形的方法绘制扇形drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint):第一个参数RectF对象指定扇形的区域第二个参数是起始角度第三个参数是旋转角度顺时针旋转第四个参数是是否填充true为填充false为不填充也就是为一条弧线第五个参数是绘制图形的画笔对象Paint。RectF通过RectF(float left, float top, float right, float bottom)构造器创建RectF对象我们通过下图理解各个参数的含义RectF对象指代的就是一个矩形区域。我们通过这四个参数构建矩形区域。Paint是绘制所有图形所用到的一个画笔我们在稍后讲解。drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint)这个是将扇形区域左上右下边的坐标直接输入而不是通过RectF对象。其他参数同上。绘制圆形drawCircle(float cx, float cy, float radius, Paint paint)第一、二个参数是指圆形的x, y坐标 第三个参数是半径 第四个参数是画笔Paint对象。绘制直线drawLine(float startX, float startY, float stopX, float stopY, Paint paint)两点确定一条直线第一、二参数是起始点的坐标第三、四参数是结束点的坐标第五个参数画笔Paint对象。drawLines(float[] pts, Paint paint)多个点确定一条直线第一个参数是点的数组第二个参数是画笔Paint对象。drawLines(float[] pts, int offset, int count, Paint paint)绘制椭圆drawOval(float left, float top, float right, float bottom, Paint paint)前四个参数是椭圆的左上右下边的坐标第五个是画笔Paint对象。drawOval(RectF oval, Paint paint)第一个参数是RectF对象 第二个参数是画笔Paint对象。绘制矩形drawRect(RectF rect, Paint paint)第一个参数是RectF对象 第二个参数是画笔Paint对象。绘制点drawPoint(float x, float y, Paint paint)第一、二个参数点的坐标第三个参数为Paint对象。渲染文本drawText(String text, float x, floaty, Paint paint)drawText(CharSequence text, int start, int end, float x, float y, Paint paint)drawText(char[] text, int index, int count, float x, float y, Paint paint)drawText(String text, int start, int end, float x, float y, Paint paint)Canvas中还给我们提供了很多绘制其他图形的方法这里我们不在一一列举。我们来看一下Paint”画笔“。PaintPaint是用于绘制的画笔Canvas就像是我们的画纸我们需要笔才可以完成一整幅图。Paint中为我们提供了很多设置的方法(我们这里只列举常用的方法)setARGB(int a, int r, int g, int b)设置 Paint对象颜色参数一为alpha透明值setAlpha(int a)设置alpha不透明度范围为0~255setAntiAlias(boolean aa)是否抗锯齿这个一般是都要设置的。setColor(int color)设置颜色这里Android内部定义的有Color类包含了一些常见颜色定义setTextScaleX(float scaleX)设置文本缩放倍数1.0f为原始setTextSize(float textSize)设置字体大小setUnderlineText(booleanunderlineText)设置下划线setStrokeCap(Paint.Cap cap)当画笔样式为STROKE或FILL_OR_STROKE时设置笔刷的图形样式如圆形样式 Cap.ROUND,或方形样式Cap.SQUAREsetSrokeJoin(Paint.Join join)设置绘制时各图形的结合方式如平滑效果等自定义View现在我们来使用Canvas类自定义一个View控件。自定义控件步骤如下1. 自定义View首先定义一个MyView类继承View类。2. 重写View的两个构造器。View是包含四个构造器的我们必须重写MyWidgetView(Context context, AttributeSet attrs)构造器因为该构造器的第二个参数是与xml布局文件相联系的如果没有重写该构造器将不能在布局中使用该控件。这里我们重写他的两个构造器public MyView(Context context) {super(context);}public MyView(Context context, AttributeSet attrs) {super(context, attrs);}3. 重写onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法定义控件的尺寸宽度和高度。在布局中使用该控件时会会传入控件的尺寸只有当传入尺寸之后且调用onMesure之后控件才会有宽度和高度。Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);width getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);height getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);setMeasuredDimension(width, height);//设置宽和高}重写onDraw(Canvas canvas)方法我们在该方法中定义绘制View当我们在Activity或其他地方使该控件时 UI主线程会调用onDraw方法绘制。Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);}onDraw(Canvas canvas)方法中传入了一个Canvas对象我们在定义控件时使用Canvas绘制。绘制时钟这里我们通过绘制一个时钟来巩固一下自定义控件以及Canvas类的使用。1. 定义一个MyView继承View。2. 重写MyView(Context context, AttributeSet attrs)构造器。3. 在重写onMeasureh和onDraw方法。4. 在onDraw方法中绘制。大体步骤就是这样我们先贴代码逐步讲解public class MyView extends View {private int width;//设置高private int height;//设置高private Paint mPaintLine;//定义一个绘制直线的画笔private Paint mPaintSecondLine;//定义一个绘制直线的画笔private Paint mPaintInterCircle;//定义一个绘制圆的画笔private Paint mPaintOutSideCircle;//定义一个绘制圆的画笔private Paint mPaintText;//定义一个绘制文字的画笔private Calendar mCalendar;//创建一个时间类private static final int NEED_INVALIDATE0X6666;//操作UI主线程private Handler handler new Handler() {Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what){case NEED_INVALIDATE://跟新时间mCalendarCalendar.getInstance();invalidate();sendEmptyMessageDelayed(NEED_INVALIDATE,1000);break;}}};public MyView(Context context) {super(context);}public MyView(Context context, AttributeSet attrs) {super(context, attrs);//初始化画直线的画笔mPaintLine new Paint();mPaintLine.setAntiAlias(true);//消除锯齿mPaintLine.setColor(Color.GRAY);//设置画笔颜色mPaintLine.setStyle(Paint.Style.STROKE);//设置为空心mPaintLine.setStrokeWidth(10);//设置宽度// 初始化秒针的画笔mPaintSecondLine new Paint();mPaintSecondLine.setAntiAlias(true);//消除锯齿mPaintSecondLine.setColor(Color.GRAY);//设置画笔颜色mPaintSecondLine.setStyle(Paint.Style.STROKE);//设置为空心mPaintSecondLine.setStrokeWidth(7);//设置宽度//初始化内圆的画笔mPaintInterCircle new Paint();mPaintInterCircle.setAntiAlias(true);//消除锯齿mPaintInterCircle.setColor(Color.BLACK);mPaintInterCircle.setStyle(Paint.Style.STROKE);//设置为空心mPaintInterCircle.setStrokeWidth(5);//初始化外圆的画笔mPaintOutSideCircle new Paint();mPaintOutSideCircle.setAntiAlias(true);//消除锯齿mPaintOutSideCircle.setColor(Color.BLACK);mPaintOutSideCircle.setStyle(Paint.Style.STROKE);//设置为空心mPaintOutSideCircle.setStrokeWidth(10);//绘制文字的画笔mPaintText new Paint();mPaintText.setAntiAlias(true);//消除锯齿mPaintText.setColor(Color.GRAY);mPaintText.setStyle(Paint.Style.STROKE);//设置为空心mPaintText.setTextAlign(Paint.Align.CENTER);mPaintText.setTextSize(40);mPaintText.setStrokeWidth(6);//初始化日历mCalendar Calendar.getInstance();//发送一个消息给UI主线程handler.sendEmptyMessageDelayed(NEED_INVALIDATE,2000);}Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);width getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);height getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);setMeasuredDimension(width, height);//设置宽和高}Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 主线程自动调用canvas.drawCircle(width / 2, height / 2, 300, mPaintInterCircle);canvas.drawCircle(width / 2, height / 2, 320, mPaintOutSideCircle);for(int i1; i12;i){canvas.save();//保存当前状态canvas.rotate(360 / 12 * i, width / 2, height / 2);canvas.drawLine(width / 2, height / 2 - 300, width / 2, height / 2 - 270, mPaintLine);canvas.drawText( i, width / 2, height / 2 - 240, mPaintText);canvas.restore();//回到save()方法保存的状态}//绘制分针int minute mCalendar.get(Calendar.MINUTE);float minuteDegree minute/60f*360;canvas.save();canvas.rotate(minuteDegree, width / 2, height / 2);canvas.drawLine(width / 2, height / 2 - 200, width / 2, height / 2 40, mPaintLine);canvas.restore();//绘制时针int hour mCalendar.get(Calendar.HOUR);float hourDegree (hour*60minute)//(12f*60)*360;canvas.save();canvas.rotate(hourDegree, width / 2, height / 2);canvas.drawLine(width / 2, height / 2 - 170, width / 2, height / 2 30, mPaintLine);canvas.restore();//绘制秒针int second mCalendar.get(Calendar.SECOND);float secondDegree second*6;//一秒是6度。canvas.save();canvas.rotate(secondDegree, width / 2, height / 2);canvas.drawLine(width / 2, height / 2 - 220, width / 2, height / 2 50, mPaintSecondLine);canvas.restore();}}绘制两个圆形嵌套这个很简单不用多说。然后绘制刻度是使用了Canvas画布的旋转这个很好理解我们在画画的时候有时候要画一些比较难的角度我们都是将画板旋转而不是我们自己换角度。在绘制时钟时我们要绘制时钟每个时间的刻度我们可以将要绘制刻度的位置旋转到竖直方向然后绘制。for(int i1; i12;i){canvas.save();//保存当前状态canvas.rotate(360 / 12 * i, width / 2, height / 2);canvas.drawLine(width / 2, height / 2 - 300, width / 2, height / 2 - 270, mPaintLine);canvas.drawText( i, width / 2, height / 2 - 240, mPaintText);canvas.restore();//回到save()方法保存的状态}然后绘制时针分针和秒针他们都是绘制一条线。然后通过获取当前的时间将这条线指向对得时间点也就是偏转对得角度。这里的偏转我们依然使用画布的偏转。以上完成后我们的时钟就差不多完成了但是我们发现我们的表并没有走。实现我们绘制的时钟转动的方式就是然我们的时钟每一秒onDraw一次这样我们的时钟正常了。onDraw是UI主线程不断调用重绘界面的因此我们需要使用到Handler通过发送一个消息给Handler对象让Handler对象在每一秒重绘一次MyView控件。这里重绘不能调用onDraw()方法额而要调用的是invalidate()方法invalidate()方法中调用了onDraw()方法。//操作UI主线程private Handler handler new Handler() {Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what){case NEED_INVALIDATE://跟新时间mCalendarCalendar.getInstance();invalidate();sendEmptyMessageDelayed(NEED_INVALIDATE,1000);break;}}};这样我们的时钟也转动了……