查看原文
其他

这次来把Drawable翻了个遍

积木zz 码上积木 2022-08-26

前言

说到Drawable,大家肯定都很熟悉,这不就是那个那个那个。。哪个?那个表示图片的东西吗?

遇到这种概念性问题,有的小伙伴可能跟我一样就有点蒙了,用是每天用,但真要我解释还真不好说,那么今天就来一起揭开的它的神秘面纱吧~

Drawable是什么

Drawable表示的是一种可以在Canvas上进行绘制的抽象的概念,种类很多,最常见的颜色和图片都可以是一个Drawable。

所以他是一种抽象的概念,是表示一种图像,但是又不全是图片,也可以表示颜色,一般被用作View的背景或者填充图。

到这里有的小伙伴可能又要问了,Canvas又是什么呢?

Canvas一个矩形区域, 没有边界, 我们可以在上面调用任意drawXXX开头的方法绘制到引用的Bitmap上. 同时提供对图形的处理, 比如裁剪, 缩放, 旋转(需要Matrix对象配合使用). 所以Canvas与其说是画布, 不如说是一个绘制工具,它实际操作和存储的像素数据都在它的私有成员 Bitmap 对象中,所谓的画到Canvas画布上,其实就是画到其Bitmap,存储到其Bitmap变量中。

说到这,又要提下Bitmap了:

Bitmap是一个存储格式, 存储了一个矩形区域内各像素点的信息. 这种格式适合显示, 但是存储效率低.可以理解为int[] buffer,用来保存每个像素的信息。

所以这三者的关系简单点就是:

Drawable表示一个可以被绘制的图像,是一个抽象概念,需要通过Canvas绘制到Bitmap上,作为一个图像的存储。所以Bitmap是Drawable存在的一种实体。

Drawable分类

Drawable的种类很多,这里列举几个比较常用的以及用法:

  • BitmapDrawablw 最常用的Drawable,表示的就是一张图片,一张带规则的图片,可以设置一些规则,比较适用于对图片有限制的情况,比如背景图。
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="clip_horizontal|clip_vertical"
    android:dither="true"
    android:src="@drawable/start_bg"
    android:tileMode="disabled"/>
    <!--属性解释-->
    <!--android:src 图片资源id-->
    <!--android:antialias是否开启抗锯齿,开启后会更平滑,应该开启-->
    <!--android:dither是否开启抖动效果,可以让高质量的图片在低质量的屏幕中还能保持较好的显示效果,应该开启-->
    <!--android:filter是否开启过滤效果,应该开启-->
    <!--android:gravity 当图片小于容器尺寸,可以设置图片定位,也就是图片的显示方式,和ImageVIew的scaleType类似,默认为fill-->
    <!--android:mipMap纹理映射,一般为false-->
    <!--android:tileMode平铺模式四个值:disabled(默认值即关闭平铺模式)、clamp、repeat、mirror-->

  • NinePatchDrawable 和BitmapDrawablw类似,使用时src传.9图片即可。实际上BitmapDrawablw也可以直接用.9图片,所以这个NinePatchDrawable没有太大的实际作用。

  • ShapeDrawable 这个很常见,一般纯颜色的图形就用这个画出来。

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape=["rectangle" | "oval" | "line" | "ring"] >

    
<!-- 表示四个角的角度,圆角的程度。   -->    
    <corners
        android:radius="integer"
        android:topLeftRadius="integer"
        android:topRightRadius="integer"
        android:bottomLeftRadius="integer"
        android:bottomRightRadius="integer" />

        
<!-- 表示渐变效果,和solid互斥   -->        
    <gradient
        android:angle="integer"
        android:centerX="float"
        android:centerY="float"
        android:centerColor="integer"
        android:endColor="color"
        android:gradientRadius="integer"
        android:startColor="color"
        android:type=["linear" | "radial" | "sweep"]
        android:useLevel=["true" | "false"] />

        
<!-- 表示包含它的View的空白。  -->        
    <padding
        android:left="integer"
        android:top="integer"
        android:right="integer"
        android:bottom="integer" />

        
<!-- 表示shape的大小 -->
    <size
        android:width="integer"
        android:height="integer" />

        
<!-- 表示填充颜色 -->
    <solid
        android:color="color" />

        
<!-- 表示描边 -->       
    <stroke
        android:width="integer"
        android:color="color"
        android:dashWidth="integer"
        android:dashGap="integer" />

</shape>
  • LayerDrawable

这是一种层次化的Drawable,相当于一种Drawable的布局嵌套,或者说集合,通过不同的Drawable放置到不同的层上达到一种叠加后的效果。

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item>
        <shape>
            <solid android:color="" />
        </shape>
    </item>

    <item>
        <bitmap android:src="@drawable/test" />
    </item>
</layer-list>
  • StateListDrawble

一般用作点击效果,对应标签是selector,可以设置按下,点击后,不点击时候的各种状态。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="true" android:drawable="@drawable/test1">
    </item>

    <item android:state_enabled="false" 
    android:drawable="@drawable/test2">

    </item>
</selector>

  • LevelListDrawable 和LayerDrawable类似,也是一个Drawable的集合,但是他是有等级的概念的,也就是可以通过设置不同的等级来展示对应的drawable,有点像一个有多种样式的Drawable,可以通过代码来展示哪一个样式。
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/test1" android:maxLevel="0"/>
    <item android:drawable="@drawable/test" android:maxLevel="1"/>
</level-list>

可以通过ImageView的setImageLevel方法来切换Drawable。

  • TransitionDrawable

该Drawable可以实现两个Drawable之间的淡入淡出,对应的标签是transition。

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/test1"/>
    <item android:drawable="@drawable/test2"/>
</transition>

可以通过代码中进行动画切换:

TransitionDrawable drawable = (TransitionDrawable) iv.getDrawable();
//切换到第2个item
drawable.startTransition(1000);
//切回到第1个item
drawable.reverseTransition(1000);
  • InsetDrawable 可以将其他的Drawable内嵌到自己当中,当一个View希望自己的背景比自己的实际区域小的时候,就可以采用这个,通过LayerDrawable也可以实现。一般用作加大点击区域。
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/onepiece"
    android:insetBottom="20dp"
    android:insetLeft="20dp"
    android:insetRight="20dp"
    android:insetTop="20dp">

</inset>

  • ScaleDrawable

用于缩放,并且和它的等级Level有关,等级为0则不可见。

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/image"
    android:scaleGravity="center_vertical|center_horizontal"
    android:scaleHeight="50%"
    android:scaleWidth="50%" />

使用的时候必须设置等级:

ScaleDrawable drawable = (ScaleDrawable) imageview.getDrawable();
drawable.setLevel(1);
  • ClipDrawable 用作裁剪,会根据自己的等级来裁剪一个Drawable,等级0表示完全裁剪,即整个Drawable都不可见,等级10000表示不裁剪,所以主要是通过控制drawable的等级来完成裁剪功能:
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/test"/>

</clip>
double scale = progress/max;
ClipDrawable drawable = (ClipDrawable) mImageShow.getBackground();
drawable.setLevel((int) (10000*scale));

参考

《Android开发艺术探索》 https://juejin.cn/post/6844903775153422343

拜拜

今天介绍了Drawable的概念,与其他绘制图类的关系,以及它的主要分类,内容还是比较简单,主要带大伙做一个回顾总结,巩固知识。晚安~


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存