前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android自定义View【实战教程】3⃣️----Paint类、Path类以及PathEffect类详解

Android自定义View【实战教程】3⃣️----Paint类、Path类以及PathEffect类详解

作者头像
先知先觉
发布2019-01-21 15:18:54
1.1K0
发布2019-01-21 15:18:54
举报

Paint类使用详解

Paint 代表了Canvas上的画笔、画刷、颜料等等

方法

作用

setARGB(int a, int r, int g, int b)

设置Paint对象颜色,参数一为alpha透明通道

setAlpha(int a)

设置alpha不透明度,范围为0~255

setMaskFilter(MaskFilter maskfilter)

滤镜效果

setStyle(Style style);

设置画笔风格

setStrokeWidth(int width)

设置画笔空心线宽

setDither(boolean dither)

设定是否使用图像抖动处理,使绘制出的图片颜色更平滑饱满,图像更加清晰

setAntiAlias(boolean aa)

是否抗锯齿

setColor(int color)

设置颜色,这里Android内部定义的有Color类包含了一些常见颜色定义

setFakeBoldText(boolean fakeBoldText)

设置伪粗体文本

setLinearText(boolean linearText)

设置线性文本

setPathEffect(PathEffect effect)

设置路径效果

setRasterizer(Rasterizer rasterizer

设置光栅化

setShader(Shader shader)

设置阴影

setTextAlign(Paint.Align align)

设置文本对齐

setTextScaleX(float scaleX)

设置文本缩放倍数,1.0f为原始

setTextSize(float textSize)

设置字体大小

setTypeface(Typeface typeface)

设置字体,Typeface包含了字体的类型,粗细,还有倾斜、颜色等。

setUnderlineText(boolean underlineText)

设置下划线

setStrokeCap(CAP cap)

线段末端效果

setStrokeJoin(Join join)

闭合图形的连接处效果

先看一个简单的demo:

代码语言:javascript
复制
public class DemoView extends View {
    Paint paint = new Paint();
    Path path = new Path();

    public DemoView(Context context) {
        this(context,null);
    }

    public DemoView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public DemoView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init();
    }

    private void init(){
        paint.setAntiAlias(false);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(10);
        paint.setColor(Color.parseColor("#ff0000"));

        //path在后面进行讲解
        path = new Path();
        path.moveTo(150, 400);
        path.lineTo(450, 400);
        path.lineTo(300, 150);
        path.close();

    }

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

        canvas.drawPath(path,paint);
    }
}

效果如图:

这里写图片描述
这里写图片描述

下面几个重要属性详细介绍:

setAlpha(int a) —透明度

代码语言:javascript
复制
paint.setAlpha(100);
这里写图片描述
这里写图片描述

setAntiAlias(boolean aa) —是否抗锯齿

false不抗锯齿

代码语言:javascript
复制
 paint.setAntiAlias(false);
这里写图片描述
这里写图片描述

true抗锯齿

代码语言:javascript
复制
 paint.setAntiAlias(true);
这里写图片描述
这里写图片描述

setStyle(Style style)—设置画笔风格

Style.FILL:实心 Style.FILL_AND_STROKE:同时显示实心和空心 Style.STROKE:空心

代码语言:javascript
复制
paint.setStyle(Paint.Style.STROKE);

效果如图:

这里写图片描述
这里写图片描述
代码语言:javascript
复制
paint.setStyle(Paint.Style.FILL);
这里写图片描述
这里写图片描述

setStrokeWidth—空心画笔宽度

代码语言:javascript
复制
setStrokeWidth(int width)
这里写图片描述
这里写图片描述

setStrokeCap(CAP cap)—线段末端效果

这里写图片描述
这里写图片描述

setStrokeJoin(Join join)—闭合图形的连接处效果

这里写图片描述
这里写图片描述

setTextAlign(Paint.Align align)—设置文本对齐

这里写图片描述
这里写图片描述

setTextSize(float testSize)—设置字体的大小

代码语言:javascript
复制
    private void init(){
        paint.setAntiAlias(true);
        paint.setColor(Color.parseColor("#ff0000"));
        paint.setTextSize(50);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText("自定义View",200,200,paint);
    }

如图:

这里写图片描述
这里写图片描述

setShader(Shader shader)—设置阴影

Shader本身是一个抽象类,它提供了如下实现类:

BitmapShader: 使用位图平铺的渲染效果. LinearGradient: 使用线性渐变来填充图形. RadialGradient: 使用圆形渐变来填充图形. SweepGradient: 使用角度渐变来填充图形. ComposeShader: 使用组合渲染效果来填充图形.

代码语言:javascript
复制
    private void init() {
        paint.setAntiAlias(true);
        paint.setColor(Color.parseColor("#ff0000"));
        paint.setTextSize(50);
        int[] colors = new int[] { Color.RED, Color.GREEN, Color.BLUE };
        Shader shader = new RadialGradient(100, 100, 80,colors, null, TileMode.REPEAT);
        paint.setShader(shader·);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText("自定义View", 200, 200, paint);
    }

如图:

这里写图片描述
这里写图片描述

是不是有种艺术字的效果。

setTextScaleX(float scaleX)—设置缩放倍数

设置水平缩放

代码语言:javascript
复制
 paint.setTextScaleX(2);

如图:

这里写图片描述
这里写图片描述

设置字体类型

public static final Typeface DEFAULT; // 默认字体 public static final Typeface DEFAULT_BOLD; //加粗 public static final Typeface SANS_SERIF; //sans serif字体类型 public static final Typeface SERIF; //SERIF字体 public static final Typeface MONOSPACE; //等宽字体

代码语言:javascript
复制
 paint.setTypeface(Typeface.DEFAULT_BOLD);  //加粗

如图:

这里写图片描述
这里写图片描述

setUnderlineText(boolean underlineText) —设置下划线

代码语言:javascript
复制
paint.setUnderlineText(true);
这里写图片描述
这里写图片描述

setMaskFilter(MaskFilter maskfilter)—滤镜的效果

设置MaskFilter,可以用不同的MaskFilter实现滤镜的效果,如滤化,立体等

Android包含了下面几种MaskFilter: BlurMaskFilter 指定了一个模糊的样式和半径来处理Paint的边缘。 EmbossMaskFilter 指定了光源的方向和环境光强度来添加浮雕效果。

代码语言:javascript
复制
        BlurMaskFilter maskFilter = new BlurMaskFilter(10, BlurMaskFilter.Blur.SOLID);

        paint.setMaskFilter(maskFilter);

这里写图片描述
这里写图片描述

Path类使用详解

Path类可以预先在View上将N个点连成一条”路径”,然后调用Canvas的drawPath(path,paint)即可沿着路径绘制图形。

下面是常用方法:

方法

作用

备注

moveTo

移动起点

移动下一次操作的起点位置

lineTo

连接直线

连接上一个点到当前点之间的直线

setLastPoint

设置终点

重置最后一个点的位置

close

闭合路劲

从最后一个点连接最初的一个点,形成一个闭合区域

addRect

添加矩形

添加矩形到当前Path

addRoundRect

添加圆角矩形

添加圆角矩形到当前Path

addOval

添加椭圆

添加椭圆到当前Path

addCircle

添加圆

添加圆到当前Path

addPah

添加路劲

添加路劲到当前Path

addArc

添加圆弧

添加圆弧到当前Path

arcTo

圆弧

绘制圆弧,注意和addArc的区别

isEmpty

是否为空

判定Path是否为空

isRect

是否为矩形

判定Path是否是一个矩形

set

替换路劲

用新的路劲替换当前路劲的所有内容

offset

偏移路劲

对当前的路劲进行偏移

quadTo

贝塞尔曲线

二次贝塞尔曲线的方法

cubicTo

贝塞尔曲线

三次贝塞尔曲线的方法

rMoveTo,rlineTo,rQuadTo,rCubicTo

rXxx方法

不带r的方法是基于原点坐标系(偏移量),带r的基于当前点坐标系(偏移量)

op

布尔操作

对两个Path进行布尔运算(交集,并集)等操作

setFillType

填充模式

设置Path的填充模式

getFillType

填充模式

获取Path的填充

isInverseFillType

是否逆填充

判断是否是逆填充模式

toggleInverseFillType

相反模式

切换相反的填充模式

getFillType

填充模式

获取Path的填充

incReserve

提示方法

提示Path还有多少个点等待加入

computeBounds

计算边界

计算Path的路劲

reset,rewind

重置路劲

清除Path中的内容(reset相当于new Path , rewind 会保留Path的数据结构)

transform

矩阵操作

矩阵变换

由于属性过多,我们分组进行讲解: 先创建画笔:

代码语言:javascript
复制
public DemoView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        paint.setAntiAlias(true);
        paint.setColor(Color.parseColor("#ff0000"));
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(10);
}

第一组:画线段(绝对坐标) XXXTo方法

moveTo , lineTo , setLastPoint , close 我们来看上面绘制的三角形

代码语言:javascript
复制
        path.moveTo(150, 400); //起点 (150,400)
        path.lineTo(450, 400); //移动到(450,400)
        path.lineTo(300, 150); //移动到(300,150)
        path.close(); //回到起点
这里写图片描述
这里写图片描述

我们把path.close() 去掉, 看一下效果

这里写图片描述
这里写图片描述

第二组:画线段(相对坐标) rXXXTo方法

rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3) rLineTo(float dx, float dy) rMoveTo(float dx, float dy) rQuadTo(float dx1, float dy1, float dx2, float dy2)

我们看一下代码就知道什么情况了:

代码语言:javascript
复制
    path.moveTo(100, 100);
    path.LineTo(200, 200);

这里的move和lineTo的坐标都是对于画布左上角(0,0)来说的,是一个绝对坐标。

这里写图片描述
这里写图片描述
代码语言:javascript
复制
    path.moveTo(100, 100);
    path.rLineTo(200, 200);

这里的(200,200)是相对于开始点(100,100)来说的,是相对坐标。

这里写图片描述
这里写图片描述

第三组:画贝赛尔曲线

quadTo,cubicTo 二次贝塞尔曲线以及三次贝塞尔曲线

1.quadTo
代码语言:javascript
复制
//quadTo方法其中 (x1,y1) 为控制点,(x2,y2)为结束点。
public void quadTo(float x1, float y1, float x2, float y2) 
这里写图片描述
这里写图片描述

解释:其中quadTo的前两个参数为控制点的坐标,后两个参数为终点坐标,至于起点默认是画布的左上角。这里的p0就是起点,(x1,y1)就是中点P1,(x2,y2)就是末端点P2。

代码语言:javascript
复制
        path = new Path();
        path.moveTo(150, 400);
        path.quadTo(200, 200, 400, 400);

效果如图:

这里写图片描述
这里写图片描述
2、cubicTo
代码语言:javascript
复制
//cubicTo方法比quadTo方法多了一个点坐标,那么其中(x1,y1) 为控制点,(x2,y2)为控制点,(x3,y3) 为结束点。
public void cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
这里写图片描述
这里写图片描述

解释:与quadTo类似,前四个参数表示两个控制点,最后两个参数表示终点。其实,(x1,y1)就是P1,(x2,y2)是P2,(x3,y3)是P3。

代码语言:javascript
复制
path.moveTo(100, 400);
        path.cubicTo(200, 200, 300, 200, 400, 400);

效果如图:

这里写图片描述
这里写图片描述

第四组:画弧线

arcTo (RectF oval, float startAngle, float sweepAngle) 上面这个方法就是画圆弧,说白了就是先确定一个矩形区域,这个区域就是圆或者椭圆的区域,然后在上面截取一段。

代码语言:javascript
复制
    path.moveTo(100, 100);
    RectF oval = new RectF(100, 100, 200, 200);
    path.arcTo(oval, 0, 90);
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

这里你会发现有一条从起点到圆弧的直线,那么使用下面的方法可以重置起点。

arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)

代码语言:javascript
复制
    path.moveTo(100, 100);
    RectF oval = new RectF(100, 100, 200, 200);
    path.arcTo(oval, 0, 90,true);
这里写图片描述
这里写图片描述

第五组:添加path(addXXX方法)

addXXX方法则可以让我们直接往Path中添加一些曲线。 比如:

addArc(RectF oval, float startAngle, float sweepAngle) addCircle(float x, float y, float radius, Path.Direction dir) addOval(float left, float top, float right, float bottom, Path.Direction dir) addRect(float left, float top, float right, float bottom, Path.Direction dir) addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Path.Direction dir)

我们注意到addArc和其他四个方法的区别在于Path.Direction这个参数,因为addArc添加的是一个开放曲线,而其他的方法添加的是闭合曲线,所以Path.Direction就是闭合曲线的方向。

让我们看一下示例:

代码语言:javascript
复制
    path.moveTo(100, 100);
    path.rLineTo(200, 200);
    RectF oval = new RectF(100, 100, 200, 200);
    path.addArc(oval, 0, 90);

这是我们上面讲的两个图形 add到了一起。

这里写图片描述
这里写图片描述

是不是豁然开朗,那再让我们看一下其他的需要使用Path.Direction这个的效果。

代码语言:javascript
复制
    path = new Path();
    path.moveTo(100, 100);
    path.rLineTo(200, 200);
    RectF oval = new RectF(100, 100, 300, 300);
    path.addRect(oval, Path.Direction.CW);
这里写图片描述
这里写图片描述

那么上面的例子可能看不出来CW和CCW的太大区别,下面的例子就可以直观的看出来了。

代码语言:javascript
复制
     path = new Path();
     RectF oval = new RectF(100, 100, 300, 300);
     path.addRect(oval, Path.Direction.CW);
     canvas.drawPath(path,paint);
     paint.setTextSize(60);
     canvas.drawTextOnPath("12345",path,0,0,paint);

Path.Direction只有两个常量值CCW和CW分别表示逆时针方向闭合和顺时针方向闭合。 CW

这里写图片描述
这里写图片描述

CCW

这里写图片描述
这里写图片描述

第六组:path的集合运算(op方法)

先看下代码

代码语言:javascript
复制
    Path path1 = new Path();
    path1.addCircle(120, 120, 100, Path.Direction.CW);
    Path path2 = new Path();
    path2.addCircle(200, 200, 100, Path.Direction.CW);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        path1.op(path2, Path.Op.UNION); //这边使用不同属性效果如下表
    }
    canvas.drawPath(path1, paint);

逻辑名称

类比

说明

示意图

DIFFERENCE

差集

Path1中减去Path2后剩下的部分

REVERSE_DIFFERENCE

差集

Path2中减去Path1后剩下的部分

INTERSECT

交集

Path1与Path2相交的部分

UNION

并集

包含全部Path1和Path2

XOR

异或

包含Path1与Path2但不包括两者相交的部分

第七组:填充效果(setFillType方法)

参数

解释

效果

WINDING

非零环绕数规则填充

INVERSE_WINDING

和WINDING相反

EVEN_ODD

奇偶规则填充

INVERSE_EVEN_ODD

和EVEN_ODD相反


PathEffect类使用详解

PathEffect是用来控制绘制轮廓(线条)的方式。

常用PathEffect如下:

方法

作用

CornerPathEffect

可以使用圆角来代替尖锐的角从而对基本图形的形状尖锐的边角进行平滑。

DashPathEffect

可以使用DashPathEffect来创建一个虚线的轮廓(短横线/小圆点),而不是使用实线。你还可以指定任意的虚/实线段的重复模式。

DiscretePathEffect

与DashPathEffect相似,但是添加了随机性。当绘制它的时候,需要指定每一段的长度和与原始路径的偏离度。

PathDashPathEffect

这种效果可以定义一个新的形状(路径)并将其用作原始路径的轮廓标记。

SumPathEffect

顺序地在一条路径中添加两种效果,这样每一种效果都可以应用到原始路径中,而且两种结果可以结合起来。

ComposePathEffect

组合效果,这个类需要两个PathEffect参数来构造一个实例,ComposePathEffect (PathEffect outerpe,PathEffect innerpe),表现时,会首先将innerpe表现出来,然后再在innerpe的基础上去增加outerpe的效果。。

看一个demo就知道这几个效果的区别了。

代码语言:javascript
复制
paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(4);
        //创建,并初始化Path
        path = new Path();
        path.moveTo(100, 100);
        path.rLineTo(90,0);
        path.rLineTo(-80,50);
        path.rLineTo(35,-80);
        path.rLineTo(45,80);
        path.close();

        //初始化七个颜色
        colors = new int[] {
                Color.BLACK,Color.BLUE,Color.CYAN,
                Color.GREEN,Color.MAGENTA,Color.RED,Color.YELLOW,Color.BLACK
        };

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

        //将背景填充成白色
        canvas.drawColor(Color.WHITE);
        //-------下面开始初始化7中路径的效果
        //使用路径效果
        effects[0] = null;
        //使用CornerPathEffect路径效果
        effects[1] = new CornerPathEffect(10);
        //初始化DiscretePathEffect
        effects[2] = new DiscretePathEffect(3.0f,5.0f);
        //初始化DashPathEffect
        effects[3] = new DashPathEffect(new float[]{20,10,5,10},phase);
        //初始化PathDashPathEffect
        Path p = new Path();
        p.addRect(0, 0, 8, 8, Path.Direction.CCW);
        effects[4] = new PathDashPathEffect(p,12,phase,PathDashPathEffect.Style.ROTATE);
        //初始化PathDashPathEffect
        effects[5] = new ComposePathEffect(effects[2],effects[4]);
        effects[6] = new SumPathEffect(effects[4],effects[3]);
        //将画布移到8,8处开始绘制
        canvas.translate(8, 8);
        //依次使用7中不同路径效果,7种不同的颜色来绘制路径
        for(int i = 0; i < effects.length; i++)
        {
            paint.setPathEffect(effects[i]);
            paint.setColor(colors[i]);
            canvas.drawPath(path, paint);
            canvas.translate(0, 60);
        }
        //改变phase值,形成动画效果
        phase += 1;
        invalidate();
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年03月24日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Paint类使用详解
    • setAlpha(int a) —透明度
      • setAntiAlias(boolean aa) —是否抗锯齿
        • setStyle(Style style)—设置画笔风格
          • setStrokeWidth—空心画笔宽度
            • setStrokeCap(CAP cap)—线段末端效果
              • setStrokeJoin(Join join)—闭合图形的连接处效果
                • setTextAlign(Paint.Align align)—设置文本对齐
                  • setTextSize(float testSize)—设置字体的大小
                    • setShader(Shader shader)—设置阴影
                      • setTextScaleX(float scaleX)—设置缩放倍数
                        • 设置字体类型
                          • setUnderlineText(boolean underlineText) —设置下划线
                            • setMaskFilter(MaskFilter maskfilter)—滤镜的效果
                            • Path类使用详解
                              • 第一组:画线段(绝对坐标) XXXTo方法
                                • 第二组:画线段(相对坐标) rXXXTo方法
                                  • 第三组:画贝赛尔曲线
                                    • 第四组:画弧线
                                      • 第五组:添加path(addXXX方法)
                                        • 第六组:path的集合运算(op方法)
                                          • 第七组:填充效果(setFillType方法)
                                          • PathEffect类使用详解
                                          领券
                                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档