自定义控件(一)

最近在跟扔物线大婶学自定义控件,其实许多东西之前都用过的,不过时间长就忘了,然后这次就系统的复习一下,顺便记录下来。
自定义绘制,首先要创建好Paint对象,重写onDraw(),把绘制代码写在onDraw()里,这就是自定义绘制最基本的实现。Paint和canvas组合使用可以画出各种各样的图形。

Paint类的常用方法

  • paint.setStyle(Style style) 设置绘制模式
  • paint.setColor(int color) 设置颜色
  • paint.setStrokeWidth(float width) 设置线条宽度
  • paint.setTextSize(float textSize) 设置文字大小
  • paint.setAntiAlias(boolean aa) 设置抗锯齿开关(初始化Paint时可直接设置)

paint.setStyle(Style style)主要有三种样式:FILL,STROKE和FILL_AND_STROKE。FILL 是填充模式,STROKE 是画线模式(即勾边模式),FILL_AND_STROKE 是两种模式一并使用:既画线又填充。它的默认值是 FILL,填充模式。

1.canvas.drawColor()颜色填充

这算是最简单的了,直接canvas.drawColor(Color.Yellow)。类似的方法还有drawColor(Color.parse("")),直接填16进制色值就行,例如drawColor(Color.parse("#F00")),drawColor(Color.parse("#6F00")),drawColor(Color.parse("#CCCCCC")),drawColor(Color.parse("#88880000"))。 drawRGB(int r, int g, int b),drawARGB(int a, int r, int g, int b)
drawColor()
    canvas.drawColor(Color.YELLOW);

2.canvas.drawCircle(float centerX, float centerY, float radius, Paint paint)画圆

前两个参数表示圆的圆心坐标,radius是圆心半径,paint可以设置圆的填充颜色,空心圆还是实心圆还是圆环,还有圆环的宽度等(插一句,从屏幕左上角,向右为X轴正方向,向下为Y轴正方向)


drawCircle()
        //实心圆
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);//开启抗锯齿
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(200,200, 150, paint);
        //空心圆
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawCircle(700, 200, 150, paint);
        //蓝色实心圆
        paint.setColor(Color.BLUE);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(700, 600, 150, paint);
        //空心圆环,环宽20
        paint.setStrokeWidth(20);
        canvas.drawCircle(200, 600, 150, paint);

3.canvas.drawRect(float left, float top, float right, float bottom, Paint paint)画矩形

drawRect()
canvas.drawRect(100,100,400,300,paint);

从上面可以很明显的看到各个参数所代表的意思。矩形的width = right-left,矩形的hight = bottom-top。当宽和高相等时就是正方形。例如,我要画一个宽为300,高为200的矩形,是这样的canvas.drawRect(100,100,400,300,paint)

4.canvas.drawPoint(float x, float y, Paint paint)画点

x 和 y 是点的坐标。点的大小可以通过 paint.setStrokeWidth(width) 来设置;点的形状可以通过 paint.setStrokeCap(cap) 来设置:ROUND 画出来是圆形的点,SQUARE 或 BUTT 画出来是方形的点。


drawPoint()
        //圆点
        paint.setColor(Color.BLACK);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(60);
        canvas.drawPoint(200, 200, paint);
        方点
        paint.setStrokeCap(Paint.Cap.SQUARE);
        paint.setStrokeWidth(60);
        canvas.drawPoint(500,200,paint);

drawPoint()是画单个点,还有两个方法是批量画点,drawPoints(float[] pts, int offset, int count, Paint paint) / drawPoints(float[] pts, Paint paint),

float[] points = {0, 0, 50, 50, 50, 100, 100, 50, 100, 100, 150, 50, 150, 100};每两个数字为一个点

// 绘制四个点:(50, 50) (50, 100) (100, 50) (100, 100)
canvas.drawPoints(points, 2 /* 跳过两个数,即前两个 0 */, 4 /* 坐标个数,也就是两个点*/, paint);
//绘制所有的点
canvas.drawPoints(points,paint);

5.canvas.drawOval(float left, float top, float right, float bottom, Paint paint)画椭圆

left, top, right, bottom 是这个椭圆的左、上、右、下四个边界点的坐标


draw.Oval()
//实心椭圆
paint.setStyle(Style.FILL);
canvas.drawOval(50, 50, 350, 200, paint);
//空心椭圆
paint.setStyle(Style.STROKE);
canvas.drawOval(400, 50, 700, 200, paint);

6.canvas.drawLine(float startX, float startY, float stopX, float stopY, Paint paint)画线

前两个参数是线的起点坐标,然后两个是终点坐标。


drawLine()
paint.setStrokeWidth(20);//设置线宽
canvas.drawLine(100, 100, 600, 500, paint);paint

画线跟画点类似,也有批量画线的方法drawLines(float[] pts, int offset, int count, Paint paint) / drawLines(float[] pts, Paint paint)

float[] points = {20, 20, 120, 20, 70, 20, 70, 120, 20, 120, 120, 120, 150, 20, 250, 20, 150, 20, 150, 120, 250, 20, 250, 120, 150, 120, 250, 120};
canvas.drawLines(points, paint);  //画所有线
canvas.drawPoints(points, 2 /* 跳过两条线,即4个点,8个数字 */, 3 /* 一共绘制三个点*/, paint);

7.canvas.drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint)画圆角矩形

left, top, right, bottom 是四条边的坐标,rx 和 ry 是圆角的横向半径和纵向半径。


drawRoundRect()
//实心圆角矩形
canvas.drawRoundRect(100,100,600,300,30,30,paint);(设置paint填充模式可画空心圆角矩形)

8.canvas.drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint) 绘制弧形或扇形

drawArc() 是使用一个椭圆来描述弧形的。left, top, right, bottom 描述的是这个弧形所在的椭圆;startAngle 是弧形的起始角度(x 轴的正向,即正右的方向,是 0 度的位置;顺时针为正角度,逆时针为负角度),sweepAngle 是弧形划过的角度;useCenter 表示是否连接到圆心,如果不连接到圆心,就是弧形,如果连接到圆心,就是扇形。


drawArc()
paint.setStyle(Paint.Style.FILL); // 填充模式
canvas.drawArc(200, 100, 800, 500, -110, 100, true, paint); // 绘制扇形
canvas.drawArc(200, 100, 800, 500, 20, 140, false, paint); // 绘制弧形
paint.setStyle(Paint.Style.STROKE); // 画线模式
canvas.drawArc(200, 100, 800, 500, 180, 60, false, paint); // 绘制不封口的弧形

9.canvas.drawPath(Path path, Paint paint) 画自定义图形(重点来了)

Path 可以描述直线、二次曲线、三次曲线、圆、椭圆、弧形、矩形、圆角矩形。把这些图形结合起来,就可以描述出很多复杂的图形。Path 有两类方法,一类是直接描述路径的,另一类是辅助的设置或计算。(详细解释请点这里
下面来重点分析下这个心形是怎么画的

drawPath()

      Path path = new Path(); // 初始化 Path 对象
      //第一步,path添加左边一个扇形
      path.addArc(200, 200, 400, 400, -225, 225);
      //第二步,从第一步完成的地方添加右边的扇形
      path.arcTo(400, 200, 600, 400, -180, 225, false);
      //第三步,从第二部步结束的地方画线,到点(400,542)也就是心形最下面的点,并与起点封闭封闭
      path.lineTo(400, 542);
      //画图
      canvas.drawPath(path, paint);

path可以添加各种形状,然后相互连接起来。


path

path

更多的方法,大家可以自己研究研究。

10.canvas.drawBitmap(Bitmap bitmap, float left, float top, Paint paint) 画 Bitmap

绘制 Bitmap 对象,也就是把这个 Bitmap 中的像素内容贴过来。其中 left 和 top 是要把 bitmap 绘制到的位置坐标。

canvas.drawBitmap(bitmap, 200, 100, paint);

11.canvas.drawText(String text, float x, float y, Paint paint) 绘制文字

界面里所有的显示内容,都是绘制出来的,包括文字。 drawText() 这个方法就是用来绘制文字的。参数 text 是用来绘制的字符串,x 和 y 是绘制的起点坐标。
通过 Paint.setTextSize(textSize),可以设置文字的大小。

paint.setTextSize(18);
canvas.drawText(text, 100, 25, paint);
paint.setTextSize(36);
canvas.drawText(text, 100, 70, paint);

12.画柱状图和饼图

练习

这些复杂的图形其实就是把前面讲到的方法综合起来用就可以绘制成想要的图形了。把一些基本的封装起来,再把一些可以设置值和颜色的方法暴露出去,就成了自己的自定义控件。

推荐两个图表类的开源项目,一个android的MPAndroidChart,一个h5页面上可以用的ECharts

以上所有的代码在这里

另外强烈推荐大家关注下扔物线大神的公众号,这是一个系列的教程,每周一篇。

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

推荐阅读更多精彩内容