美文网首页
View绘制相关

View绘制相关

作者: LeoFranz | 来源:发表于2019-08-22 17:29 被阅读0次

    • 硬件加速和软件加速的区别
    • Canvas与图层
    • Bitmap
    • 自定义style

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

    硬件加速是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有两种常用方式:

    • 通过转化成BitmapDrawbale对象然后转化成Drawable对象作为图像资源使用
    Bitmap bitmap = BitmapFactory.decodeResource(res,R.drawable.pdd);
            BitmapDrawable bitmapDrawable = new BitmapDrawable();
            View view;
            ImageView imageView = (ImageView) findViewById(id);
            imageView.setImageDrawable(bitmapDrawable);
    
    • 通过绑定Canvas对象用于绘制图像——当做画布
      可以通过onDraw,onDispatchDraw方法获得canvas对象然后绘制Bitmap,或者通过new Canvas(bitmap)等方式自建画布。

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

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

    3、Bitmap的生成

    • BitmapFactory生成,
      该类可以通过资源,文件,字节数组,FileDescriptor和InputStream等生成Bitmap对象
      BitmapFactory.Options可以设置图片的采样率,在不加载图片的前提下获得图片的尺寸信息,通过改变图片的高、宽、缩放比例、是否缩放、像素存储格式等能减少图片像素,实际开发中可以利用该值降低OOM的发生概率。
     BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = XXX;
            String pathName;
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.pdd,options);
            imagView.setInmageBitmap(bitmap);
    
    • 利用静态方法构建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采样算法间隔取点即可缩小图片。

    • 屏幕分辨率和资源文件夹分辨率适配时候,不会缩放图片;
    • 从SD卡等非apk内存获取图片时,不会对图片进行缩放。

    5、其他常用函数

    • getAllocationByteCount();获取生成的Bitmap的分配空间大小
    • recycle()强制回收Bitmap所占用的内存。——Bitmap本身和像素数据都存储在Dalvik堆中。能够被java虚拟机回收。
      isRecycle()判断是否已经回收。
      在API11以后可以不强制使用回收函数,由GC机制自动处理即可,但如果有大量Bitmap等待GC时候,可能出现卡顿,所以必要时候需要手动回收内存,一般编码如下:
    if(bmp != null && !bmp.isRecycled()) {
        bmp.recycle();
        bitmap = null;
        system.gc() //提醒系统及时回收内存
    }
    
    • compress()压缩Bitmap
      compress(CompressFormat format, int quality, OutputStream stream)
      三种压缩格式JPEG,PNG,WEBP,会将bitmap压缩后写入指定的输入流中

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

    自定义style

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

    相关文章

      网友评论

          本文标题:View绘制相关

          本文链接:https://www.haomeiwen.com/subject/hsensctx.html