View绘制相关

2019-08-22  本文已影响0人  LeoFranz


硬件加速和软件加速的区别

硬件加速是GPU主导图形绘制
软件绘制是指CPU主导绘制
硬件加速中,由OpenGL调用绘制函数实现绘制,主要优势是提高了Android系统显示和刷新的速度。缺点在于
1、绘制函数被转化成了OpenGL,可能面临OpenGL函数不能完全兼容原生绘制函数的问题
2、需要额外加载OpenGL相关的包,增加内存消耗
3、更加耗电
在Application、activity、window、view中有各自的启用/禁用硬件加速的选项。间《自定义控件入门与实战》P206


Canvas与图层

获取Canvas对象的方法
1、重写onDraw(), dispatchDraw()方法
从传入参数中获取原始Canvas对象,其属于该view。
在绘制流程中,对view来说两个方法都会以同样的先后顺序被调用,除非在ViewGroup中如果缺乏背景onDraw()方法会被跳过。所以,对于图像的绘制代码可以放上述任意方法之中,但通常我们在View中重写onDraw(),在ViewGroup中重写onDisPatchDraw().
2、利用BitMap构建Canvas
Canvas c = new Canvas(bitmap);
通过这个canvas绘制的图像只会保存在bitmap对象中,不会直接显示在界面上,除非我们使用view原始canvas.drawBitmap()方法将该bitmap绘制。
3、使用SurfaceView时候调用其SurfaceHolder.lockCanvas函数

layer, Bitmap, Canvas的关系
layer是透明图层,每次调用canvas.drawXXX方法都会生成一个透明图层来绘制这个图形。
Bitmap是真正承载图像的对象,每次draw一个图形,就是生成一个透明图层绘制图像,然后覆盖到该Bitmap上。Bitmap画布有两种,一种是view的原始画布通过onDraw方法传入,由其中的canvas对象对应,另一种就是人造画布,通过saveLayer(),new Canvas(bitmap)等方法构造。注意saveLayer生成画布后,所有draw函数所生成的图像都是保存在这个新Bitmap中,只有调用resTore,resoreToCount函数后才会返回到原始画布上进行绘制。
Canvas是画布的表现形式,代码中只能通过newCanvas(bitmap)方式生成,可以把Canvas理解成绘图工具,由其函数所绘制的图像最终都是要画到bitmap上的。

保存画布
save()与saveLayer(),保存位置信息和大小信息,对应的flag为MATRIX_SAVE_FLAG,大小信息对应的是CLIP_SAVE_FLAG,可以在调用保存状态函数时候将对应的flag传入。
saveLayer会新建一块画布,后续所有操作都会在这块画布上进行。

恢复画布
restore()与restoreToCount(int count)
两者针对同一个画布栈操作,前者是将栈顶画布出栈,恢复画布状态,后者是一直将栈顶画布出栈直到传入的指定索引画布出栈。


Bitmap

Bitmap是位图,也就是一个个像素点构成的对象。
Android绘制流程中,我们通过重写onDraw方法获得canvas对象去将图像绘制到bitmap中,每个view绑定一个Bitmap,并利用这个Bitmap生成一个Canvas对象,即canvas中保存着一个Bitmap对象,所以该canvas绘制的图像能显示在view上。
总而言之,Bitmap有两种常用方式:

Bitmap bitmap = BitmapFactory.decodeResource(res,R.drawable.pdd);
        BitmapDrawable bitmapDrawable = new BitmapDrawable();
        View view;
        ImageView imageView = (ImageView) findViewById(id);
        imageView.setImageDrawable(bitmapDrawable);

1、Bitmap格式
用Bitmap.Config标识,推荐ARGB_8888,每个纬度站一个字节,一个像素占四个字节,最占内存同时最清晰

2、Bitmap的存储
在内存中:bitmap是代码生成,其占内存大小为:高宽每个像素占内存大小
在文件中:bitmap是通过压缩算法压缩过的,有不同的压缩格式:JPEG,PNG,WEBP,每种格式对应一种压缩算法。

3、Bitmap的生成

 BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = XXX;
        String pathName;
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.pdd,options);
        imagView.setInmageBitmap(bitmap);
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height);
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter);

4、Bitmap占用空间的计算
高度(px) * 宽度(px) * 每个像素点的字节数
Android系统会动态缩放bitmap对象。
缩放比例等于:屏幕分辨率/文件所在文件夹的分辨率
eg:xhdpi文件夹(适应480dpi)下原本100px*200px的图片,放在720dpi的真实屏幕下,生成的bitmap对象会被扩大为原来的1.5倍。
多生成的像素是利用类似于setDither的抗抖动算法,利用两个像素生成中间值像素进行填充。
缩小图片同理,减少像素即可,依据inSampleSize采样算法间隔取点即可缩小图片。

5、其他常用函数

if(bmp != null && !bmp.isRecycled()) {
    bmp.recycle();
    bitmap = null;
    system.gc() //提醒系统及时回收内存
}

6、bitmap、view、drawable、canvas关系
之前已经梳理了大半
canvas内部保存一个Bitmap,view中会新建一个canvas和bitmap,同样表明view也是通过bitmap呈现的,Drawable会利用外部传入的canvas来进行绘制,并且它自己不能保存这个canvas实例。

自定义style

values目录下定义自定义属性,对应自定义控件的布局文件中引用(加上命名空间)或者导入自定义的属性集让xml能够被系统识别,在自定义控件代码中以TypeArray获取对应自定义属性的值(系统无法使用,需要自己加操作方法)

上一篇下一篇

猜你喜欢

热点阅读