淘先锋技术网

首页 1 2 3 4 5 6 7

自定义控件一直是让很多人包括我头疼的地方,难度较高 且学习资料零碎 直到我发现扔物线大神的HenCoder进阶手册.

这篇文章记录一下学习过程,以及途中经过精简的内容.便于日后查阅

1.1 绘制基础

关键词语: onDraw()方法 Canvas 画布 Paint画笔

一切的开始:

绘制圆形:

Paint paint = new Paint();

@Override
protected void onDraw(Canvas canvas) {  
    super.onDraw(canvas);
    // 绘制一个圆
    canvas.drawCircle(300, 300, 200, paint);
}
复制代码
  • 1.Canvas 类下的所有 draw- 打头的方法,例如 drawCircle() drawBitmap()。
  • 2.Paint 类的几个最常用的方法。具体是:

Paint.setStyle(Style style) 设置绘制模式

Paint.setColor(int color) 设置颜色

Paint.setStrokeWidth(float width) 设置线条宽度

Paint.setTextSize(float textSize) 设置文字大小

Paint.setAntiAlias(boolean aa) 设置抗锯齿开关

Canvas.drawColor(@ColorInt int color) 颜色填充.这是最基本的 drawXXX() 方法:在整个绘制区域统一涂上指定的颜色(可以这么理解: 画布整个染上了某种颜色), 这类颜色填充方法一般用于在绘制之前设置底色,或者在绘制之后为界面设置半透明蒙版。

类似方法(作用一致) : drawRGB(int r, int g, int b) 和 drawARGB(int a, int r, int g, int b)

drawCircle(float centerX, float centerY, float radius, Paint paint) 画圆,参数:圆心xy坐标 半径 画笔.原点是View 左上角的那个点;水平方向是 x 轴,右正左负

例:canvas.drawCircle(300, 300, 200, paint) 如下图:

划重点 : 一些独有信息(就是只有它有,别人没有的信息.例如画圆:圆心 半径) 都会直接作为参数写进 drawXXX() 方法里的(比如 drawCircle(centerX, centerY, radius, paint) 的前三个参数)。 而除此之外,其他的都是公有信息。比如图形的颜色、空心实心这些,你不管是画圆还是画方都有可能用到的,这些信息则是统一放在 paint 参数里的

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

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

  • drawPoints(float[] pts, int offset, int count, Paint paint) / drawPoints(float[] pts, Paint paint) 画点(批量)

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

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

  • drawLines(float[] pts, int offset, int count, Paint paint) / drawLines(float[] pts, Paint paint) 画线(批量)

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

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

  • drawPath(Path path, Paint paint) 画自定义图形

    Path 方法第一类:直接描述路径。

    * 第一组 : addXxx() ——添加子图形  
    eg:addCircle(float x, float y, float radius, Direction dir) 添加圆 还可以添加椭圆 矩形 圆角矩形
    
    * 第二组 : xxxTo() ——画线(直线或曲线)
    eg:lineTo(float x, float y) / rLineTo(float x, float y)前缀 r 代表 relatively 「相对地」 画直线.
    quadTo(float x1, float y1, float x2, float y2) / rQuadTo(float dx1, float dy1, float dx2, float dy2) 画二次贝塞尔曲线.
    moveTo(float x, float y) / rMoveTo(float x, float y) 移动到目标位置
    两个特殊的方法: arcTo() 和 addArc()。它们也是用来画线的,但并不使用当前位置作为弧线的起点。
    特殊1: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) 画弧形
    特殊2:addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle) / addArc(RectF oval, float startAngle, float sweepAngle)
    
    close() 封闭当前子图形它的作用是把当前的子图形封闭,即由当前位置向当前子图形的起点绘制一条直线。
    复制代码
    

    Path 方法第二类:辅助的设置或计算(场景比较少,只讲其中一个方法: setFillType(FillType fillType)。)

    Path.setFillType(Path.FillType ft) 设置填充方式
    FillType 的取值有四个:
    EVEN_ODD(原理:奇偶原则)
    WINDING (非零环绕数原则)(默认值)
    INVERSE_EVEN_ODD
    INVERSE_WINDING
    复制代码
    
  • drawBitmap(Bitmap bitmap, float left, float top, Paint paint) 画 Bitmap

  • drawText(String text, float x, float y, Paint paint) 绘制文字(Paint.setTextSize(float textSize)设置文字大小)

总结:1.1绘制基础: Canvas 的 drawXXX() 系列方法和 Paint 的基本使用,就到这里

想看1.1详细原文请戳这里,里面还有练习项目...

1.2 Paint详解

emm....这期的内容,只要做到「知道有这么个东西」,在需要用到的时候能想起来这个功能能不能做、大致用什么做就好,至于具体的实现,到时候拐回来再翻一次就行了。
复制代码

Paint 的 API 大致可以分为 4 类:

1.颜色

1.1 基本颜色
* 直接设置颜色 : setColor(int color) setARGB(int a, int r, int g, int b)
* 设置着色器 : setShader(Shader shader) 
        > LinearGradient 线性渐变
            Shader shader = new LinearGradient(100, 100, 500, 500, Color.parseColor("#E91E63"),Color.parseColor("#2196F3"),Shader.TileMode.CLAMP);
        > RadialGradient 辐射渐变(从中心向周围)
            Shader shader = new RadialGradient(300, 300, 200, Color.parseColor("#E91E63"), Color.parseColor("#2196F3"), Shader.TileMode.CLAMP);
        > SweepGradient 扫描渐变
            Shader shader = new SweepGradient(300, 300, Color.parseColor("#E91E63"),Color.parseColor("#2196F3"));
        > BitmapShader 用 Bitmap 的像素来作为图形或文字的填充
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.batman);  
            Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);  
        > ComposeShader 混合着色器
            // 第一个 Shader:头像的 Bitmap
            Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.batman);  
            Shader shader1 = new BitmapShader(bitmap1, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            // 第二个 Shader:从上到下的线性渐变(由透明到黑色)
            Bitmap bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.batman_logo);  
            Shader shader2 = new BitmapShader(bitmap2, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            // ComposeShader:结合两个 Shader
            Shader shader = new ComposeShader(shader1, shader2, PorterDuff.Mode.SRC_OVER); 
        
1.2 设置颜色过滤器 setColorFilter(ColorFilter colorFilter)
        > LightingColorFilter 模拟光照效果
            ColorFilter lightingColorFilter = new LightingColorFilter(0x00ffff, 0x000000);  
        > PorterDuffColorFilter 使用一个指定的颜色和一种指定的 PorterDuff.Mode 来与绘制对象进行合成
            PorterDuffColorFilter(int color, PorterDuff.Mode mode) 
        > ColorMatrixColorFilter 使用一个 ColorMatrix 来对颜色进行处理。 ColorMatrix 这个类,内部是一个 4x5 的矩阵(厉害了)
1.3 setXfermode(Xfermode xfermode)  以绘制的内容作为源图像,以 View 中已有的内容作为目标图像,选取一个  PorterDuff.Mode 作为绘制内容的颜色处理方案
复制代码

2.效果

2.1 setAntiAlias (boolean aa) 设置抗锯齿
2.2 setStyle(Paint.Style style) 设置填充模式
2.3 线条形状,四个方法:
    >  setStrokeWidth(float width)设置线条宽度。单位为像素,默认值是 0。
    >  setStrokeCap(Paint.Cap cap)设置线头的形状。线头形状有三种:BUTT 平头、ROUND 圆头、SQUARE 方头。默认为 BUTT。
    >  setStrokeJoin(Paint.Join join)设置拐角的形状。有三个值可以选择:MITER 尖角、 BEVEL 平角和 ROUND 圆角。默认为 MITER。
    >  setStrokeMiter(float miter)这个方法是对于 setStrokeJoin() 的一个补充,它用于设置 MITER 型拐角的延长线的最大值。
2.4 色彩优化.Paint 的色彩优化有两个方法: setDither(boolean dither) 和 setFilterBitmap(boolean filter)    
    >  setDither(boolean dither)设置图像的抖动。
    >  setFilterBitmap(boolean filter)设置是否使用双线性过滤来绘制 Bitmap 。
2.5 setPathEffect(PathEffect effect)使用 PathEffect 来给图形的轮廓设置效果。
2.6 setShadowLayer(float radius, float dx, float dy, int shadowColor)在之后的绘制内容下面加一层阴影。
2.7 setMaskFilter(MaskFilter maskfilter)为之后的绘制设置 MaskFilter。 有BlurMaskFilter模糊效果 EmbossMaskFilter浮雕效果 
2.8 获取绘制的 Path.根据 paint 的设置,计算出绘制 Path 或文字时的实际 Path。
    >  getFillPath(Path src, Path dst) 获取实际path
    >  getTextPath(String text, int start, int end, float x, float y, Path path) / getTextPath(char[] text, int index, int count, float x, float y, Path path)获取文字path
复制代码

3.drawText() 相关

方法太多,下一节里单独讲;
复制代码

4.初始化

它们是用来初始化 Paint 对象,或者是批量设置 Paint 的多个属性的方法
4.1 reset() 重置 Paint 的所有属性为默认值。相当于重新 new 一个,不过性能当然高一些啦。
4.2 set(Paint src) 把 src 的所有属性全部复制过来。相当于调用 src 所有的 get 方法,然后调用这个 Paint 的对应的  set 方法来设置它们。
4.3 setFlags(int flags)  批量设置 flags。相当于依次调用它们的 set 方法。例如:
复制代码

最后再强调一遍:这期的内容没必要全部背会,只要看懂、理解,记住有这么个东西就行了。以后在用到的时候,再拐回来翻一翻就行了。

原文及练习传送门