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

    xiaoxiao2021-03-26  10

    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中的坐标是在所画图形的右手坐标系中定义的,如下图所示:

    ambient

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

    specular

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

    blurRadius

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

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

    可以直接传入

    ColorMatrixColorFilterLightingColorFilterPorterDuffColorFilter

    的对象作为参数

    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(透明度)的向量

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

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

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

    这里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);

    原图

    效果图

    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。

    效果图

    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取两图层全部区域,交集部分变为透明色

    @Override protected 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); }

    效果图

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

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

    例如

    mPaint.setPathEffect(new CornerPathEffect(10));

    CornerPathEffect(float radius)

    将路径的转角变得圆滑

    DiscretePathEffect(float segmentLength, float deviation)

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

    new DiscretePathEffect(3.0F, 5.0F)

    第一个参指定这些突出的“杂点”的密度,值越小杂点越密集;

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

    DashPathEffect(float[] intervals, float phase)

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

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

    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);

    效果图:

    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));

    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取两图层全部区域,交集部分变为透明色

    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);

    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);

    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);

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

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

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

    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);

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

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

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

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

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

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

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

    pt.setStrokeWidth(12.0f);

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

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

    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的最大值

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

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

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

    dx = (int) mPaint.measureText(String.valueOf(mDayOfMonth)) / 2; dy = (int) (-mPaint.ascent() + mPaint.descent()) / 2;
    转载请注明原文地址: https://ju.6miu.com/read-500262.html

    最新回复(0)