Android自定义控件开发入门与实战(8)Paint基础

第六章、Paint的基本使用

硬件加速

GPU为“图形处理器”,是专门处理图形任务而产生的芯片。
在GPU出现之前,处理图片的一直是CPU,CPU从设计上是尽可能快的完成一项任务,但是对于需要频繁计算的图片、多并发线程下的图片的存取,CPU不能及时响应的话屏幕就会显得很卡顿。所以自带处理器和存储器专门处理多媒体计算的GPU应运而生。

对于Android,API 11之前没有GPU这个概念,在API 11之后,程序集中加入了对GPU加速的支持,在API 14之后,硬件加速默认是开启的,在API 11-13期间,硬件加速是有,但是默认关闭。我们可以显示的在进行图像计算时使用GPU而不是用CPU。

软件加速和硬件加速的区别
基于软件加速时,CPU主导绘图,视图按照两个步骤绘制:

  • 让View层次结构失效
  • 绘制View层次结构

在基于硬件加速时,GPU主导绘图,视图按照三个步骤绘制:

  • 让View层次结构失效
  • 记录、更新显示列表
  • 绘制显示列表

在GPU加速时,流程中后两个,表示在第一步View层次结构失效后,并不是直接开始逐层绘制的,而而是首先把这些view的绘制函数作为绘制指令记录在一个显示列表中,然后再读取显示列表中的绘制指令,调用OpenGL的相关函数完成实际绘制。

也就是说,在GPU加速时,实际上是使用OpenGL的相关函数来完成绘制的。
GPU加速相比于CPU加速的优点就是:提高了Android系统显示和刷新的速度。

但是其缺陷也比较明显:

  1. 兼容性问题:
    由于是将绘制函数转成OpenGL指令来绘制的,所以必然会存在OpenGL并不能完全支持原始绘制函数的问题。从而造成在打开GPU加速时,效果会失效的问题。
  2. 内存消耗问题:
    由于需要OpenGL的指令,所以需要把系统中与OpenGL相关的包加载到内存中来,而单纯的OpenGL API调用会占用8MB内存,实际上占用的内存会更大
  3. 电量消耗问题

禁用GPU硬件加速的方法
Android在四种层级上提供了不同的禁用方法,分为Application、Activity、Window、View

  1. AndroidManifest.xml中为application标签添加如下属性
 <application  android:hardwareAccelerated="false"
        ....>
  1. activity标签下也可以使用该属性
<activity  android:hardwareAccelerated="false"
        ....>
  1. 在Window层级上使用如下代码开启硬件加速(Window层级只能打开硬件加速不能关闭硬件加速)
getWindow().setFlag{
          WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
          WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
}
  1. View层级上,可以从代码或者layout文件来开启/禁用硬件加速
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
<LinearLayout 
    android:layerType="software"
    .....>

文字

在canvas中,在利用drawText()函数绘制文字时,文字的绘制是在一条基线上的。
就和我们刚开始学写字母时,在四线格上学写字母,而canvas的文字的位置也是在这条线上,其位置和四线格中的第三格线一样。

构造函数

canvas.drawText(String str,float x,float y,Paint paint);

其中str为文本内容,paint为画笔,x、y为绘制的起点坐标。
起点坐标是文本内容的左下角,y代表的是基线的纵坐标

我们来绘制一个View,然后把基线也绘制出来:
在这里插入图片描述
结论:

  • drawText()函数中y坐标是基线的位置

paint.setTextAlign函数
该函数之前接触过,就是用来表示文本内容在x坐标的左侧、中间、还是右侧
构造函数为:

Paint::setTextAlign(Align align);
//取值为:
paint.setTextAlign(Paint.Align.LEFT);        //文本在x坐标右侧
paint.setTextAlign(Paint.Align.CENTER);      //文本在x坐标中间
paint.setTextAlign(Paint.Align.RIGHT);       //文本在x坐标左侧

所以也知道默认情况下是Paint.Align.LEFT

四线格
除了基线以外,Androdi还提供了额外四个参考线:

  • ascent:单个字符应当的最高高度所在的线(系统推荐)
  • descent:单个字符应当的最低高度所在的线(系统推荐)
  • top:可绘制的最高高度所在线
  • bottom:可绘制的最低高度所在线

关于这部分知识可以上网找图,这里的主要意思是我们在绘制文字的时候,文字的最高高度要尽可能的比ascent要低,而最低高度要比descent要高。并且top要比ascent高,bottom要比descent要低。

FontMetrics
Android提供了一个类FontMetrics用来计算上述的四线格每个属性的值。
他们的计算方法如下:

  • ascent = ascent线的y坐标 - baseline线的y坐标
  • descent = descent线的y坐标 - baseline线的y坐标
  • top = top线的y坐标 - baseline线的y坐标
  • bottom = bottom线的y坐标 - baseline线的y坐标

因为x y轴以文字左下角为原点向右向下,所以ascent为负数,descent为正数。
注:这些值是真实存在的,不要混淆,它们就是用来计算文字的四线格的。

那么如何去获取这四线格涅:

Paint paint = new Paint();
Paint.FontMetrics fm = paint.getFontMetrics();
Paint.FontMetricsInt fmInt = paint.getFontMetricsInt();

这里看到有一个FontMetricsInt类,其实它和FontMetrics类一模一样,只是FontMetrics的值为float型,而FontMetricsInt的值为int型而已。
那么实例fm中就有ascent、descent这些参数啦。

一些常用函数
在这部分我们将学习如何获取字符串所占区域高度、宽度和最小矩形。

1、求一个Text的绘制区域大小,就是直接用bottom线所在的位置来减去top线所在的位置就能得出高度

        int top = baseLineY + fmInt.top;
        int bottom = baseLineY + fmInt.bottom;
        int hegiht = bottom - top;

而宽度也好测量:

  int width = paint.measureText(str);

这样就能得到字符串所占区域的高度和宽度辽

2、如何测最小矩形:
最小矩形就是通过系统函数来获取的:

 /**
     * Return in bounds (allocated by the caller) the smallest rectangle that
     * encloses all of the characters, with an implied origin at (0,0).
     * 获取指定字符串所对应的的最小矩形,以(0,0)点所在位置为基线。
     * 
     * @param text 要测量最小矩形的字符
     * @param start 所要测量字符在字符串中的索引
     * @param end 所要测量的字符串的长度
     * @param bounds 接受测量结果
     */
    public void getTextBounds(String text, int start, int end, Rect bounds);

Paint常用函数

这里接hencoder学习自定义view(1)
还有几个函数:

//线帽
setStrokeCap(Paint.Cap cap);

设置线帽有三个参数:Cap.ROUND(圆形线帽) Cap.SQUARE(方形线帽) Cap.BUTT(无线帽)

//设置路径的转角样式
setStrokeJoin(Paint.Join join);

设置转角路径有三个参数:Join.MITER(结合处为锐角) Join.ROUND(结合处为圆弧) Join.BEVEL(结合处为直线)

//抗抖动效果
setDither(bool dither)

什么是抗抖动效果呢?就是因为在RGB模式下 只能显示2^16=65535种颜色,因此很多丰富的色彩变化无法呈现。所以,图像在颜色渐变时,可能会出现大块马赛克的效果。
Android为了让色彩过渡不那么僵硬,于是在变化时的相邻像素颜色取中间值进行“调和”。

//设置是否为粗体文字
setFakeBoldText(boolean fakeBoldText)

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

//设置下划线
setUnderlinText(boolean underlineText)

//设置开始绘图点位置
setTextAlign(Paint.Align align)

//设置字体水平倾斜度
setTypeface(float skewX)

//设置字体样式
setTypeface(Typeface typeface)

//设置是否打开线性文本标识,不将文本保存在显存中,会浪费速度但是节省内存,以前手机内存很小的时候有用,但是基于当前手机市场,这个函数已经没什么用了
setLinearText(boolean linearText)

//是否打开亚像素设置来绘制文本
setSubpixelText(boolean subpixelText)

关于最后一个函数,亚像素的定义,是在像素之间再多插入几个像素点,这样的话会显得更加的清晰。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
封面 1 序 2 捐助说明 5 目 录 7 第一章 View的绘图流程 12 1.1、概述 12 1.2、Activity的组成结构 13 1.3、View树的绘图流程 15 1.3.1 测量组件大小 16 1.3.2 确定子组件的位置 17 1.3.3 绘制组件 18 1.4、说点别的 22 1.5 练习作业 22 第二章 Graphics2D API 23 2.1、概述 23 2.2、Point类和PointF类 23 2.3、Rect类和RectF类 25 2.4、Bitmap类和BitmapDrawable类 32 2.5、Canvas类与Paint类 34 2.5.1 绘图概述 34 2.5.2 Paint类 34 2.5.3 Canvas类 39 2.6 练习作业 63 第三章 使用Graphics2D实现动态效果 64 3.1 概述 64 3.2 invalidate()方法 65 3.3 坐标转换 69 3.4 剪切区(Clip) 73 3.5 案例:指针走动的手表 82 3.6 练习作业 88 第四章 双缓存技术 89 4.1 双缓存 89 4.2 在屏幕上绘制曲线 90 4.3 在屏幕上绘制矩形 99 4.4 案例:绘图App 104 4.4.1 绘图属性 106 4.4.2 软件参数 108 4.4.3 绘图缓冲区 109 4.4.4 撤消操作 111 4.4.5 图形绘制 113 4.4.6 绘图区 118 4.4.7 主界面 119 4.5 练习作业 122 第五章 阴影、渐变和位图运算 123 5.1 概述 123 5.2 阴影 123 5.3 渐变 125 5.3.1 线性渐变(LinearGradient) 126 5.3.2 径向渐变(RadialGradient) 130 5.3.3 扫描渐变(SweepGradient) 135 5.3.4 位图渐变(BitmapShader) 138 5.3.5 混合渐变(ComposeShader) 140 5.3.6 渐变与Matrix 142 5.4 位图运算 143 5.4.1 PorterDuffXfermode 143 5.4.2 图层(Layer) 146 5.4.3 位图运算技巧 148 5.5 案例1:圆形头像 152 5.6 案例2:刮刮乐 156 5.7 练习作业 161 第六章 自定义组件 163 6.1 概述 163 6.2 自定义组件的基本结构 164 6.3 重写onMeasure方法 166 6.4 组件属性 175 6.4.1 属性的基本定义 175 6.4.2 读取来自style和theme中的属性 181 6.5 案例1:圆形ImageView组件 186 6.6 案例2:验证码组件CodeView 190 6.7 练习作业 202 第七章 自定义容器 204 7.1 概述 204 7.2 ViewGroup类 205 7.2.1 ViewGroup常用方法 205 7.2.2 ViewGroup的工作原理 208 7.2.3 重写onLayout()方法 213 7.3 CornerLayout布局 217 7.3.1 基本实现 217 7.3.2 内边距padding 224 7.3.3 外边距margin 228 7.3.4 自定义LayoutParams 238 7.4 案例:流式布局(FlowLayout) 246 7.5 练习作业 256 第八章 Scroller与平滑滚动 257 8.1 概述 257 8.2 认识scrollTo()和scrollBy()方法 258 8.3 Scroller类 264 8.4 平滑滚动的工作原理 271 8.5 案例:触摸滑屏 272 8.5.1 触摸滑屏的技术分析 272 8.5.2 速度跟踪器VelocityTracker 273 8.5.3 触摸滑屏的分步实现 274 8.6 练习作业 285 第九章 侧边栏 287 9.1 概述 287 9.2 使用二进制保存标识数据 289 9.2.1 位运算符 289 9.2.2 位运算的常用功能 292 9.3 继承自ViewGroup的侧边栏 293 9.4 继承自HorizontalScrollView的侧边栏 304 9.5 练习作业 312 第十章 加强版ListView 313 10.1 概述 313 10.2 ListView的基本使用 314 10.3 ListItem随手指左右滑动 318 10.4 向右滑动删除ListItem 326 10.5 滑动ListItem出现删除按钮 336 10.5.1 列表项专用容器ExtendLayout 337 10.5.2 列表项能滑出删除按钮的ListView 342 10.5.3 定义布局文件 350 10.5.4 显示ListView 351 10.6练习作业 353 案例代码说明 354

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值