自定义View Bitmap与Drawable的区别

1.什么是Bitmap

Bitmap 是位图信息的存储,就是一个矩形图像每个像素的颜色信息的存储器。

2.什么是Drawable

2.1.Drawable是一种可以在Canvas上进行绘制的抽象的概念。Drawable 是一个可以调用Canvas来进行绘制的上层工具。Drawable.draw(canvas)可以将Drawable设置的绘制内容绘制到Canvas中。

2.2.Drawable的内部存储的是绘制规则,这个规则可以是一个具体的Bitmap,也可以是一个纯粹的颜色,甚至可以是一个抽象。灵活的描述。Drawable可以不含有具体的像素信息,只要它含有的信息足以在draw(canvas)方法中被调用时进行绘制就够了。也就是说,颜色、图片等都可以是一个Drawable

2.3.Drawable 可以通过XML定义,或者通过代码构建

2.4.Android 中 Drawable是一个抽象类,每个具体的Drawable都是其子类。

2.5.由于Drawable存储的只是绘制规则,因此他在draw()方法被调用前,需要先调用Drawable.setBounds()来为它设置绘制边界。

3.Drawable 优点

1.使用简单,比自定义View的成本低
2.非图片类的Drawable所占用空间小,能减小apk大小

4.Drawable 的内部宽高

    1.一般getIntrinsicWidth/Height 能获取内部宽/高
    2.图片Drawable其内部宽高就是图片的宽高
    3.颜色Drawable没有内部宽高的概念
    4.内部宽高不等同于他的大小,一般Drawable没有大小概念(作为View背景时,会被拉伸至View的大小)

Drawable的分类

image.png

5.BitmapDrawable 的作用和使用

表示一种图片,可以直接引用原始图片或者通过XML进行描述

<?xml version="1.0" encoding="utf-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@color/colorPrimary"
    android:antialias="true"
    android:dither="true"
    android:filter="true"
    android:gravity="center"
    android:mipMap="false"
    android:tileMode="disabled"
    />

6.Bitmap的属性

image.png

7.gravity属性详情

image.png

8.NinePathDrawable(.9图片)的作用

1.自动根据宽高进行缩放且不会失真。
2.实际使用,可以直接引用图片或者通过XML描述

<?xml version="1.0" encoding="utf-8"?>
<nine-patch
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@color/colorPrimary"
    android:antialias="true"
    android:dither="true"
    android:filter="true"
    android:gravity="center"
    android:mipMap="false"
    android:tileMode="disabled"
    />

9.ShapeDrawable的作用

1.通过颜色构造的图形
2.可以是纯色的图形
3.也可以是有渐变效果的图形
4.shape标签创建的Drawable实体是GradientDrawable

10.ShapeDrawable的使用

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

    <corners
        android:radius="10dp"
        android:topLeftRadius="10dp"
        android:topRightRadius="10dp"
        android:bottomLeftRadius="10dp"
        android:bottomRightRadius="10dp"/>
    <gradient
        android:angle="45"
        android:centerX="30"
        android:centerY="30"
        android:centerColor="@color/colorAccent"
        android:endColor="@color/colorPrimary"
        android:startColor="@color/colorPrimaryDark"
        android:gradientRadius="20"
        android:type="linear"
        android:useLevel="true" />
    <padding
        android:left="10dp"
        android:top="10dp"
        android:right="10dp"
        android:bottom="10dp" />
    <size
        android:width="200dp"
        android:height="200dp" />
    <solid
        android:color="@color/colorPrimary"/>
    <stroke
        android:width="10dp"
        android:color="@color/colorAccent"
        android:dashWidth="5dp"
        android:dashGap="3dp"/>

</shape>

11.ShapeDrawable的属性介绍

image.png

12.LayerDrawable的作用

1.XML标签为layer-list
2.层次化的Drawable集合
3.可以包含多个item,每个item表示一个Drawable
4.item中可以通过android:drawable直接引用资源
5.android:top等表示Drawable相当于View上下左右的偏移量

13.LayerDrawable的使用

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

    <item>
        <shape android:shape="rectangle">
            <solid
                android:color="#0ac39e"/>
        </shape>
    </item>

    <item
        android:bottom="6dp">
        <shape android:shape="rectangle">
            <solid
                android:color="#FFFFFF"/>
        </shape>
    </item>

    <item
        android:bottom="1dp"
        android:left="1dp"
        android:right="1dp">
        <shape android:shape="rectangle">
            <solid
                android:color="#FFFFFF"/>
        </shape>
    </item>

</layer-list>

14.StateListDrawable的作用

1.对应selector标签
2.用于View根据状态选择不同的Drawable

15.StateListDrawable 的使用和要点

<?xml version="1.0" encoding="utf-8"?>
<selector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:constantSize="false" //StateListDrawable的固有大小是否根据状态而改变,默认false=根据状态而改变
    android:dither="true"        //是否开启抖动-让高质量图片在低质量屏幕上依旧效果好,默认true开启
    android:variablePadding="false" //padding是否根据状态的改变而改变,不建议开启(false)
    >
    <item android:state_pressed="true"  //Button被按下后却没有松开的状态
        android:drawable="@color/colorAccent"/>
    <item android:state_focused="true"  //View获取了焦点
        android:drawable="@color/colorPrimary"/>
    <item android:state_selected="true" //用户选择了View
        android:drawable="@color/colorPrimary"/>
    <item android:state_checked="true" //用户选中了View,一般用于CheckBox这类在选中和没有选中状态之间切换的View
        android:drawable="@drawable/ic_launcher_background"/>
    <item android:state_enabled="true" //View处于可用状态
        android:drawable="@drawable/ic_launcher_foreground"/>
    <item android:drawable="#FFFFFF"/> //默认Drawable: 按顺序向下匹配,需要放在最下方,因为可以匹配任何状态
</selector>

16.LevelListDrawable的作用

1.对应level-list标签
2.拥有多个item,每个item都有maxLevel和minLevel
3.Level的范围0~10000
4.给定level后,会按从上至下的顺序匹配,直到找到范围合适的Drawable,并返回
5.item的level一定要降序或者升序
6.调用View的getBackground获得Drawable对象,并调用setLevel设置等级Level
7.ImageView的setImageLevel()能快速指定src引用的Drawable的Level
8.LevelListDrawable是根据level改变,选择不同的Drawable,能用于实现进度条,音量调节。

17.LevelIstDrawable的使用

<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:minLevel="0" android:maxLevel="10" android:drawable="@drawable/d1" />
    <item android:minLevel="11" android:maxLevel="20" android:drawable="@drawable/d2" />
    <item android:minLevel="21" android:maxLevel="30" android:drawable="@drawable/d3" />
    <item android:minLevel="31" android:maxLevel="40" android:drawable="@drawable/d4" />
</level-list>

18.TransitionDrawable的作用

1.对应于transition标签
2.实现两个Drawable之前的淡入淡出效果
3.获得背景的TransitionDrawable后,通过startTransition和reverseTransition方法实现效果和逆过程。

19.TransitionDrawable的使用

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/transition_drawable"
        android:drawable="@drawable/ic_launcher"
        android:top="10dp"    //四周的偏移量
        android:bottom="10dp"
        android:right="10dp"
        android:left="10dp"/>
    <item android:drawable="@drawable/ic_launcher_round" />
</transition>

20.InsetDrawable的作用和使用

1.对应inset标签
2.将其他Drawable内嵌到自身,并在四周留出间距
3.View需要背景比自己实际区域要小的时候,可以使用inset,layer-list也可以实现该需求
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_launcher"
    android:insetTop="10dp"
    android:insetBottom="10dp"
    android:insetLeft="10dp"
    android:insetRight="10dp">
</inset>

21.ScaleDrawable的作用

1.对应于scale标签
2.根据自己的等级level(0~10000)将指定的Drawable缩放到一定比例
3.android:scaleHeight="70%"用于指定宽高的缩放比例=为原来的30%
4.ScaleDrawable的level为0,不可见。为10000时,不缩放。
5.一般将level设置为1,就会按照属性指定的比例缩放。其他值也会改变缩放效果。
6.android:scaleGravity属性和gravity属性完全一致

22.ScaleDrawable的使用

<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_launcher"
    android:scaleGravity="center"
    android:scaleHeight="70%"
    android:scaleWidth="70%">
</scale>

23.ClipDrawable的作用

1.对应于clip标签
2.根据自己当前的等级level(0~10000)来裁剪另一个Drawable
3.裁剪方向由clipOrientation和gravity属性共同控制
4.level为0,Drawable不可见;10000表示不裁剪;为8000,表示裁减了2000;为1,表示裁剪了9999

24.ClipDrawable的gravity

image.png

25.AnimationDrawable的作用

1.对应于animation-list标签
2.用于实现逐帧动画效果
3.android:oneShot决定是循环播放还是播放一次,false:循环播放
4.item中设置一帧一帧的Drawable以及持续时间
5.AnimationDrawable的setOneShot(boolean flag) 和android:oneShot配置一样
6.addFrame (Drawable frame, int duration) 动态的添加一个图片进入该动画中
7.stop()和start()用于停止和开始/继续播放,停止时会停留在当前一帧上

26.AnimationDrawable的使用

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:drawable="@drawable/shake_anim_01" android:duration="100"/>
    <item android:drawable="@drawable/shake_anim_02" android:duration="100"/>
    <item android:drawable="@drawable/shake_anim_03" android:duration="100"/>
    <item android:drawable="@drawable/shake_anim_04" android:duration="100"/>
    <item android:drawable="@drawable/shake_anim_05" android:duration="100"/>
    <item android:drawable="@drawable/shake_anim_06" android:duration="100"/>
    <item android:drawable="@drawable/shake_anim_07" android:duration="100"/>
    <item android:drawable="@drawable/shake_anim_08" android:duration="100"/>
    <item android:drawable="@drawable/shake_anim_09" android:duration="100"/>
    <item android:drawable="@drawable/shake_anim_10" android:duration="100"/>
</animation-list>

val imageview = findViewById<ImageView>(R.id.imaview)
(imageview.drawable as AnimationDrawable).start() //开始播放

27.ShapeDrawable的OvalShape、RectShape、ArcShape和PaintDrawable的作用和使用

1.用于获得有shape形状的drawable(椭圆、长方形、扇形以及更为通用PaintDrawable-具有圆角和边界)

    /**===================================================
     *  一个继承自ShapeDrawable更为通用的Drawable:具有圆角
     *====================================================*/
    PaintDrawable drawable3 = new PaintDrawable(Color.GREEN);
    drawable3.setCornerRadius(30);
    findViewById(R.id.textView3).setBackgroundDrawable(drawable3);

    /**============================================
     *   通过Shape构造出相应的ShapeDrawable
     *=============================================*/
    //椭圆形形状 : shape赋予ShapeDrawable
    OvalShape ovalShape = new OvalShape();
    ShapeDrawable drawable1 = new ShapeDrawable(ovalShape);
    drawable1.getPaint().setColor(Color.BLUE);
    drawable1.getPaint().setStyle(Paint.Style.FILL);
    findViewById(R.id.textView1).setBackgroundDrawable(drawable1);

    //矩形形状  : shape赋予ShapeDrawable
    RectShape rectShape = new RectShape();
    ShapeDrawable drawable2 = new ShapeDrawable(rectShape);
    drawable2.getPaint().setColor(Color.RED);
    drawable2.getPaint().setStyle(Paint.Style.FILL);
    findViewById(R.id.textView2).setBackgroundDrawable(drawable2);

    //扇形、扇面形状 : shape赋予ShapeDrawable
    //顺时针,开始角度30, 扫描的弧度跨度180
    ArcShape arcShape = new ArcShape(30, 180);
    ShapeDrawable drawable4 = new ShapeDrawable(arcShape);
    drawable4.getPaint().setColor(Color.YELLOW);
    drawable4.getPaint().setStyle(Paint.Style.FILL);
    findViewById(R.id.textView4).setBackgroundDrawable(drawable4);

28 其余Drawable

image.png

自定义Drawable

29.自定义Drabale

1.一般作为ImageView的图像来显示
2.另一个是作为View的背景
3.自定义Drawable主要就是实现draw方法
4.setAlpha、setColorFilter、getOpacity也需要重写,但是模板固定
5.当自定义Drawable有固定大小时(比如绘制一张图片),需要重写6.getIntrinsicWidth()/getIntrinsicHeight()方法(默认返回-1),会影响到View的wrap_content布局
7.内部固定大小不等于Drawable的实际区域大小,getBounds能获得实际区域大小

注:自定义Drawable无法在XML中使用

SVG矢量图

30.SVG概念

1.可伸缩矢量图(Android 5.0推出)
2.定义用于网络的基于矢量的图形(在Web上应用非常广泛)
3. 使用XML格式定义图形
4.图像缩放不会影响质量
5.万维网联盟标准(与DOM和XSL之类的W3C标准是一个整体)

31、SVG和Bitmap区别

1. SVG是一个绘图标准。
2. Bitmap是通过每个像素点上存储色彩信息来表示图像。
3. SVG放大不会失真, Bitmap会失真。
4. Bitmap需要为不同分辨率设计多套图表,SVG绘制一张图就能适配不同分辨率。

32、静态矢量图SVG-VectorDrawable

1. 基于XML的静态矢量图
2. 采用标签vector
3. vector中path是最小单位,创建SVG-用指令绘制SVG图形
4. vector中group将不同path组合起来

33、VectorDrawable的vector标签有哪些属性

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="200dp"  // SVG的具体大小
    android:height="200dp"
    android:viewportWidth="100" //将宽度分为多少份,与path配合(50份等于100dp)
    android:viewportHeight="100">
    <group>   //将不同`path`组合起来
        <path    //SVG树形结构的最小单位,用指令绘制SVG图形
            android:name="path1" //该path的名称
            android:pathData="M 20,80 L 50,80 80,80"
            android:strokeColor="@color/colorAccent"
            android:strokeWidth="3"
            android:strokeLineCap="round"/>
        <path
            .../>
    </group>
</vector>

34 VectorDrawable的path标签的全部指令

image.png
1.坐标轴以(0, 0)为中心, X轴水平向右, Y轴水平向下
2.指令大写-绝对定位,参考全局坐标系;指令小写-相对定位,参考父容器坐标系
3.指令和数据间空格可以省略
4.同一指令出现多次,可以只用一个。
5.A的参数:RX/RY:椭圆半轴大小 XROTATION:椭圆X轴与水平方向顺时针方向夹角 FLAG1:1-大角度弧线 0-小角度弧线 FLAG2:起点到终点的方向,1-顺时针,2-逆时针 X/Y:终点坐标

35 VectorDrawable的实例

//1. 使用`vector`标签定义矢量图VectorDrawable(ic_black_24dp.xml)
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
        <group
           android:name="test"> //该组的名称:可以在AnimatedVectorDrawable中指定动画效果
           <path
              android:fillColor="#FF000000"
              android:pathData="M12,6c1.11,0 2,-0.9 2,-2 0,-0.38 -0.1,-0.73 -0.29,-1.03L12,0l-1.71,2.97c-0.19,0.3 -0.29,0.65 -0.29,1.03 0,1.1 0.9,2 2,2zM16.6,15.99l-1.07,-1.07 -1.08,1.07c-1.3,1.3 -3.58,1.31 -4.89,0l-1.07,-1.07 -1.09,1.07C6.75,16.64 5.88,17 4.96,17c-0.73,0 -1.4,-0.23 -1.96,-0.61L3,21c0,0.55 0.45,1 1,1h16c0.55,0 1,-0.45 1,-1v-4.61c-0.56,0.38 -1.23,0.61 -1.96,0.61 -0.92,0 -1.79,-0.36 -2.44,-1.01zM18,9h-5L13,7h-2v2L6,9c-1.66,0 -3,1.34 -3,3v1.54c0,1.08 0.88,1.96 1.96,1.96 0.52,0 1.02,-0.2 1.38,-0.57l2.14,-2.13 2.13,2.13c0.74,0.74 2.03,0.74 2.77,0l2.14,-2.13 2.13,2.13c0.37,0.37 0.86,0.57 1.38,0.57 1.08,0 1.96,-0.88 1.96,-1.96L20.99,12C21,10.34 19.66,9 18,9z"/>
        </group>
</vector>
//2. 使用矢量图
<ImageView
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:src="@drawable/ic_black_24dp"/>

36 矢量图动画-AnimatedVectorDrawable

针对静态矢量图-VectorDrawable来做动画
xml标签为animated-vector
在target子标签下指明VectorDrawable的名字(都是android:name="..."属性指明),并指定动画效果android:animation="@animator/..."

37 AnimatedVectorDrawable实例

//1. 静态矢量图-VectorDrawable(vector_two_line.xml)
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="200dp"
    android:height="200dp"
    android:viewportWidth="100"
    android:viewportHeight="100">
    <group>
        <path
            android:name="path1" //路径1的名称
            android:pathData="M 20,80 L 50,80 80,80"
            android:strokeColor="@color/colorAccent"
            android:strokeWidth="3"
            android:strokeLineCap="round"/>
        <path
            android:name="path2" //路径2的名称
            android:pathData="M 20,20 L 50,20 80,20"
            android:strokeColor="@color/colorAccent"
            android:strokeWidth="3"
            android:strokeLineCap="round"/>
    </group>
</vector>

//2. 轨迹动画效果-属性动画ObjectAnimator(res/animator/trimpath_animator)
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:propertyName="trimPathEnd"
    android:valueFrom="0"
    android:valueTo="1"
    android:valueType="floatType"
    android:interpolator="@android:interpolator/accelerate_decelerate">
</objectAnimator>

//3. 粘合静态SVG和属性动画:AnimatedVectorDrawable(vector_trimpath_anim.xml)
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vector_two_line"> //静态SVG
   <target
       android:animation="@animator/trimpath_animator" //属性动画
       android:name="path1"> //静态SVG中路径1的名称
   </target>
   <target
       android:animation="@animator/trimpath_animator" //属性动画
       android:name="path2"> //静态SVG中路径2的名称
   </target>
</animated-vector>

//4. 布局中使用AnimatedVectorDrawable
<ImageView
            android:id="@+id/trimpath_anim_imageview"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:src="@drawable/vector_trimpath_anim"/> //动画矢量图

代码中开启动画
    ImageView imageView = (ImageView) findViewById(R.id.trimpath_anim_imageview);
    ((Animatable)imageView.getDrawable()).start();
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容