热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android自定义控件绘图篇之Paint函数大汇总

本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。

自定义控件三部曲之绘图篇(七)——Paint之函数大汇总

本篇将讲述路径的各种效果,比如铁锈路径、自定义图形路径、虚线路径等

经过前几篇,我们基本把paint和canvas的基本用法就看完了,今天我们来个大汇总,列举一个paint的所有函数,然后一个一个的过。经过这几篇,你将能学会paint中所有处理函数的用法。

一、基本用法

1、概述

我们先来看一下paint中基本设置的函数都有哪些:

reset()

重置画笔

setColor(int color)

给画笔设置颜色值

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

同样是设置颜色,但是利用ARGB分开设置

setAlpha(int a)

设置画笔透明度

setStyle(Paint.Style style)

设置画笔样式,取值有

Paint.Style.FILL :填充内部

Paint.Style.FILL_AND_STROKE :填充内部和描边

Paint.Style.STROKE :仅描边

setStrokeWidth(float width)

设置画笔宽度

setAntiAlias(boolean aa)

设置画笔是否抗锯齿

上面这些函数,我们在前面几篇已经详细讲过了,难度也都不大,不再细讲。下面几个函数我们是没有讲到过的,下面做下补充

setStrokeCap(Paint.Cap cap)

设置线冒样式,取值有Cap.ROUND(圆形线冒)、Cap.SQUARE(方形线冒)、Paint.Cap.BUTT(无线冒)

setStrokeJoin(Paint.Join join)

设置线段连接处样式,取值有:Join.MITER(结合处为锐角)、Join.Round(结合处为圆弧)、Join.BEVEL(结合处为直线)

setStrokeMiter(float miter)

设置笔画的倾斜度,90度拿画笔与30拿画笔,画出来的线条样式肯定是不一样的吧。(事实证明,根本看不出来什么区别好吗……囧……)

setPathEffect(PathEffect effect)

设置路径样式;取值类型是所有派生自PathEffect的子类:ComposePathEffect, CornerPathEffect, DashPathEffect, DiscretePathEffect, PathDashPathEffect, SumPathEffect

这四个函数中,setStrokeMiter(float miter)就不再讲了,我做过试验,没什么变化,也就是没啥屌用……,我们分别来看看另外三个函数的具体用法。

2、setStrokeCap(Paint.Cap cap)

设置线帽样式,取值有Cap.ROUND(圆形线帽)、Cap.SQUARE(方形线帽)、Paint.Cap.BUTT(无线帽)

我先不讲什么叫做线冒,大家先来看看下面这段代码以及它的效果:

有关自定义View控件的部分就不再讲了,我们已经啰嗦了六篇文章了,如果现在还不知道如何自定义一个控件让其显示绘图效果的话,可以去撞豆腐了

Paint paint = new Paint();

paint.setStrokeWidth(80);

paint.setAntiAlias(true);

paint.setColor(Color.GREEN);

paint.setStyle(Paint.Style.STROKE);

paint.setStrokeCap(Paint.Cap.BUTT);

canvas.drawLine(100,200,400,200,paint);

paint.setStrokeCap(Paint.Cap.SQUARE);

canvas.drawLine(100,400,400,400,paint);

paint.setStrokeCap(Paint.Cap.ROUND);

canvas.drawLine(100,600,400,600,paint);

//垂直画出x=100这条线

paint.reset();

paint.setStrokeWidth(2);

paint.setColor(Color.RED);

canvas.drawLine(100,50,100,750,paint);

在这里,我们水平画了三条线,他们的线冒类型分别是Cap.BUTT(无线帽)、Cap.SQUARE(方形线帽)、Cap.ROUND(圆形线冒)

最后,垂直画出x=100的那条起始线:

d424a0346a5ba6f03da0651a1ce94f8c.png

从效果图中可以明显看出,从无线冒多出来的那块区域就是线帽!就相当于给原来的直线加上一个帽子一样,所以叫线帽

android的线冒样式是很少的,只有方形和圆形两种,而在Windows SDK中,线冒样式多达十几种。

8ba12c3ca44079d43d5f0daee8278ff5.png

3、setStrokeJoin(Paint.Join join)

参数取值有:

Join.MITER(结合处为锐角)

Join.Round(结合处为圆弧)

Join.BEVEL(结合处为直线)

网上说,他们三个的区别如下:

02cd75030336c67385008c7c40911299.png

但我运行出来的效果却不是如此,Join.Round和 Join.BEVEL没有明显的区别:

我们画出来三个锐角的path,分别给这三段Path设置不同的连接方式:

Paint paint = new Paint();

paint.setStrokeWidth(40);

paint.setColor(Color.GREEN);

paint.setStyle(Paint.Style.STROKE);

paint.setAntiAlias(true);

Path path = new Path();

path.moveTo(100,100);

path.lineTo(450,100);

path.lineTo(100,300);

paint.setStrokeJoin(Paint.Join.MITER);

canvas.drawPath(path,paint);

path.moveTo(100,400);

path.lineTo(450,400);

path.lineTo(100,600);

paint.setStrokeJoin(Paint.Join.BEVEL);

canvas.drawPath(path,paint);

path.moveTo(100,700);

path.lineTo(450,700);

path.lineTo(100,900);

paint.setStrokeJoin(Paint.Join.ROUND);

canvas.drawPath(path,paint);

效果为:

8e1ed46e9ceac1eba2ad00e05cc8bafd.png

4、setPathEffect(PathEffect effect)

设置路径样式;取值类型是所有派生自PathEffect的子类

28ce5c9d44173aad413c86bfa20478fb.png

我们一个个来看他们的效果:

(1)、CornerPathEffect——圆形拐角效果

它的作用就是将原来Path生硬的直线拐角,变成圆形拐角:

a1fd8e896ba5cd40c26c2e2585b98410.png

上面的那条是Path默认的直线拐角,下面的那条是圆形拐角。

其构造函数为:

public CornerPathEffect(float radius)

它只有一个参数radius:即当前连接两条直线所使用的圆的半径。

b3fbb5780acf9a52ac8f31a68b504d53.png

上面这个图,很清晰的展示了利用半径R=50的圆来代替原来两条直线间的夹角。

我们利用代码,再来看看具体效果:

Paint paint = new Paint();

paint.setStrokeWidth(4);

paint.setColor(Color.GREEN);

paint.setStyle(Paint.Style.STROKE);

Path path = new Path();

path.moveTo(100,600);

path.lineTo(400,100);

path.lineTo(700,900);

canvas.drawPath(path,paint);

paint.setColor(Color.RED);

paint.setPathEffect(new CornerPathEffect(100));

canvas.drawPath(path,paint);

paint.setColor(Color.YELLOW);

paint.setPathEffect(new CornerPathEffect(200));

canvas.drawPath(path,paint);

在这里,我利用Path构造了一个夹角,在同一个位置画了三遍,第一遍是没有添加任何PathEffect的;第二遍,CornerPathEffect的圆半径为100;第三遍CornerPathEffect的圆半径为200;

2d1f7089883245a7dffa5572f0958e42.png

很明显能看出在半径不同情况下,连接位置也是不一样的。

(2)、DashPathEffect——虚线效果

这个功能能够实现虚线段的效果:

98bf3ad68c6f88143b7fe07744e3c4ad.png

它的函数声名如下:

public DashPathEffect(float intervals[], float phase)

其中:

intervals[]:

表示组成虚线的各个线段的长度;整条虚线就是由intervals[]中这些基本线段循环组成的。比如,我们定义new float[] {20,10};那这个虚线段就是由两段线段组成的,第一个可见的线段长为20,每二个线段不可见,长度为10;

2bf65c4a338b5c127134e5e783ad2f1a.png

对于intervals[]数组的有两个限定:

长度必须大于等于2;因为必须有一个实线段和一个空线段来组成虚线。

个数必须为偶数,如果是基数,最后一个数字将被忽略;这个很好理解,因为一组虚线的组成必然是一个实线和一个空线成对组成的。

我们再做一个假设,如果我们定义intervals[]为new float[] {20,10,100,100};那么这条虚线将是由四条子线段循环组成的,第一条实线长度为20,第二个空线长度为10,第三个实线长为100,第四条空线长充为100;

phase:

开始绘制的偏移值

我们来看看代码的运行效果来验证我们想的是否正确:

Paint paint = getPaint();

Path path = new Path();

path.moveTo(100,600);

path.lineTo(400,100);

path.lineTo(700,900);

canvas.drawPath(path,paint);

paint.setColor(Color.RED);

//使用DashPathEffect画线段

paint.setPathEffect(new DashPathEffect(new float[]{20,10,100,100},0));

canvas.translate(0,100);

canvas.drawPath(path,paint);

//画同一条线段,偏移值为15

paint.setPathEffect(new DashPathEffect(new float[]{20,10,50,100},15));

paint.setColor(Color.YELLOW);

canvas.translate(0,100);

canvas.drawPath(path,paint);

其中把paint封装成一个getPaint方法来获取基本的画笔设置。

private Paint getPaint(){

Paint paint = new Paint();

paint.setStrokeWidth(4);

paint.setColor(Color.GREEN);

paint.setStyle(Paint.Style.STROKE);

paint.setAntiAlias(true);

return paint;

}

效果图如下:

c5a10584e702395259024a306941cfee.png

从这个效果图中可以看到两点:

第一:红线段的基本组成部分,分别长度为20,10,100,100实线段和空线段组成的

第二:黄线段位移了15,从开始处就可以明显看出效果。原来20的线段,只剩5,所以看起来就像一个点一样。大家也可以发挥想象,利用动画设置偏移量让这条虚线段动起来:

769005c0362b1b6f369bd409b79ce61c.gif

给大家一个提示,使用ValueAnimator,动画长度值设为一个虚线的一个基线的长度,这里的基线是由20,10,100,100组成的,所以一个基线长度是230,然后设置成无限循环,把拿到的值设置为DashPathEffect偏移量即可;

如果看完了我的动画系列,这个小动画是不会成问题的,这里就不再讲了,不懂的同学,看源码吧,源码里有这个动画。

(3)、DiscretePathEffect——离散路径效果

55da46e7d7bed68431437be447c9c17d.png

同样,图中第一条线是原生的,第二条线加上离散路径效果后的样式。

DiscretePathEffect就是将原来路径分隔成定长的线段,然后将每条线段随机偏移一段位置,我们可以用它来模拟一种类似生锈铁丝的效果;

它的构造函数如下:

public DiscretePathEffect(float segmentLength, float deviation)

第一个参数segmentLength:表示将原来的路径切成多长的线段。如果值为2,那么这个路径就会被切成一段段由长度为2的小线段。所以这个值越小,所切成的小线段越多;这个值越大,所切成的小线段越少。

第二参数deviation:表示被切成的每个小线段的可偏移距离。值越大,就表示每个线段的可偏移距离就越大,就显得越凌乱,值越小,每个线段的可偏移原位置的距离就越小。

我们看下代码效果:

Paint paint = getPaint();

Path path = getPath();

//第一条原生Path

canvas.drawPath(path,paint);

//第二条Path

canvas.translate(0,200);

paint.setPathEffect(new DiscretePathEffect(2,5));

canvas.drawPath(path,paint);

//第三条Path

canvas.translate(0,200);

paint.setPathEffect(new DiscretePathEffect(6,5));

canvas.drawPath(path,paint);

//第四条Path

canvas.translate(0,200);

paint.setPathEffect(new DiscretePathEffect(6,15));

canvas.drawPath(path,paint);

我们这里涉及到一个函数getPath函数就是随机生成一条路径;我们先来看效果,然后再回来看getPath()的实现

4731b07498989b872f13f9e45ac272bf.png

从第二条和第三条相比,可以明显看出,在仅增大segmentLength的情况下,很明显第三条线段所切的子线段要大一些,所以就没有第二条曲线的那么多线段相交所产生的折点,所以相比第二条更顺滑一些,当然铁锈效果就没有第二条那么明显了。

第三条和第四条相比,在segmentLength都是6的情况下,在第四条仅增大了deviation参数(偏移距离),从效果图中也明显可以看出每个子线段向外偏移的距离也增大了。

从效果图中很明显可以看出各个参数的作用,这里就不多讲了,下面回过头来看看getPath()得到一个随机路径的方法:

private Path getPath(){

Path path = new Path();

// 定义路径的起点

path.moveTo(0, 0);

// 定义路径的各个点

for (int i &#61; 0; i <&#61; 40; i&#43;&#43;) {

path.lineTo(i*35, (float) (Math.random() * 150));

}

return path;

}

就是利用Math.random()产生一个随机数&#xff0c;然后每隔35px构造出一个点。代码难度不大&#xff0c;不再细讲。

(4)、PathDashPathEffect——印章路径效果

这个名字是我自己取的……&#xff0c;因为这个功能就相当于Photoshop中的印章功能。

它的作用就是用另一个路径图案做为印章&#xff0c;沿着指定路径一个个盖上去。

我们先来看看PathDashPathEffect的声明:

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

其中&#xff1a;

Path shape:表示印章路径&#xff0c;比如我们下面示例中的三角形加右上角一个点&#xff1b;

float advance&#xff1a;表示两个印章路径间的距离,很容易理解&#xff0c;印章间距离越大&#xff0c;间距就越大。

float phase&#xff1a;路径绘制偏移距离&#xff0c;与上面DashPathEffect中的float phase参数意义相同

Style style&#xff1a;表示在遇到转角时&#xff0c;如何操作印章以使转角平滑过渡&#xff0c;取值有&#xff1a;Style.ROTATE&#xff0c;Style.MORPH&#xff0c;Style.TRANSLATE;Style.ROTATE表示通过旋转印章来过渡转角&#xff1b;Style.MORPH表示通过变形印章来过渡转角&#xff1b;Style.TRANSLATE表示通过位移来过渡转角。这三个效果的具体意义&#xff0c;上面会通过具体示例来分别讲解。

然后我们看看如何来实现下面这个效果&#xff1a;

f6e947ec785c71593058a27c6b3ea0cf.png

如上图所示&#xff0c;印章路径就是一个三角形加右上角一个点。然后就拿这个印章路径在原来的路径上每隔一定距离盖章。

上图的对应代码为&#xff1a;

Paint paint &#61; getPaint();

//画出原始路径

Path path &#61; new Path();

path.moveTo(100,600);

path.lineTo(400,100);

path.lineTo(700,900);

canvas.drawPath(path,paint);

//构建印章路径

Path stampPath &#61; new Path();

stampPath.moveTo(0,20);

stampPath.lineTo(10,0);

stampPath.lineTo(20,20);

stampPath.close();

stampPath.addCircle(0,0,3, Path.Direction.CCW);

//使用印章路径效果

canvas.translate(0,200);

paint.setPathEffect(new PathDashPathEffect(stampPath,35,0, PathDashPathEffect.Style.TRANSLATE));

canvas.drawPath(path,paint);

最重要的是最后几句

//构建印章路径

Path stampPath &#61; new Path();

stampPath.moveTo(0,20);

stampPath.lineTo(10,0);

stampPath.lineTo(20,20);

stampPath.close();

stampPath.addCircle(0,0,3, Path.Direction.CCW);

//使用印章路径效果

canvas.translate(0,200);

paint.setPathEffect(new PathDashPathEffect(stampPath,35,0, PathDashPathEffect.Style.TRANSLATE));

首先构造一个印章路径&#xff0c;然后利用

paint.setPathEffect(new PathDashPathEffect(stampPath,35,0, PathDashPathEffect.Style.TRANSLATE));

来构造一个印章画笔&#xff0c;然后就利用这个画笔在指定路径上画图

canvas.drawPath(path,paint);

在示例中我们有两个路径&#xff0c;大家一定要把路径和印章路径分清楚&#xff0c;一个路径是path&#xff0c;这个是原始路径&#xff1b;另一个路径是stampPath,这个是印章路径。印章路径是用来构造画笔的(paint)&#xff0c;而原始的路径就是用这个画笔来做画的。

下面我们就来看看&#xff0c;在Style不同的情况下&#xff0c;在转角处都如何处理的&#xff1a;

private void drawPathDashPathEffect(Canvas canvas){

Paint paint &#61; getPaint();

Path path &#61; getPath();

canvas.drawPath(path,paint);

canvas.translate(0,200);

paint.setPathEffect(new PathDashPathEffect(getStampPath(),35,0, PathDashPathEffect.Style.MORPH));

canvas.drawPath(path,paint);

canvas.translate(0,200);

paint.setPathEffect(new PathDashPathEffect(getStampPath(),35,0, PathDashPathEffect.Style.ROTATE));

canvas.drawPath(path,paint);

canvas.translate(0,200);

paint.setPathEffect(new PathDashPathEffect(getStampPath(),35,0, PathDashPathEffect.Style.TRANSLATE));

canvas.drawPath(path,paint);

}

private Path getStampPath(){

Path path &#61; new Path();

path.moveTo(0,20);

path.lineTo(10,0);

path.lineTo(20,20);

path.close();

path.addCircle(0,0,3, Path.Direction.CCW);

return path;

}

这段代码通过getPath()函数随机生成一条路径&#xff0c;并将原始路径和各个Style的路径画出来。第一条是原始路径&#xff0c;第二条的Style是Style.MORPH&#xff0c;第三条是Style.ROTATE&#xff0c;第四条是Style.TRANSLATE&#xff1b;

ef68929d0b3b75480f35d86f986c4bdb.png

大家第一眼估计就看得眼花缭乱了&#xff0c;仔细看一下红线处的三角形的样式。

74c4ea66a64ede4367206cc27ba0bec0.png

同样是转角&#xff0c;如上图&#xff0c;当Style.MORPH时&#xff0c;就是通过对印章进行变形来过渡转角的

a77f3e4d429b28ea20316d94e8185d7f.png

当Style为Style.ROTATE时就是靠旋转印章角度来过渡转角的

2667ca50245d7773b78b07a8eeeb9498.png

当Style为Style.TRANSLATE时&#xff0c;即不会对印章变形也不会对旋转印章角度&#xff0c;而只是通过变改印章的位置来过渡

其中的一个参数float phase&#xff0c;表示路径绘制偏移距离我们还没讲&#xff0c;这个与上面的偏移距离的意义一样&#xff0c;通过改变偏移距离同样可以实现动画

b5ec6378310f374eb4834e24ce352c29.gif

(5)、ComposePathEffect与SumPathEffect

这两个都是用来合并两个特效的。但它们之间是有区别的&#xff1a;

public ComposePathEffect(PathEffect outerpe, PathEffect innerpe)

ComposePathEffect合并两个特效是有先后顺序的&#xff0c;它会先将第二个参数的PathEffect innerpe的特效作用于路径上&#xff0c;然后再在此加了特效的路径上作用第二个特效。

public SumPathEffect(PathEffect first, PathEffect second)

而SumPathEffect是分别对原始路径分别作用第一个特效和第二个特效。然后再将这两条路径合并&#xff0c;做为最终结果。

我们来看看效果&#xff1a;

//画原始路径

Paint paint &#61; getPaint();

Path path &#61; getPath();

canvas.drawPath(path,paint);

//仅应用圆角特效的路径

canvas.translate(0,200);

CornerPathEffect cornerPathEffect &#61; new CornerPathEffect(100);

paint.setPathEffect(cornerPathEffect);

canvas.drawPath(path,paint);

//仅应用虚线特效的路径

canvas.translate(0,200);

DashPathEffect dashPathEffect &#61; new DashPathEffect(new float[]{2,5,10,10},0);

paint.setPathEffect(dashPathEffect);

canvas.drawPath(path,paint);

//利用ComposePathEffect先应用圆角特效,再应用虚线特效

canvas.translate(0,200);

ComposePathEffect composePathEffect &#61; new ComposePathEffect(dashPathEffect,cornerPathEffect);

paint.setPathEffect(composePathEffect);

canvas.drawPath(path,paint);

//利用SumPathEffect,分别将圆角特效应用于原始路径,然后将生成的两条特效路径合并

canvas.translate(0,200);

paint.setStyle(Paint.Style.STROKE);

SumPathEffect sumPathEffect &#61; new SumPathEffect(cornerPathEffect,dashPathEffect);

paint.setPathEffect(sumPathEffect);

canvas.drawPath(path,paint);

代码很简单&#xff0c;就是画几条特效路径 &#xff0c;效果图如下&#xff1a;

efa70e3eda9ea21edec297e6fbce88b1.png

特别注意路径D和路径E:

路径D的生成方法为&#xff1a;

ComposePathEffect(dashPathEffect,cornerPathEffect);

表示先将圆角特效应用于原始路径&#xff0c;得到路径B&#xff0c;然后再在路径B的基础上应用虚线特效得到最终的效果D;

而路径E的生成方法则比较弱智&#xff1a;

SumPathEffect(cornerPathEffect,dashPathEffect);

它的原理是&#xff0c;先将圆角特效应用于原始路径A得到路径B,然后将虚线特效应依然应用于原始路径&#xff0c;得到路径C.然后将路径B和路径C合并(即画在一起……囧)&#xff0c;就得到路径E

好了&#xff0c;到这里&#xff0c;所有的路径效果都讲完了&#xff0c;真TM累死哥了……

二、字体相关

setTextSize(float textSize)

设置文字大小

setFakeBoldText(boolean fakeBoldText)

设置是否为粗体文字

setStrikeThruText(boolean strikeThruText)

设置带有删除线效果

setUnderlineText(boolean underlineText)

设置下划线

setTextAlign(Paint.Align align)

设置开始绘图点位置

setTextScaleX(float scaleX)

水平拉伸设置

setTextSkewX(float skewX)

设置字体水平倾斜度&#xff0c;普通斜体字是-0.25&#xff0c;可见往右斜

setTypeface(Typeface typeface)

字体样式

上面的这些方法&#xff0c;我们在

已经详细讲过&#xff0c;这里就不再细讲

下面补充几个没讲到的函数&#xff1a;

1、setLinearText(boolean linearText)

设置是否打开线性文本标识&#xff1b;由于文本想要快速绘制出来&#xff0c;必然是需要提前缓存在显存中的&#xff0c;一般而言每个文字需要一个字节的大小来存储它(当然具体需要多少字节与编码方式有关)&#xff0c;那如果是长篇文章&#xff0c;可见所需的大小可想而知。我们可以通过setLinearText (true)告诉Android我们不需要这样的文本缓存。但如果我们不用文本缓存&#xff0c;虽然能够省去一些内存空间&#xff0c;但这是以显示速度为代价的。

由于这个是API 1的函数&#xff0c;由于当时的android手机的内存大小还是很小的&#xff0c;所以尽量减少内存使用是每个应用的头等大事&#xff0c;在当时的的环境下这个函数还是很有用的。

但在今天&#xff0c;内存动不动就是4G以上了&#xff0c;文本缓存的所占的那点内存就微不足道了&#xff0c;没有哪个APP会牺牲性能来减少这点这内存占用了&#xff0c;所以这个函数基本没用了。

2、setSubpixelText(boolean subpixelText)

表示是否打开亚像素设置来绘制文本。亚像素的概念比较难理解&#xff0c;首先&#xff0c;我们都知道像素&#xff0c;比如一个android手机的分辨率是1280*720&#xff0c;那就是指它的屏幕在垂直方向有1280个像素点&#xff0c;水平方向上有720个像素点。我们知道每个像素点都是一个独立显示一个颜色的个体。所以如果一副图片&#xff0c;在一个屏幕上用了300*100个相素点&#xff0c;而在另一个屏幕上却用了450*150个像素来显示。那么&#xff0c;请问在哪个屏幕上这张图片显示的更清晰&#xff1f;当然是第二个屏幕&#xff0c;因为它使用的像素点更多&#xff0c;所显示的细节更精细。

那么问题来了&#xff0c;android设置在出厂时&#xff0c;设定的像素显示都是固定的几个范围&#xff1a;320*480&#xff0c;480*800&#xff0c;720*1280&#xff0c;1080*1920等等&#xff1b;那么如何在同样的分辨率的显示器中增强显示清晰度呢&#xff1f;

亚像素的概念就油然而生了&#xff0c;亚像素就是把两个相邻的两个像素之间的距离再细分&#xff0c;再插入一些像素&#xff0c;这些通过程序加入的像素就是亚像素。在两个像素间插入的像素个数是通过程序计算出来的&#xff0c;一般是插入两个、三个或四个。

所以打开亚像素显示&#xff0c;是可以在增强文本显示清晰度的&#xff0c;但由于插入亚像素是通过程序计算而来的&#xff0c;所以会耗费一定的计算机性能。注意&#xff1a;亚像素是通过程序计算出来模拟插入的&#xff0c;在没有改变硬件构造的情况下&#xff0c;来改善屏幕分辨率大小。

亚像素显示&#xff0c;是仅在液晶显示器上使用的一种增强字体清晰度的技术。但这种技术有时会出现问题&#xff0c;用投影仪投射到白色墙壁上&#xff0c;会出出字体显示不正常的情况&#xff0c;而且对于老式的CRT显示器是根本不支持的。

在android还没有出现时&#xff0c;windows已经能够支持亚像素显示了&#xff0c;在windows机器中&#xff0c;这个功能叫做ClearType&#xff0c;在以前讲述windows的GDI绘图时&#xff0c;也曾经讲过ClearType的应用效果。

b2a7657d8d20d1426fcaf7f2d38fbaa3.png

这个图片中的最后一行文字&#xff0c;就是在windows上应用CLearType技术后的显示效果。此图片摘自《 GDI&#43;学习及代码总结之——文本与字体》可见在windows的显示中&#xff0c;还是有明显差别的

但我放在android里面来试,并未发现明显的差别&#xff0c;可能是我的显示器分辨率太高了……汗……

Paint paint &#61; new Paint();

paint.setColor(Color.GREEN);

String text &#61; "乌龟&梦想";

paint.setTextSize(200);

paint.setSubpixelText(false);

canvas.drawText(text,0,200,paint);

canvas.translate(0,300);

paint.setSubpixelText(true);

canvas.drawText(text,0,200,paint);

效果图如下&#xff1a;

1cf97104622c9cccc0bc3a69ee08c5c1.png

三、其它

接下来还剩几个跟图片和测量相关的函数&#xff0c;我们接下来分篇慢慢讲解。

1、图像处理&#xff1a;

setShader(Shader shader)

setShadowLayer(float radius, float dx, float dy, int shadowColor)

setDither(boolean dither)

setColorFilter(ColorFilter filter)

setXfermode(Xfermode xfermode)

setFilterBitmap(boolean filter)

clearShadowLayer()

2、measure测量相关

[java] view plain copy

breakText(char[] text, int index, int count, float maxWidth, float[] measuredWidth)

measureText(String text)

好了&#xff0c;本文就到这了



推荐阅读
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 花瓣|目标值_Compose 动画边学边做夏日彩虹
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Compose动画边学边做-夏日彩虹相关的知识,希望对你有一定的参考价值。引言Comp ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • 本文讨论了在shiro java配置中加入Shiro listener后启动失败的问题。作者引入了一系列jar包,并在web.xml中配置了相关内容,但启动后却无法正常运行。文章提供了具体引入的jar包和web.xml的配置内容,并指出可能的错误原因。该问题可能与jar包版本不兼容、web.xml配置错误等有关。 ... [详细]
  • 打开用户根目录cd~然后编辑.bash_profile文件#可以尝试用自带工具打开open-e.bash_profile#或者vim.bash_profile加入语句alia ... [详细]
author-avatar
benpk2702933054
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有