[Android 知识点] 自定义View(二)

来源:互联网 发布:激光祛痘的危害 知乎 编辑:程序博客网 时间:2024/06/03 12:40

Paint类介绍

Paint类API

  • 下面就一起来学习这些用法:

setARGB(int a,int r,int g,int b);设置画笔颜色

mPaint.setARGB( 255, 35, 31, 42 ); 

ARGB的颜色选择可以使用这网站

setAntiAlias(boolean aa); 会平滑一些

mPaint.setAntiAlias( true ); 

设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢。

setDither(boolean dither); 颜色更精细

mPaint.setDither( true ); 

setMaskFilter(MaskFilter maskfilter); 实现滤镜的效果

Android包含了下面几种MaskFilter:

  • BlurMaskFilter 指定了一个模糊的样式和半径来处理Paint的边缘。
  • EmbossMaskFilter 指定了光源的方向和环境光强度来添加浮雕效果。

  • [x] 需要注意的是,由于在GPU硬件加速模式下,Paint的setMaskFilter不被GPU支持,所以为了能够正常使用setMaskFilter方法,我们需要将我们要绘制的View使用软件渲染模式

//为了确保画笔的setMaskFilter能供起效,我们需要对MyView禁用掉GPU硬件加速  if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){      //View从API Level 11才加入setLayerType方法      //设置myView以软件渲染模式绘图      setLayerType(View.LAYER_TYPE_SOFTWARE, null);  }  

BlurMaskFilter 模糊效果

new BlurMaskFilter(float radius, Blur style) 
  • radius: 阴影的模糊半径,如上图所示,其值越大表示图形绘制出来越模糊,其值越小图形越清晰。

  • Blur style:

类型 h效果 NORMAL 同时绘制图形本身内容+内阴影+外阴影,即正常阴影效果 SOLID 只绘制外阴影和图形内容本身,不绘制内阴影。 OUTER 不绘制图形内容以及内阴影,只绘制外阴影,即图形轮廓以内完全不绘制,轮廓线以内完全是空白的。 INNER 绘制图形内容本身+内阴影,不绘制外阴影。

效果展示

EmbossMaskFilter 浮雕效果

new EmbossMaskFilter (float[] direction, float ambient, float specular, float blurRadius) 
  • direction

是一个float类型的数组,表示光线的方向,是个向量,包含三个值,分别是x分量、y分量、z分量,这三个值的绝对大小并不重要,因为direction最后在真正被Android使用时会被归一化成一个单位向量,即变成长度为1的向量。direction中的坐标是在所画图形的右手坐标系中定义的,如下图所示:
image

  • ambient

    表示环境光因子,float类型,取值是0到1,值越接近于0,环境光越暗,值越接近于1,环境光越亮。

  • specular

    表示镜面反射因子,float类型,取值也是0到1。镜面反射就是模拟像镜子一样的高光反射,值越接近于0,镜面反射越强,被光照照射到的地方更容易出现很白很亮的状态,即高光效果。

  • blurRadius

    表示模糊半径,是float类型,其值越大,模糊效果越明显。

image

setColorFilter(ColorFilter filter) 设置颜色过滤器

可以直接传入

  • ColorMatrixColorFilter
  • LightingColorFilter
  • PorterDuffColorFilter

的对象作为参数

ColorMatrixColorFilter 色彩矩阵颜色过滤器

在Android中图片是以RGBA像素点的形式加载到内存中的,修改这些像素信息需要一个叫做ColorMatrix类的支持,这个类其实定义的是一个矩阵,是一个4x5的float[]类型的矩阵

ColorMatrix colorMatrix = new ColorMatrix(new float[]{                  1, 0, 0, 0, 0,  // 红色向量                0, 1, 0, 0, 0,  // 绿色向量                0, 0, 1, 0, 0,  // 蓝色向量                0, 0, 0, 1, 0,  // 透明度向量        }); 

其中,第一行表示的R(红色)的向量,第二行表示的G(绿色)的向量,第三行表示的B(蓝色)的向量,最后一行表示A(透明度)的向量

image

这个矩阵不同的位置表示的R、G、B、A值,其范围在0.0F至2.0F之间,1为保持原图的RGB值。每一行的第五列数字表示”偏移值“。

  • ”偏移值“:比如:(255, 253, 251, 247)和纯白(255, 255, 255, 255)之间的偏移值(0, 2, 4, 8)我们称之为白平衡的色彩偏移

我们来看看这个矩阵是怎么计算的。其实说白了就是矩阵之间的运算乘积:

image

这里MyColor的RGBA值我们需要转换为[0,1]。通过这种计算我们可以将我们自己设定的颜色和矩阵的颜色进行叠加,创立一个新的颜色

// 生成色彩矩阵  ColorMatrix colorMatrix = new ColorMatrix(new float[]{          -1, 0, 0, 1, 1,          0, -1, 0, 1, 1,          0, 0, -1, 1, 1,          0, 0, 0, 1, 0,  }); mPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix)); Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.kale);canvas.drawBitmap(bitmap,240,600,mPaint);

原图

image

效果图

image

LightingColorFilter (int mul, int add) 亮度过滤

mul全称是colorMultiply意为色彩倍增,而add全称是colorAdd意为色彩添加,这两个值都是16进制的色彩值0xAARRGGBB、

    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        // 设置颜色过滤          mPaint.setColorFilter(new LightingColorFilter(0xFFFF00FF, 0x00000000));          Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.kale);        canvas.drawBitmap(bitmap,240,600,mPaint);    }

运行后你会发现绿色确实是没了但是原来偏绿的部分现在居然成了红色,当LightingColorFilter(0xFFFFFFFF,0x00000000)的时候原图是不会有任何改变的,如果我们想增加红色的值,那么LightingColorFilter(0xFFFFFFFF, 0x00XX0000)就好,其中XX取值为00至FF。

效果图

image

PorterDuffColorFilter(int color, PorterDuff.Mode mode)

这个构造方法也接受两个值,一个是16进制表示的颜色值这个很好理解,而另一个是PorterDuff内部类Mode中的一个常量值,这个值表示混合模式。那么什么是混合模式呢?混合混合必定是有两种东西混才行,第一种就是我们设置的color值而第二种当然就是我们画布上的元素了!也就是说将画布上的元素和我们设置的color进行混合,产生最终的效果。

  • PorterDuff.Mode mode

PorterDuff.Mode为枚举类,一共有16个枚举值:

模式 效果 PorterDuff.Mode.CLEAR 所绘制不会提交到画布上。 PorterDuff.Mode.SRC 显示上层绘制图片 PorterDuff.Mode.DST 显示下层绘制图片 PorterDuff.Mode.SRC_OVER 正常绘制显示,上下层绘制叠盖。 PorterDuff.Mode.DST_OVER 上下层都显示。下层居上显示。 PorterDuff.Mode.SRC_IN 取两层绘制交集。显示上层。 PorterDuff.Mode.DST_IN 取两层绘制交集。显示下层。 PorterDuff.Mode.SRC_OUT 上层绘制非交集部分。 PorterDuff.Mode.DST_OUT 下层绘制非交集部分。 PorterDuff.Mode.SRC_ATOP 下层非交集部分与上层交集部分 PorterDuff.Mode.DST_ATOP 上层非交集部分与下层交集部分 PorterDuff.Mode.XOR 异或:去除两图层交集部分 PorterDuff.Mode.DARKEN 取两图层全部区域,交集部分颜色加深 PorterDuff.Mode.LIGHTEN 取两图层全部,点亮交集部分颜色 PorterDuff.Mode.MULTIPLY 取两图层交集部分叠加后颜色 PorterDuff.Mode.SCREEN 取两图层全部区域,交集部分变为透明色

image

@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    // 设置颜色过滤      mPaint.setColorFilter(new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.DARKEN));      Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.kale);    canvas.drawBitmap(bitmap,240,600,mPaint);}

效果图

image

setPathEffect(PathEffect effect); 设置绘制路径的效果

效果是由它的六个子类实现:
- ComposePathEffect
- CornerPathEffect
- DashPathEffec
- DiscretePathEffect
- PathDashPathEffect
- SumPathEffect

例如

mPaint.setPathEffect(new CornerPathEffect(10));

CornerPathEffect(float radius)

将路径的转角变得圆滑
image
image

DiscretePathEffect(float segmentLength, float deviation)

绘制很多“杂点”的突出来模拟一种类似生锈铁丝的效果

new DiscretePathEffect(3.0F, 5.0F)
  • 第一个参指定这些突出的“杂点”的密度,值越小杂点越密集;

  • 第二个参数是“杂点”突出的大小,值越大突出的距离越大反之反之。

image

DashPathEffect(float[] intervals, float phase)

  • 第一个参数是一个浮点型的数组,只要浮点型数组中元素个数大于等于2即可。{20, 10}的偶数参数20(注意数组下标是从0开始哦)定义了我们第一条实线的长度,而奇数参数10则表示第一条虚线的长度,如果此时数组后面不再有数据则重复第一个数以此往复循环,整条线就成了[20,10,20,10,20,10…………………………]这么一个状态。

image

  • 第二个参数(phase)我称之为偏移值,即是奇数偶数的间隔数,可以理解为取模。

image

PathDashPathEffect(Path shape, float advance, float phase, PathDashPathEffect.Style style)

和DashPathEffect是类似的,但我们自己定义图形和路径虚线的样式。

  • shape : 是指填充图形
  • advance : 每个图形间的间距
  • phase : 绘制时的偏移量
  • style : Style.ROTATE、Style.MORPH和Style.TRANSLATE
类型 效果 Style.ROTATE 线段连接处的图形转换以旋转到与下一段移动方向相一致的角度进行转转 Style.MORPH 图形会以发生拉伸或压缩等变形的情况与下一段相连接 Style.TRANSLATE 图形会以位置平移的方式与下一段相连接。
Path path = new Path();  path.addCircle(0, 0, 3, Direction.CCW);  PathEffect pathEffect = new PathDashPathEffect(path, 12, phase, PathDashPathEffect.Style.ROTATE);  

效果图:

image

ComposePathEffect(PathEffect outerpe, PathEffect innerpe)

SumPathEffect(PathEffect first, PathEffect second)

ComposePathEffect和SumPathEffect都可以用来组合两种路径效果,就是把两种效果二合一。唯一不同的是组合的方式:
- ComposePathEffect会先将路径变成innerpe的效果,再去复合outerpe的路径效果,即:outerpe(innerpe(Path));
- SumPathEffect(PathEffect first, PathEffect second)则会把两种路径效果加起来再作用于路径。

PathEffect pe = new DiscretePathEffect(10, 4);PathEffect pe2 = new CornerPathEffect(4);dwShape[3].getPaint().setPathEffect( new ComposePathEffect(pe2, pe));

image

setXfermode(Xfermode xfermode); 设置图形重叠时的处理方式

设置图形重叠时的处理方式,如合并,取交集或并集,经常用来制作橡皮的擦除效果

模式 效果 AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。 PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素XOR操作。 PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。
  • AvoidXfermode
1 AvoidXfermode avoid = new AvoidXfermode(Color.BLUE, 10, AvoidXfermode.Mode. AVOID); 2 borderPen.setXfermode(avoid)
  • PixelXorXfermode
1 Xfermode xFermode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);2 paint.setXfermode(xFermode);
  • PorterDuffXfermode
模式 效果 PorterDuff.Mode.CLEAR 所绘制不会提交到画布上。 PorterDuff.Mode.SRC 显示上层绘制图片 PorterDuff.Mode.DST 显示下层绘制图片 PorterDuff.Mode.SRC_OVER 正常绘制显示,上下层绘制叠盖。 PorterDuff.Mode.DST_OVER 上下层都显示。下层居上显示。 PorterDuff.Mode.SRC_IN 取两层绘制交集。显示上层。 PorterDuff.Mode.DST_IN 取两层绘制交集。显示下层。 PorterDuff.Mode.SRC_OUT 上层绘制非交集部分。 PorterDuff.Mode.DST_OUT 下层绘制非交集部分。 PorterDuff.Mode.SRC_ATOP 下层非交集部分与上层交集部分 PorterDuff.Mode.DST_ATOP 上层非交集部分与下层交集部分 PorterDuff.Mode.XOR 异或:去除两图层交集部分 PorterDuff.Mode.DARKEN 取两图层全部区域,交集部分颜色加深 PorterDuff.Mode.LIGHTEN 取两图层全部,点亮交集部分颜色 PorterDuff.Mode.MULTIPLY 取两图层交集部分叠加后颜色 PorterDuff.Mode.SCREEN 取两图层全部区域,交集部分变为透明色

image

setARGB(int a,int r,int g,int b); 设置画笔颜色

设置绘制的颜色,a代表透明度,r,g,b代表颜色值。

p.setARGB(175, 216, 216, 216); 

setAlpha(int a); 设置绘制图形的透明度

mBluePaint.setAlpha(10);

setColor(int color) 设置画笔制的颜色

使用颜色值来表示,该颜色值包括透明度和RGB颜色

mBluePaint.setColor(0xff0000ff); 

setShader(Shader shader); 设置图像效果

使用Shader可以绘制出渲染图像以及一些几何图形

包括了5个直接子类:

  • BitmapShader 图像渲染
  • ComposeShader 混合渲染
  • LinearGradient 线性渲染
  • RadialGradient 环形渲染
  • SweepGradien 梯度渲染

BitmapShader (Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY);

  • bitmap : 表示用来作为纹理填充的位图
  • Shader.TileMode
类型 效果 CLAMP 平铺 如果渲染器超出原始边界范围,则会复制边缘颜色对超出范围的区域进行着色 REPEAT 重复 横向和纵向上以平铺的形式重复渲染位图 MIRROR 镜像 在横向和纵向上以镜像的方式重复渲染位图
new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 

image

LinearGradient (float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile);

作用是实现某一区域内颜色的线性渐变效果

  • x0表示渐变的起始点x坐标
  • y0表示渐变的起始点y坐标
  • x1表示渐变的终点x坐标
  • y1表示渐变的终点y坐标
  • colors表示渐变的颜色数组
  • positions用来指定颜色数组的相对位;
  • tile表示平铺方式

通常,参数positions设为null,表示颜色数组以斜坡线的形式均匀分布。

另外一种构造方式:

LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)
- color0表示渐变开始颜色
- color1表示渐变结束颜色

利用LinearGradient实现一个从蓝色线性渐变到红色的圆形图:

new LinearGradient(width / 2, 0, width / 2, height, 0xffffffff, 0x00ffffff,Shader.TileMode.CLAMP);

image

ComposeShader (Shader shaderA, Shader shaderB, PorterDuff.Mode mode);

作用是实现渲染效果的叠加,如BitmapShader与LinearGradient的混合渲染效果等

  • 参数shaderA表示某一种渲染效果
  • 参数shaderB也表示某一种渲染效果
  • 参数mode表示两种渲染效果的叠加模式

RadialGradient (float x, float y, float radius, int[] colors, float[] positions, Shader.TileMode tile);

作用是在某一区域内实现环形的渐变效果

  • 参数x表示环形的圆心x坐标
  • 参数y表示环形的圆心y坐标
  • 参数radius表示环形的半径
  • 参数colors表示环形渐变的颜色数组
  • 参数positions用来指定颜色数组的相对位置
  • 参数tile表示平铺的方式
new RadialGradient(37.5f, 12.5f, 50f, color, darkColor, Shader.TileMode.CLAMP);

image

SweepGradient (float cx, float cy, int[] colors, float[] positions);

梯度渲染,是指在某一中心以x轴正方向逆时针旋转一周而形成的扫描效果的渲染形式。

  • 参数cx表示扫描的中心x坐标;
  • 参数cy表示扫描的中心y坐标;
  • 参数colors表示梯度渐变的颜色数组;
  • 参数positions用来指定颜色数组的相对位置。
 new SweepGradient(0.0f, 0.0f, 0xff000000, 0xffffffff); 

image

setShadowLayer(float radius ,float dx,float dy,int color); 在图形下面设置阴影层

产生阴影效果

  • 第一个参数为模糊半径,越大越模糊
  • 第二个参数是阴影离开文字的x横向距离
  • 第三个参数是阴影离开文字的Y横向距离
  • 第四个参数是阴影颜色
valuePaint.setShadowLayer(0.5f, 0, 0.5f, 0xFFFFFFFF); 

setStyle(Paint.Style style); 设置画笔的样式

Paint.Style类型有

类型 效果 Style.FILL 实心 Style.FILL_AND_STROKE 实心和空心兼有 Style.STROKE 空心
paint.setStyle(Paint.Style.STROKE); 

image

setStrokeCap(Paint.Cap cap); 设置笔刷的图形样式

当画笔样式为STROKE或FILL_OR_STROKE时可用

  • Cap.ROUND 圆形样式
  • Cap.SQUARE 方形样式

image

setSrokeJoin(Paint.Join join); 设置绘制时各图形的结合方式

  • Join.MITER(结合处为锐角)
  • Join.Round(结合处为圆弧)
  • Join.BEVEL(结合处为直线)

image

setStrokeWidth(float width); 设置笔刷的粗细度

当画笔样式为STROKE或FILL_OR_STROKE时可用

pt.setStrokeWidth(12.0f); 

setFakeBoldText(boolean fakeBoldText); 模拟实现粗体文字

设置在小字体上效果会非常差

image
image

setSubpixelText(boolean subpixelText); 对文本的一种优化设置

设置自像素。如果该项为true,将有助于文本在LCD屏幕上的显示效果

setTextAlign(Paint.Align align); 设置绘制文字的对齐方向

  • CENTER: 居中
  • LEFT: 左对齐
  • RIGHT :右对齐

setTextScaleX(float scaleX); 设置绘制文字x轴的缩放比例

可以实现文字的拉伸的效果

setTextSize(float textSize); 设置绘制文字的字号大小

setTextSkewX(float skewX); 设置斜体文

  • skewX为倾斜弧度

setTypeface(Typeface typeface); 字体风格

  • Typeface.DEFAULT:默认字体。
  • Typeface.DEFAULT_BOLD:加粗字体。
  • Typeface.MONOSPACE:monospace字体。
  • Typeface.SANS_SERIF:sans字体。
  • Typeface.SERIF:serif字体。
/将字体文件保存在assets/fonts/目录下,创建Typeface对象Typeface typeFace =Typeface.createFromAsset(getAssets(),"fonts/HandmadeTypewriter.ttf");//使用字体textView.setTypeface(typeFace);

setUnderlineText(boolean underlineText); 设置带有下划线的文字效果

setStrikeThruText(boolean strikeThruText); 设置带有删除线的效果

setLetterSpacing(float letterSpacing) 设置行的间距

默认值是0,负值行间距会收缩

setFontFeatureSettings(String settings) 设置字体样式,可以设置CSS样式

measureText(char[] text, int index, int count) 测量字体的长度

measureText(String text, int start, int end)

measureText(String text)

measureText(CharSequence text, int start, int end)

paint.measureText(mString); 

breakText(char[] text, int index, int count,float maxWidth, float[] measuredWidth) 截取指定长度的显示

breakText(CharSequence text, int start, int end,boolean measureForwards, floatmaxWidth, float[] measuredWidth)

breakText(String text, boolean measureForwards,float maxWidth, float[] measuredWidth)

剪切显示,就是大于maxWidth的时候只截取指定长度的显示

p.breakText(text, true, maxSize - 12, null); 

getTextWidths(char[] text, int index, int count,float[] widths) 提取指定范围内的字符串

getTextWidths(CharSequence text, int start, int end, float[] widths)

getTextWidths(String text, int start, int end, float[] widths)

getTextWidths(String text, float[] widths)

提取指定范围内的字符串,保存到widths中

mScalePaint.getTextWidths("...", 0, 1, widths); 

getTextPath(char[] text, int index, int count, float x, float y, Path path) 获取文本绘制的路径

getTextPath(String text, int start, int end, float x, float y, Path path)

获取文本绘制的路径,提取到Path中

mHugePaint.getTextPath(text, 0, count, 0, 0, path); 

getTextBounds(String text, int start, int end, Rect bounds) 得到文本的边界

getTextBounds(char[] text, int index, int count, Rect bounds)

得到文本的边界,上下左右,提取到bounds中,可以通过这计算文本的宽和高

mTextPaint.getTextBounds( mLabel, 0, mLabel.length(), mBounds ); 

文本FontMetrics类:

textPaint.getFontMetrics(); 

基准点是baseline
- ascent:是baseline之上至字符最高处的距离
- descent:是baseline之下至字符最低处的距离
- leading:是上一行字符的descent到下一行的ascent之间的距离,也就是相邻行间的空白距离
- top:是指的是最高字符到baseline的值,即ascent的最大值
- bottom:是指最低字符到baseline的值,即descent的最大值

image

ascent() + descent() 可以看成文字的height。

mPaint.measureText(text) 可以看成文字的width。

绘画文字时候的x,y坐标为:

dx = (int) mPaint.measureText(String.valueOf(mDayOfMonth)) / 2;dy = (int) (-mPaint.ascent() + mPaint.descent()) / 2;
0 0