相关文章:Android自定义View之View的测量


之前讲了自定义View View的测量一部分,很好掌握吧?

但是View的测量只能控制View的大小,如果想定制外观,就要靠View的绘制。


View的绘制是要重写View  的 OnDraw方法

public class MyView extends View{public MyView(Context context) {super(context);}@Overrideprotected void onDraw(Canvas canvas){}}

我们再看一下View类中 onDraw的源码

/**     * Implement this to do your drawing.     *     * @param canvas the canvas on which the background will be drawn     */    protected void onDraw(Canvas canvas) {    }
是空的~  也就是什么也没绘制

所以我们上一篇文章测试时候的View,就是一个没有图形的View。

可能有人会说,上一篇文章,最后明明显示是一个矩形!

但是实际上,呢只是因为View的边界包裹起来本身是个矩形,这和View的绘制是两码事

绘制,就是好像,View是一张矩形的纸,我们在这个纸上画画


View的绘制,我们使用Canvas ,Paint ,Path三个类就可以基本完成各种图形了


Canvas:

我直接先把Canvas提供的绘制方法放出来,大家看一下

Canvas的绘制方法
方法签名 简要说明
drawLine(float startX, float startY, float stopX, float stopY, Paint paint) 绘制一条直线
drawLines(float[] pts, int offset, int count, Paint paint) 绘制多条直线
drawCircle(float cx, float cy, float radius, Paint paint) 绘制一个圆
drawOval(RectF oval, Paint paint) 绘制一个椭圆
drawPath(Path path, Paint paint) 根据路径绘制任意形状
drawPoint(float x, float y, Paint paint) 绘制一个点
drawPoints(float[] pts, int offset, int count, Paint paint)  绘制多个点
drawRect(float left, float top, float right, float bottom, Paint paint) 绘制矩形
drawRoundRect(RectF rect, float rx, float ry, Paint paint) 绘制圆角矩形
drawText(String text, int start, int end, Paint paint) 绘制字符串
drawTextOnPath(参数太多,表格放不下了,需要自己查吧...) 沿着路径绘制字符串
clipRect(float left, float top, float right, float bottom) 剪切一个矩形区域
clipRegion(Region region) 剪切制定区域
drawArc(参数太多,表格放不下了,需要自己查吧...) 绘制弧
drawBitmap(Bitmap bitmap, rect src, Rect dst, Paint paint) 绘制从源位图"挖取“的一块
drawBitmap(Bitmap bitmap, float left, float top, Paint paint) 绘制位图
   


















上表的各种方法具体使用不一一赘述了,大家看参数和简要说明应该就明白了,实在不懂可以搜索一下,具体用法我可能以后再开一篇总结吧~

我们上表就可以看出,Canvas就是提供给我们绘制基本图形的方法,复杂的图形也就是靠这些组合起来的~

此外,Canvas还提供了坐标变换的方法(Canvas的坐标原点在View的左上角,坐标轴方向遵循Android坐标系)


Canvas坐标变换的方法
方法签名 简要说明
rotate(float degrees, float px, float py) 旋转变换
scale(float sx, float sy, float px, float py) 缩放变换
skew(float sx, float sy) 倾斜变换
translate(float dx, float dy) 移动坐标原点


我们也可以看出,Canvas的使用,离不开 Paint,下面我们看一下Pait的方法


Paint

Paint 就好像生活中的画笔一样

Paint的常用方法
setARGB(int a, int r, int g, int b) 设置颜色
setAlpha(int a) 设置透明度
setAntiAlias(boolean aa) 设置是否抗锯齿
setColor(int color) 设置颜色
setPathEffect(PathEffect effect) 设置绘制路径时的路径效果
setShader(Shader shader) 设置画笔的填充效果
setShadowLayer(float radius, float dx, float dy, int color) 设置阴影
setStrokeWidth(float width) 设置画笔的笔尖宽度
setStrokeJoin(Paint.Join join) 设置画笔转弯处的连接风格
setStyle(Paint.Style style) 设置Pain的填充风格
setTextAlign(Paint.Align align) 设置绘制文本时的文字对齐方式
setTextSize(float textSize) 设置绘制文本时的文字大小












根据方法的简要说明,很清晰明了吧~

具体使用,自己试一试就更清楚啦~

下面我们直接上手做一个复合图形吧

效果图如下

就是一个常见的钟表盘(你会发现这个钟表盘的数字有点问题,接下来我们来看看实现代码就明白这个问题是怎么回事啦)

import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.util.AttributeSet;import android.view.View;public class Clock extends View{public Clock(Context context, AttributeSet attrs) {super(context, attrs);}public Clock(Context context) {super(context);}@Overrideprotected void onDraw(Canvas canvas){// 画外圆Paint paintCircle = new Paint();paintCircle.setStyle(Paint.Style.STROKE);//设置抗锯齿,防止缩放变换后图片出现锯齿边缘paintCircle.setAntiAlias(true);paintCircle.setStrokeWidth(5);//getWidth() 和 getHeight()是View自己的方法 获取View的宽和高//我们画一个以View中心点为圆心,半径为View宽度一半的圆//从这个函数参数的传递,我们也可以看出,Canvas的坐标原点在View左上角canvas.drawCircle(this.getWidth()/2, this.getHeight()/2, this.getWidth()/2, paintCircle);//画刻度的画笔Paint paintDegree = new Paint();paintDegree.setTextAlign(Paint.Align.CENTER);//从0点(12点)开始画刻度for(int i = 0; i < 12; i ++){//区分特殊点if(i == 0 || i == 3 || i == 6 || i == 9){//特殊的刻度,线更长,笔尖宽度更大paintDegree.setStrokeWidth(5);paintDegree.setTextSize(30);//大家自己琢磨一下这个线的起点和终点吧canvas.drawLine(this.getWidth()/2, this.getHeight()/2 - this.getWidth()/2, this.getWidth()/2, this.getHeight()/2 - this.getWidth()/2 + 60, paintDegree);String clockTime = null;//表盘上一般都把0点显示为12点if(i == 0)clockTime = String.valueOf(i + 12);elseclockTime = String.valueOf(i);canvas.drawText(clockTime, this.getWidth()/2, this.getHeight()/2 - this.getWidth()/2 + 90, paintDegree);}else{paintDegree.setStrokeWidth(3);paintDegree.setTextSize(15);canvas.drawLine(this.getWidth()/2, this.getHeight()/2 - this.getWidth()/2, this.getWidth()/2, this.getHeight()/2 - this.getWidth()/2 + 30, paintDegree);String clockTime = String.valueOf(i);canvas.drawText(clockTime, this.getWidth()/2, this.getHeight()/2 - this.getWidth()/2 + 60, paintDegree);}//这个地方,我们就用到了旋转坐标系的方法来达到每30度角画一个刻度//注意,这个是旋转坐标系!并不是旋转画布,也就是说,单独执行这个方法,你看不到任何效果的!canvas.rotate(30, this.getWidth()/2,this.getHeight()/2);}}//这里我们没有重写onMeasureprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){super.onMeasure(widthMeasureSpec, heightMeasureSpec);}}
代码注释的比较清楚,唯一就是旋转坐标系这个我想还是再强调一下。

因为当时自己开始以为是旋转画布,调用后,并没有变化。

而就是因为坐标系旋转了,所以我们呢个6点,就倒过来了,像9一样。


最后在xml文件中引用这个布局就可以了

   

项目源码AndroidOnDraw




更多相关文章

  1. 一起学android openg 纹理
  2. Android实例练习-可爱的小闹钟
  3. Linux设置qt-android开发环境
  4. Android39_Clock和TimePicker
  5. Android(安卓)Material Design之CardView(卡片式布局)
  6. Android自学——ListView
  7. Android(安卓)Kotlin项目集成阿里ARouter
  8. Android:保存图片到Sqlite数据库
  9. Android官方提供的支持不同屏幕大小的全部方法

随机推荐

  1. 用python实现超强的加密软件
  2. C#中调用MySQL存储过程的方法
  3. table课程表,用户注册模板,内联框架实现后
  4. PHP方法的返回值示例详解
  5. 一个简单的留言板
  6. dom元素的增删改操作
  7. PHP中国际化的字符串排序和比较对象详解
  8. js中的firstElementChild,lastElementChil
  9. 那些前端开发必不可少的生产力工具
  10. js的自定义dataset对象 ,js操作css, js中