自定义View-第二步:绘制基础图形

前言

根据Gcssloop所学习的自定义View整理与笔记。

一、自定义View流程

简化版

二、自定义View的代码超级基础框架

public class MyView extends View {
    public MyView(Context context) {
        this(context, null);
    }
    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }
    //TODO 各种初始化内容
    private void initView() {
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //TODO 在这里进行绘图操作
    }
//    @Override
//    protected void dispatchDraw(Canvas canvas) {
//        super.dispatchDraw(canvas);
//    }
}

onDraw、dispatchDraw区别

  1. onDraw()的意思是绘制视图自身
    dispatchDraw()是绘制子视图
  1. 无论是View还是ViewGroup对它们俩的调用顺序都是onDraw()->dispatchDraw()
  2. 在绘制View控件时,需要重写onDraw()函数,在绘制ViewGroup时,需要重写dispatchDraw()函数。

三、绘制流程

1.** 初始化画笔**

//TODO 各种初始化内容
private void initView() {
   paint = new Paint();
   paint.setColor(Color.RED);//画笔颜色为红色
   paint.setStyle(Paint.Style.STROKE);//画笔模式为描边
   paint.setStrokeWidth(5f);//画笔宽度为5px
   paint.setAntiAlias(true); //是否使用抗锯齿功能
}

2.绘制内容

@Overrideprotected
 void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //TODO 在这里进行绘图操作
    //绘制底色
    canvas.drawColor(Color.BLACK);
    //在坐标(200,500)的位置绘制一个点
    canvas.drawPoint(200, 500, paint);
    //在这些坐标位置绘制多个点
    canvas.drawPoints(new float[]{
            200, 200,
            300, 300,
            400, 400
    }, paint);
    //绘制一条起点为(10,10),终点为(100,600)的直线
    canvas.drawLine(10, 10, 100, 600, paint); 
   //绘制一组线
    canvas.drawLines(new float[]{
            0, 0, 0, 400,
            0, 0, 500, 0
    }, paint);
    //绘制矩形
     //第一种方式
    canvas.drawRect(315,115,345,145,paint);
     //第二种方式
    Rect rect = new Rect(360, 115, 390, 145);
    canvas.drawRect(rect,paint);
    //第三种方式
    RectF rectF = new RectF( 335.5f, 160F,370.5f, 170.6f);
    canvas.drawRect(rectF,paint);
}
效果图

四、 绘制一些其他形状

  1. 圆角矩形
// 第一种
RectF rectF = new RectF(100,100,800,400);
//drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint)
canvas.drawRoundRect(rectF,30,30,paint);
// 第二种,API21以上可用
canvas.drawRoundRect(100,100,800,400,30,30,paint);

** rx,ry的理解**


圆角矩形的角实际上不是一个正圆的圆弧,而是椭圆的圆弧,这里的两个参数实际上是椭圆的两个半径
在rx为宽度的一半,ry为高度的一半时,刚好是一个椭圆,通过上面我们分析的原理推算一下就能得到,而当rx大于宽度的一半,ry大于高度的一半时,实际上是无法计算出圆弧的,所以drawRoundRect对大于该数值的参数进行了限制(修正),凡是大于一半的参数均按照一半来处理

  1. 椭圆
// 第一种
RectF rectF = new RectF(100,100,800,400);
canvas.drawOval(rectF,paint);
// 第二种
canvas.drawOval(100,100,800,400,paint);
椭圆原理
 // 绘制一个圆心坐标在(500,500),半径为400 的圆。
canvas.drawCircle(500,500,400,paint);
  1. 圆弧
// 第一种
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint){}
 // 第二种
public void drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint) {}

startAngle :开始角度
sweepAngle:扫过角度
useCenter:是否使用中心
demo来一个吧O(∩_∩)O~

    RectF rectF = new RectF(100, 100, 400, 300);
// 绘制背景矩形
        paint.setColor(Color.GRAY);
        canvas.drawRect(rectF, paint);
// 绘制圆弧
        paint.setColor(Color.BLUE);
        canvas.drawArc(rectF, 0, 60, false, paint);
        RectF rectF2 = new RectF(100, 400, 400, 600);
// 绘制背景矩形
        paint.setColor(Color.GRAY);
        canvas.drawRect(rectF2, paint);
// 绘制圆弧
        paint.setColor(Color.BLUE);
        canvas.drawArc(rectF2, 0, 60, true, paint);

效果图:

五、画个饼图

要点:不断改变startAngle和sweepAngle的值就OK啦,直接举栗子


饼图效果图
public class MyView extends View {
    public MyView(Context context) {
        this(context, null);
    }
    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }
    private Paint paint;
    private int[] startAngle = new int[6];
    private int[] color = {Color.BLACK, Color.BLUE, Color.CYAN, Color.GREEN, Color.MAGENTA};
    //TODO 各种初始化内容
    private void initView() {
        paint=new Paint();
        paint.setColor(Color.RED);//画笔颜色为红色
        paint.setStyle(Paint.Style.FILL);//画笔模式为描边
        paint.setStrokeWidth(5f);//画笔宽度为5px
        paint.setAntiAlias(true); //是否使用抗锯齿功能
        for (int i = 0; i < 5; i++) {
            startAngle[i] = i * 60 + i;
        }
        startAngle[5] = 360;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //TODO 在这里进行绘图操作
      //移动到屏幕(200,300)的位置,下一篇会具体讲解的
        canvas.translate(200, 300);
        RectF rect = new RectF(-100, -100, 200, 200);
        for (int i = 0; i < 5; i++) {
            paint.setColor(color[i]);
            canvas.drawArc(rect, startAngle[i], startAngle[i+1]-startAngle[i], true, paint);
        }
    }}

六、canvas的各种方法

[之后会讲解的,这里只提一下O(∩_∩)O~]

drawColor, drawRGB, drawARGB //使用单一颜色填充整个画布
drawPoint, drawPoints, drawLine, drawLines, drawRect, drawRoundRect, drawOval, drawCircle, drawArc//依次为 点、线、矩形、圆角矩形、椭圆、圆、圆弧
drawBitmap, drawPicture//绘制位图和图片
drawText, drawPosText, drawTextOnPath//依次为 绘制文字、绘制文字时指定每个文字位置、根据路径绘制文字
drawPath//绘制路径,绘制贝塞尔曲线时也需要用到该函数
drawVertices, drawBitmapMesh//通过对顶点操作可以使图像形变,drawVertices直接对画布作用、 drawBitmapMesh只对绘制的Bitmap作用
clipPath, clipRect//画布剪裁,设置画布的显示区域
save, restore, saveLayerXxx, restoreToCount, getSaveCount//依次为 保存当前状态、 回滚到上一次保存的状态、 保存图层状态、 回滚到指定状态、 获取保存次数
translate, scale, rotate, skew//画布变换,依次为 位移、缩放、 旋转、错切
getMatrix, setMatrix, concat//实际上画布的位移,缩放等操作的都是图像矩阵Matrix, 只不过Matrix比较难以理解和使用,故封装了一些常用的方法。

参考网址

  1. Android 的Paint(画笔)及Canvas(画布)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容