自定义view,paint,canvas,画线,画圆,画圈圈

1.简单介绍自定义View

创建一个简单的自定义View非常简单,创建自定义View类继承自View,提前创建好Paint对象,从写onDray()方法,然后在onDray()方法中绘制自己需要的图像即可。
例:绘制矩形
public class ViewDemo extends View {

    private Paint mPaint = new Paint();

    public ViewDemo(Context context) {
        super(context);
    }

    public ViewDemo(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ViewDemo(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    {
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(Color.RED);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.drawRect(200,100,800,600,mPaint);
    }
}

2.Canvas(画布),Paint(画笔)

2.1 Paint(画笔 ),Paint工具类有几个常用方法。

1.Paint.setStyle(Style style)设置绘制模式
2.Paint.setColor(int color)设置颜色
3.Paint.setStrokeWidth(float width)设置线条宽度
4.Paint.setTextSize(float textSize)设置文字大小
5.Paint.setAntiAlias(boolean true)抗锯齿开关

3.Canvas 的部分drawXXX()方法

3.1 drawColor(Color color)

    在整个绘制区域涂上指定颜色
    例:
    drawColor(Color.RED);  将整个图层涂黑
    关于颜色:
    1.

3.2 drawCircle(float centerX,float centerY,float readius,Paint paint)

    画圆
    例:
      drawCircle(100,100,50,paint);
image.png

这里,还可以设置Paint的各种参数,调节颜色,样式等

3.2.1.paint.setColor(Color color);可以设置画笔的颜色
image.png
3.2.2.paint.setStyle(Paint.Stytle Style);设置画笔的样式

比如:
1.paint.setStyle(Paint.Style.STROKE);// 修改Paint为画线样式
drawCircle(100,100,50,paint);


image.png

Paint.Style 类为一个枚举类


image.png

Paint.Style,里面有三种样式--FILL STROKE FILL_AND_STROKE
1.FILL 填充模式
2.STROKE 画线模式
3.FILL_AND_STROKE 两种模式共用,既填充又画线

Paint.Style 默认为FILL

3.2.3.Paint.setStrokeWidth(float width)

如果Style的模式为STROKE 或者 FILL_AND_STROKE,那还可以设置画笔的宽度


image.png
3.2.4.抗锯齿

在绘制的时候,很可能需要设置抗锯齿来使得图形或者文字来使得边缘更加平滑。
1.Paint.setAntiAlias(boolean true)
2.Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
例:


image.png

image.png

附:如果未开启抗锯齿,则图片会出现毛边现象。
抗锯齿不一定适用于所有场景,锯齿现象的产生,是由于图形分辨率过低,导致人眼察觉出了画面中的像素颗粒而已。如果不开启抗锯齿,图形的边缘也已经完美的,而并不是一个粗略计算的粗糙版本。开启抗锯齿后,之所以会看上去图形的边缘更加平滑,是因为修改图形边缘处的像素颜色,从而使得图形在肉眼看起来有更加平滑的感觉。


image.png
注:抗锯齿,在大多数情况下都应该开启。

3.3 drawRect(float left,float top,float right,float bottom,Paint paint) 矩形

    Left,top,right,bottom 是矩形四条边的坐标(简单理解就是左上角跟右下角两个点的坐标)

3.4 drawPoint(float x,float y,Paint paint) 画点

    1.x,y是点的坐标。
    2.点的大小是通过 paint.setStrokeWith(width)来设定。
    3.点的形状可以通过paint.setStrokeCap(cap)来设定。
        这个方法是设置线条端点的形状,端点有圆头(ROUND),平头(BUTT),方头(SQUARE)

3.5 drawPoints(……),可以批量画点

3.6 drawOval(float left,float top,float right,float bottom,Paint paint) 画椭圆

drawOval(RectF rect,Paint paint)也可以画椭圆


image.png

3.7 drawLine(float startX,float startY,float stopX,float stopY,Paint paint) 画线

    startX , startY , stopX , stopY 分别是线的起点和终点坐标。
    canvas.drawLine(200, 200, 800, 500, paint);
image.png
 drawLines(float[] pts,int offset,int count,Paint paint)/drawLines(float[] pts,Paint paint) 画线(批量画线)

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

    rx和ry是圆角的横向半径和纵向半径。
    drawRoundRectF(RectF rect,float rx,float ry,Paint paint)

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

    drawArc 是使用一个椭圆来描述弧形。
    startAngle 是弧形的起始角度(x轴正向为0度,顺时针为正角度)
    sweepAngle 是弧形滑过的角度。

userCenter 表示是否连接圆心。

4 路径

路径类似于我们用画笔画画,画笔所画出来的一段不间断的曲线就是路径
在Android中,Path 类就代表路径
在Canvas中绘制路径的方法:Canvas(Path path,Paint paint)

4.1 直接描述路径

addXXX() ---直接添加子图形
addCircle(float x,flaot y,float radius,Direction dir) 添加圆
x,y,radius 为圆心的位置,圆的半径,dir为画圆的路径的方向。

路径的方向:顺时针CCW,逆时针CW

添加椭圆:

addOval(float left, float top, float right, float bottom, Direction dir) / addOval(RectF oval, Direction dir)addRect(float left, float top, float right, float bottom, Direction dir) 

添加矩形:

addRect(RectF rect, Direction dir) 

添加圆角矩形:

addRoundRect(RectF rect, float rx, float ry, Direction dir) / addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Direction dir) / addRoundRect(RectF rect, float[] radii, Direction dir) / addRoundRect(float left, float top, float right, float bottom, float[] radii, Direction dir)

添加另一个 Path:

    addPath(Path path) 

xxxTo ----画线

xxxTo() 只是添加一条直线,addXxx()方法是添加的一整个封闭图形。

    lineTo(float x, float y) / rLineTo(float x, float y) 画直线
    从当前位置到目标位置画一条直线,x,y为目标位置的坐标。
    lineTo(float x, float y) x,y为绝对坐标
    rLineTo(float x, float y) x,y为相对坐标(既上次调用画Path方法的终点既为下一个起点)

例:

paint.setStyle(Style.STROKE);  
path.lineTo(100, 100); // 由当前位置 (0, 0) 向 (100, 100) 画一条直线  
path.rLineTo(100, 0); // 由当前位置 (100, 100) 向正右方 100 像素的位置画一条直线
image.png

quadTo(float x1, float y1, float x2, float y2) / rQuadTo(float dx1, float dy1, float dx2, float dy2) 画二次贝塞尔曲线

二次贝塞尔曲线的起点就是当前位置,x1,y1 和 x2,y2 就是控制点和终点的坐标。quadTo()为绝对坐标,rQuadTo()为相对坐标

贝塞尔曲线:
            贝塞尔曲线是几何上的一种曲线。他通过起点,控制点和终点来描述一种计算机图形学。
            简单的说,就是他可以绘制圆滑漂亮的曲线。

cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) / rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3) 画三次贝塞尔曲线

moveTo(float x, float y) / rMoveTo(float x, float y) 移动到目标位置
moveTo()就是移动到图形起点。

arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(RectF oval, float startAngle, float sweepAngle) 画弧形
arcTo() 用于画弧形,forceMoveTo 参数来控制画笔是否跟上一个图形相连接。

addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle) / addArc(RectF oval, float startAngle, float sweepAngle)
画弧形。
addArc() 相当于使用forceMoveTo = true 的 arcTo();

close() 封闭当前子图形

4.2 辅助的设置或者计算

Path.setFillType(Path.FillType ft) 设置填充方式
FillType 的值有四个 WIDING 为默认值


image.png

其中 前缀带 INVERSE 的为相反版本

WINDING与EVEN_ODD

image.png
            WINDING与EVEN_ODD原理
            即 even-odd rule (奇偶原则):
                对于平面中的任意一点,向任意方向射出一条射线,这条射线和图形相交的次数(相交才算,相切不算哦)如果是奇数,则这个点被认为在图形内部,是要被涂色的区域;如果是偶数,则这个点被认为在图形外部,是不被涂色的区域。还以左右相交的双圆为

例:

image.png

射线的方向无所谓,因为同一个点向任何地方射线,结果都是一样的。
从上图可以看出,射线每穿过图形中的一条线,内外状态就发生一次切换,这就是为什么 EVEN_ODD 是一个「交叉填充」的模式。

WINDING
在我们绘制任何图形的时候,都是有绘制方向的,WINDING,相当于我们


image.png

然后,同样是从平面中的点向任意方向射出一条射线,但计算规则不一样:以 0 为初始值,对于射线和图形的所有交点,遇到每个顺时针的交点(图形从射线的左边向右穿过)把结果加 1,遇到每个逆时针的交点(图形从射线的右边向左穿过)把结果减 1,最终把所有的交点都算上,得到的结果如果不是 0,则认为这个点在图形内部,是要被涂色的区域;如果是 0,则认为这个点在图形外部,是不被涂色的区域。


image.png

这里我们可以得出:INDING 确实是一个「全填充」的规则,但如果使用不同的方向来绘制图形,结果就不一样了。

4.3 drawBitmap(Bitmap bitmap, float left, float top, Paint paint) 画 Bitmap

重载方法
drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) /drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) /drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)

4.4 drawText(String text, float x, float y, Paint paint) 绘制文字

X,y 为绘制的起始点

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

推荐阅读更多精彩内容