绘制在View.draw()方法里调用的,具体的执行顺序是:
drawBackground():绘制背景,不能重写。
onDraw():绘制主体。
dispatchDraw():绘制子View
onDrawForeground():绘制滑动边缘渐变、滚动条和前景。


1 绘制分析

我们如果继承View来实现自定义View。View类的onDraw()是空实现,所以我们的绘制代码写在super.onDraw(canvas)的前面或者后面都没有关系,如下所示:

public class DrawView extends View {@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//绘制代码,写在super.onDraw(canvas)前后均可}
}

但是如果我们继承特定的控件,例如TextView。我们就需要去考虑TextView的绘制逻辑。

public class DrawView extends TextView {@Overrideprotected void onDraw(Canvas canvas) {//写在前面,DrawView的绘制会先于TextView的绘制,TextView绘制的内容可以会覆盖DrawViewsuper.onDraw(canvas);//写在后面,DrawView的绘制会晚于TextView的绘制,DrawView绘制的内容可以会覆盖TextView}
}

2 Paint:顾名思义,画笔,通过Paint可以对绘制行为进行控制。

2.1 颜色处理类

在Paint类中,处理颜色主要有三个方法。

  • setShader(Shader shader):用来处理颜色渐变
  • setColorFilter(ColorFilter filter):用来基于颜色进行过滤处理;
  • setXfermode(Xfermode xfermode) 用来处理源图像和 View 已有内容的关系
2.1.1 setShader(Shader shader)

着色器是图像领域的一个通用概念,它提供的是一套着色规则。着色器具体由Shader的子类实现。

2.1.1.1 线性渐变 LinearGradient
public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, TileMode tile)

参数解析:x0 y0 x1 y1:渐变的两个端点的位置,color0 color1 是端点的颜色
tile:端点范围之外的着色规则,类型是 TileMode(定义平铺模式)。TileMode 一共有 3 个值可选: CLAMP(复制边缘色彩), MIRROR (在水平和垂直方向上使用交替镜像的方式重复图片的绘制)和 REPEAT(图像平铺)。


//线性渐变 案例Shader shader1 = new LinearGradient(0, 150, 200, 150, Color.RED, Color.BLUE, Shader.TileMode.CLAMP);mPaint.setShader(shader1);Shader shader2 = new LinearGradient(0, 350, 200, 350, Color.RED, Color.BLUE, Shader.TileMode.MIRROR);mPaint2.setShader(shader2);Shader shader3 = new LinearGradient(0, 750, 200, 750, Color.RED, Color.BLUE, Shader.TileMode.REPEAT);mPaint3.setShader(shader3);canvas.drawRect(0, 100, 1000, 200, mPaint);canvas.drawRect(0, 300, 1000, 600, mPaint2);canvas.drawRect(0, 700, 1000, 1000, mPaint3);

2.1.1.2 SweepGradient - 辐射渐变
public RadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, @NonNull TileMode tileMode)

参数解析:

参数名 参数值
centerX centerY 辐射中心的坐标
radius 辐射半径
centerColor 辐射中心的颜色
edgeColor 辐射边缘的颜色
tileMode 辐射范围之外的着色模式
        //辐射渐变//(0,100)为辐射中心点坐标,参数200为辐射半径Shader shader1 = new RadialGradient(0, 100, 200, Color.RED, Color.BLUE, Shader.TileMode.CLAMP);mPaint.setShader(shader1);Shader shader2 = new RadialGradient(0, 300, 200, Color.RED, Color.BLUE, Shader.TileMode.MIRROR);mPaint2.setShader(shader2);Shader shader3 = new RadialGradient(0, 700, 200, Color.RED, Color.BLUE, Shader.TileMode.REPEAT);mPaint3.setShader(shader3);canvas.drawRect(0, 100, 1000, 200, mPaint);canvas.drawRect(0, 300, 1000, 600, mPaint2);canvas.drawRect(0, 700, 1000, 1000, mPaint3);

2.1.1.3 BitmapShader - 位图着色
public BitmapShader(@NonNull Bitmap bitmap, TileMode tileX, TileMode tileY)
参数名 参数值
bitmap 用来做模板的 Bitmap 对象
tileX 横向的 TileMode
tileY 纵向的 TileMode。
2.1.1.4 ComposeShader - 组合Shader

ComposeShader可以将连个Shader组合在一起

public ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode)
参数名 参数值
shaderA, shaderB 两个相继使用的 Shader
mode 两个 Shader 的叠加模式,即 shaderA 和 shaderB 应该怎样共同绘制。它的类型是PorterDuff.Mode。

PorterDuff.Mode用来指定两个Shader叠加时颜色的绘制策略,它有很多种策略,也就是以一种怎样的模式来与原图像进行合成,具体如下

2.1.2 setColorFilter(ColorFilter filter)

颜色过滤器可以将颜色按照一定的规则输出,常见于各种滤镜效果。

2.1.2.1 LightingColorFilter - 模拟光照效果
public LightingColorFilter(int mul, int add)

mul 和 add 都是和颜色值格式相同的 int 值,其中 mul 用来和目标像素相乘,add 用来和目标像素相加

//颜色过滤器
ColorFilter colorFilter1 = new LightingColorFilter(Color.RED, Color.BLUE);
paint2.setColorFilter(colorFilter1);
2.1.2.2 PorterDuffColorFilter - 模拟颜色混合效果
public PorterDuffColorFilter(@ColorInt int color, @NonNull PorterDuff.Mode mode)

PorterDuffColorFilter指定一种颜色和PorterDuff.Mode来与源图像就行合成,也就是以一种怎样的模式来与原图像进行合成

//我们在使用Xfermode的时候也是使用它的子类PorterDuffXfermode
Xfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
canvas.drawBitmap(rectBitmap, 0, 0, paint); // 画方
paint.setXfermode(xfermode); // 设置 Xfermode
canvas.drawBitmap(circleBitmap, 0, 0, paint); // 画圆
paint.setXfermode(null); // 用完及时清除 Xfermode
2.1.2.3 ColorMatrixColorFilter - 颜色矩阵过滤

ColorMatrixColorFilter使用一个颜色矩阵ColorMatrix来对象图像进行处理。

public ColorMatrixColorFilter(ColorMatrix matrix)

ColorMatrix是一个4x5的矩阵

[ a, b, c, d, e,f, g, h, i, j,k, l, m, n, o,p, q, r, s, t ]

通过计算,ColorMatrix可以对要绘制的像素进行转换,如下:

R’ = a*R + b*G + c*B + d*A + e;
G’ = f*R + g*G + h*B + i*A + j;
B’ = k*R + l*G + m*B + n*A + o;
A’ = p*R + q*G + r*B + s*A + t;

2.2 文字处理类

Paint里有大量方法来设置文字的绘制属性,事实上文字在Android底层是被当做图片来处理的。

方法 解说
setTextSize(float textSize) 设置文字大小
setTypeface(Typeface typeface) 设置文字字体
setFakeBoldText(boolean fakeBoldText) 是否使用伪粗体(并不是提到size,而是在运行时描粗的)
setStrikeThruText(boolean strikeThruText) 是否添加删除线
setUnderlineText(boolean underlineText) 是否添加下划线
setTextSkewX(float skewX) 设置文字倾斜度
setTextScaleX(float scaleX) 设置文字横向缩放
setLetterSpacing(float letterSpacing) 设置文字间距
setFontFeatureSettings(String settings) 使用CSS的font-feature-settings的方式来设置文字。
setTextAlign(Paint.Align align) 设置文字对齐方式
setTextLocale(Locale locale) 设置文字Local
setHinting(int mode) 设置字体Hinting(微调),过向字体中加入 hinting 信息,让矢量字体在尺寸过小的时候得到针对性的修正,从而提高显示效果。
setSubpixelText(boolean subpixelText) 设置次像素级抗锯齿,根据程序所运行的设备的屏幕类型,来进行针对性的次像素级的抗锯齿计算,从而达到更好的抗锯齿效果。
2.3 特殊效果类
2.3.1 setAntiAlias (boolean aa)设置抗锯齿

默认关闭,用来是图像的绘制更加圆润。我们还可以在初始化的时候设置Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);。

2.3.2 setStyle(Paint.Style style) 设置填充风格
设置值 解析
FILL 模式 填充
STROKE 模式 画线
FILL_AND_STROKE 模式 填充 + 画线

如果是划线模式,我们针对线条还可以有多种设置

  • setStrokeWidth(float width) - 设置线条粗细

  • setStrokeCap(Paint.Cap cap) - 设置线头的形状,默认为 BUTT

    • UTT 平头
    • ROUND 圆头
    • SQUARE 方头
  • setStrokeJoin(Paint.Join join) - 设置拐角的形状。默认为 MITER

    • MITER 尖角
    • BEVEL 平角
    • ROUND 圆角
  • setStrokeMiter(float miter)- 设置 MITER 型拐角的延长线的最大值

2.3.3 setDither(boolean dither) 设置图像的抖动。
2.3.3 setFilterBitmap(boolean filter)设置是否使用双线性过滤来绘制 Bitmap

图像在放大绘制的时候,默认使用的是最近邻插值过滤,这种算法简单,但会出现马赛克现象;而如果开启了双线性过滤,就可以让结果图像显得更加平滑。
etPathEffect(PathEffect effect)

2.3.4 设置图形的轮廓效果。Android有六种PathEffect:
属性值 解说
CornerPathEffect 将拐角绘制成圆角
DiscretePathEffect 将线条进行随机偏离
DashPathEffect 绘制虚线
PathDashPathEffect 使用指定的Path来绘制虚线
SumPathEffect 组合两个PathEffect,叠加应用。
ComposePathEffect 组合两个PathEffect,叠加应用。
//图形轮廓效果
//绘制圆角 参数 20 为圆角半径
PathEffect cornerPathEffect = new CornerPathEffect(20);
paint1.setStyle(Paint.Style.STROKE);
paint1.setStrokeWidth(5);
paint1.setPathEffect(cornerPathEffect);//绘制尖角 float segmentLength:用来拼接每个线段的长度,float deviation:偏离量
PathEffect discretePathEffect = new DiscretePathEffect(20, 5);
paint2.setStyle(Paint.Style.STROKE);
paint2.setStrokeWidth(5);
paint2.setPathEffect(discretePathEffect);//绘制虚线
//float[] intervals:指定了虚线的格式,数组中元素必须为偶数(最少是 2 个),按照「画线长度、空白长度、画线长度、空白长度」……的顺序排列
float phase:虚线的偏移量
PathEffect dashPathEffect = new DashPathEffect(new float[]{20,10, 5, 10}, 0);
paint3.setStyle(Paint.Style.STROKE);
paint3.setStrokeWidth(5);
paint3.setPathEffect(dashPathEffect);//使用path来绘制虚线
Path path = new Path();//画一个三角来填充虚线
path.lineTo(40, 40);
path.lineTo(0, 40);
path.close();
PathEffect pathDashPathEffect = new PathDashPathEffect(path, 40, 0, PathDashPathEffect.Style.TRANSLATE);
paint4.setStyle(Paint.Style.STROKE);
paint4.setStrokeWidth(5);
paint4.setPathEffect(pathDashPathEffect);
2.3.5 setShadowLayer(float radius, float dx, float dy, int shadowColor)设置阴影图层

处于目标下层图层
参数说明

参数名 说明
float radius 阴影半径
float dx 阴影偏移量
float dy 阴影偏移量
int shadowColor 阴影颜色
2.3.6 setMaskFilter(MaskFilter maskfilter)

设置图层遮罩层,处于目标上层图层。

Android Paint 画笔使用详解 Android自定义View(六)相关推荐

  1. android常用技术网站收藏过的网址 给 Android 开发者的 RxJava 详解 Android设备标识-没有完美的解决方案-只有取舍 - 小彼得的专栏 - 博客频道 - CSDN.NET

    收藏过的网址 http://www.jianshu.com/p/a7b36d682b6f?ref=myread  Android插件化快速入门与实例解析 http://www.cnblogs.com/ ...

  2. android uri图片压缩,详解android 通过uri获取bitmap图片并压缩

    详解android 通过uri获取bitmap图片并压缩 很多人在调用图库选择图片时会在onactivityresult中用media.getbitmap来获取返回的图片,如下: uri mimage ...

  3. android:stretchcolumns=quot;*quot;,详解Android TableLayout中stretchColumns、shrinkColumns的用法...

    详解Android 中TableLayout中stretchColumns.shrinkColumns的用法 android:stretchColumns="1" android: ...

  4. android led闪烁功能,详解Android应用层制作LED指示灯

    详解Android应用层制作LED指示灯 在Java应用层修改LED指示灯的颜色,这个花了我半天时间, 才实现该功能! public class LEDActivity extends Activit ...

  5. Android Paint set方法详解

    一.前言 我们用set方法来设置画笔的样式,类似于我们挑选画笔画画的过程.由于上面有些方法不支持硬件加速,所以在高版本系统中可能会没有效果.因此,我们首先来看看官方废弃的方法. 下图来自: https ...

  6. android任务 进程 线程详解,Android任务、进程、线程详解

    singleTop模式,基本上于standard分歧,仅正在请求的Activity反好位于栈顶时,无所区别.此时,配放成singleTop的Activity,不再会构制新的实例加入到Task栈外,而是 ...

  7. Android编程之SparseArrayE详解 Android编程之SparseArrayE详解

    Android编程之SparseArray<E>详解 分类:Android2012-09-01 13:139412人阅读评论(5)收藏举报 android编程delete存储list 最近 ...

  8. android布局优化 工具,详解Android布局优化

    怎样才能写出优秀的Android App,是每一个程序员追求的目标.那么怎么才能写出一个优秀的App呢?相信很多初学者也会有这种迷茫.一句话来回答这个问题:细节很重要.今天我们就从最基础的XML布局来 ...

  9. android事件处理主要方法,详解Android的两种事件处理机制

    UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于监听器的事件处理. 对于基于监听器的事件处理而言,主要就是为Android界面组件绑定特定的事 ...

最新文章

  1. 敏捷个人手机应用:如何使用时中法目标
  2. Oozie和Azkaban的技术选型和对比
  3. 【杂谈】一个五岁孩子妈妈在有三AI学习并且赚钱的故事
  4. Codeforces Round #613 (Div. 2) E. Delete a Segment 离散化
  5. 很全的路由器默认初始密码集合.txt_UpSet——集合关系可视化神器
  6. 谈一谈Java编程开发中虚拟机的内存区域划分?猿们怎么看?
  7. python画布位置_如何调整tkinter画布的位置
  8. 最大流算法(Edmons-Karp + Dinic 比较) + Ford-Fulkson 简要证明
  9. 路遥《平凡的世界》读后感
  10. 微信小程序金额千分位
  11. SpringBoot整合MybatisPlus实现逻辑删除
  12. MATLAB与信号处理课程手册
  13. 【搜索/提问必备】如何正确的在Stack Overflow提问
  14. 全球与中国家用手动和电动工具的产能、产量、销量、销售额、价格及未来趋势
  15. 闲鱼商品选投实时性优化
  16. artdialog ajax新增,artDialog 对话框组件使用简介
  17. 数字图像处理--冈萨雷斯第4版--第一章 绪论
  18. 基于threejs的商品VR展示平台的设计与实现思路
  19. 【JS】Proxy(代理)
  20. 2021年企业服务行业BP和融资计划书PPT模板

热门文章

  1. 超越 EfficientNet!小米AutoML 团队开源 Scarlet 模型!
  2. 是时候学习生成对抗网络了,李宏毅老师GAN视频教程下载
  3. mysql 实现非递归树_二叉树的非递归前序,中序,后序遍历算法
  4. Python编辑统一缩进(Pycharm)
  5. enum java 比较_Kotlin与Java比较:枚举类
  6. CNN卷积神经网络分析
  7. 算法移植优化(六)tensorflow模型移植推理优化
  8. Ubuntu16.04+Cuda8.0+cuDNN6配置py-faster rcnn(转)
  9. linux的可执行文件通常放在哪个目录中?写出该目录的路径.,实验2 Linux的基本操作与 使用vi编辑器 2010 (1)...
  10. 我有一个域名_一个域名可以绑定几个网站?域名解析多少子域名?