硬件加速:
GPU与CPU的区别:
-
GPU是专门负责所有的运算工作,自带处理器和存储器,专门用来计算和存储所媒体任务的
-
CPU的架构是有利于X86指令集的创行架构,从设计思路上看适合尽可能快的完成一项任务,但是面临类似多媒体、图形图像处理类型的任务是,就会显得力不从心
-
在Android中在API11之前是没有GPU概念的,在API14之后,硬件加速功能默认开启
-
在CPU和GPU绘制的时候,两者的流程是有区别的
-
CPU在基于软件的绘制模型写,主导绘图,试图按照下面两个步骤进行绘制:
让View层次结构失效
绘制View层次结构
- 在基于硬件加速的绘制模式下,GPU主导绘图,按照如下三个步骤进行:
让View层次结构失效
记录、更新显示列表
绘制显示列表
- 从上面可以看出GPU的工作流程比较复杂,并不是直接进行绘制的,首先将这些View函数作为绘制指令记录在一个显示列表中,然后图区显示列表中的绘制指令,调用OpenGL的相关函数完成实际的绘制
GPU加速 | 优点 | 缺点 |
---|---|---|
1 | 提高Android系统的显示和刷新的速度 | 兼容性问题,OpenGL可能不可以完全的兼容原始的绘制函数 |
2 | 内存消耗问题,因为需要OpenGL指令,所以需要将庞大的OpenGL相关的包引入,OpenGL API大致会占用8MB的内存,实际占用会更大 | |
3 | 电量消耗的问题,多使用了一个GPU部件,就好比电脑开独显费电一样 |
禁止使用GPU加速的方法:
- 整个应用级别的禁用硬件加速:
在AndroidMaifest.xml中为application添加
<application android:hardwareAccelerated="true">
- Activity级别的禁用:
在AndroidMaifest.xml中的activity下添加
<activity android:hardwareAccelerated="false"/>
- 在Window层级进行开启硬件加速(该层级不支持禁用硬件加速):
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
- 在View层级 使用如下代码进行关闭硬件加速(不支持开启硬件加速):
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
或者使用
<LinearLayout...
android:layerType="software"/>
文字
- 基线:
在Canvas中调用drawText()的时候,会有一个基线来控制文字的水平对齐方式,也就是小时候学习英语
四线格中的第三条底线,用来确定文字的位置
canvas.drawText()函数
public void drawText(String text, float x, float y, Paint paint)
(x,y)表示的是基线左起始点的位置
drawText()函数中的参数y是基线的位置
只要x,y坐标,极限位置,文字大小确定,文字的位置也就确定了
eg:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int baseLineX = 0;
int baseLineY = 200;
//画基线
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawLine(baseLineX, baseLineY, 3000, baseLineY, paint);
//写文字
paint.setColor(Color.GREEN);
paint.setTextSize(120);
canvas.drawText("wjx", baseLineX, baseLineY, paint);
}
- paint.setTextAlign()函数
- 在刚才的案例中发现y是文字基线的位置,但是会误认为x是文字开始的位置,实际上x是代表所绘制的文字所在矩形的相对位置,相对位置就是指点(x,y)在所要绘制矩形中的位置。
Paint::setTextAlign(Align align);
其中Align的取值为Paint.ALign.LEFT、Paint.Align.CENTER、Paint.Align.RIGHT, 参数的三个取值分别为在X坐标的左中右三个位置
- 注意:相对位置是根据所要绘制的文字的矩形进行计算的,就是你的文字有多长,那么center就会平分你的文字的长度
绘图四线格与 FontMetrics
- 除了基线以外,系统在绘制文字的时候,还有四条线,分别是ascent, descent, top和bottom
ascent:系统推荐的,在绘制单个字符的时,字符应当的最高高度所在线
descent:系统推荐的,在绘制单个字符时,字符应当的最低高度所在线
top:可绘制的最高高度所在线
bottom:可绘制的最低高度所在线
我们就尽量将文字绘制在系统推荐的最高和最低的限度之内,这样在不同的屏幕的手机上,文字都可以完整的展现出来
- FontMetrics概述:
- 在使用drawText()的时候,基线是由y来决定的,那么如何决定上述四个参数
- Android提供了一个类,FontMetrics,他里面有四个成员变量,也就是上述的四个参数
asccent = ascent线的y坐标 - baseline线的y坐标
descent = descent线的y坐标 - baseline线的y坐标
top = top的y坐标 - baseline线的y坐标
bottom = bottom线的y坐标 - baseline线的y坐标
- 注意:这四个变量是用来计算四条线的位置的,并不存在
计算方式:
ascent线y坐标 = baseline线y坐标 + fontMetric.ascent
descent线 y坐标 = baseline线的y坐标 + fontMetric.descent
top线y坐标 = baseline线y坐标 + fontMetric.top
bottom线的y坐标 = baseline线y坐标 + fontMetric.bottom
获取FontMetrics对象
Paint paint = new Paint();
//四个成员属性都死float类型
Paint.FontMetrics fontMetricsc = paint.getFontMetrics();
//四个成员属性是int类型
Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
eg:
//获取四条线
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float ascent = baseLineX + fontMetrics.ascent;
float descent = baseLineX + fontMetrics.descent;
float top = baseLineX + fontMetrics.top;
float bottom = baseLineX + fontMetrics.bottom;
//将四条线一条条画出来
paint.setColor(Color.BLUE);
//基线
canvas.drawLine(baseLineX, baseLineY, 300, baseLineY, paint);
//ascent线
paint.setColor(Color.RED);
canvas.drawLine(baseLineX, ascent, 3000, ascent, paint);
//descent线
paint.setColor(Color.GREEN);
canvas.drawLine(baseLineX, descent, 3000, descent, paint);
//top线
paint.setColor(Color.YELLOW);
canvas.drawLine(baseLineX, top, 3000, top, paint);
//bottom线
paint.setColor(Color.BLACK);
canvas.drawLine(baseLineX, bottom, 3000, bottom, paint);
常用函数:
- 字符串所占区域的高度和宽度
- 高度:bottom-top(注意y正方向向下)
Paint paint = new Paint();
Paint.FontMetricsInt fm = paint.getFontMetricsInt();
int top = baselineY + fm.top;
int bottom = baselineY + fm.bottom;
int height = bottom - top;
- 宽度:
int width = paint.measureText(String text);
- 最小矩形:
- 概述:最小矩形是通过系统函数来获得的
//text要测量的最小矩形字符串
//start起始字符在字符串中的索引
//end所要测的字符的长度
//bounds接受测试结果
public void getTextBounds(String text, int start, int end, Rect bounds)
eg:
Rect rect = new Rect();
paint.getTextBounds(text, 0, text.length(), rect);
System.out.println(rect.toShortString());
Paint函数
函数名称 | 说明 |
---|---|
reset() | 重置画笔 |
setColor() | 设置画笔颜色 |
setARGB(int a, intr, int g, int b) | 利用R, G, A, B设置颜色 |
setAlpha(int a) | 设置画笔的透明度 |
setStyle(Paint.Style style) | 设置画笔样式 |
setStrokeWidth(float width) | 设置画笔宽度 |
setAntiAlias(boolean aa) | 设置画笔是否抗锯齿 |
setStrokeMiter(float miter) | 设置画笔倾斜度(但是基本上看不出区别) |
setPathEffect(PathEffect effet) | 设置路径样式(下面详细描述) |
setStrokeCap(Paint.cap cap) | 设置线帽样式(Cap.Round, Cap.SQUARE, Cap.BUTT分别为圆方无线帽) |
setStrokejoin(Paint.Join join) | 设置路径转角样式 |
setDither(boolean ditcher) | 抗抖动效果 |
setTextSize(float textSize) | 字体大小 |
setFakeBoldText(boolean fakeBoldText) | 设置是否为粗体文字 |
setStrikeThruText(boolean strikeThruText) | 设置是否具有删除线效果 |
setUnderlineText(boolean underlineText) | 设置是否具有下划线效果 |
setTextAlign(Paint.Align align) | 设置开始绘图点位置 |
setTextScaleX(float scaleX) | 设置水平拉伸 |
setTextSkewX(float skewX) | 设置字体水平倾斜度 |
setTypeface(Typeface typeface) | 设置字体样式 |
setLinearText(boolean linearText) | 设置是否打开线性文本标识(牺牲文本缓存减少内存的占用,牺牲显示速度) |
setSubpixelText(boolean subpixelText) | 是否打开亚像素来设置文本(增加文本的清晰度,但是会耗费性能 |
- setPathEffect(PathEffect effect):
- 取值类型为所有派生自PathEffect的子类:ComposePatthEffect(原始路径)、CornerPathEffect(圆角拐角效果)、DashPathEffect(虚线效果)、DiscretePathEffect(离散路径效果)、PathDashPathEffect(印章路径效果)、SumPathEffect(复杂路径效果)