Android中Drawable的分类

Drawable 的分类

1 BitmapDrawable:

BitmapDrawable算是最常见的Drawable之一,我们构造一个Bitmap对象的时候,有时候会用到BitmapDrawable,那么BitmapDrawable的构造,除了在代码中new一个BitmaDrawable之外,我们还可以使用XML来构造一个BitmapDrawable对象,在项目的drawable文件中新创建一个xml文件,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:antialias="true"
    android:dither="true"
    android:filter="true"
    android:gravity="center"
    android:mipMap="true"
    android:src="drawable/xmyh"
    android:tileMode="clamp">
</bitmap>
  • android:src
    这个是资源,可以是图片也可以是颜色

  • android:antialias
    是否开启图片抗锯齿,开启后图片会变得平滑一点,同时也会在一定程度上降低清晰度,不过这个降低我们完全可以无视,所以这个可以开启

  • android:dither
    是否开启抖动效果,当图片的像素配置和手机不一致的时候,开启这个选项可以让高质量的图片在低分辨率的屏幕上保持比较好的显示效果,比如图片的色彩模式ARGB8888,但是设备只支持RGB555,这个时候开启抖动模式可以让图片不会过于失真,在Android中创建的Bitmap一般会使用ARGB8888这个模式,即ARGB四个通道各占8位,在这个色彩下,一个像素所占为4个字节,一个像素的位数综合越高,图片越逼真,抖动也应该开启。

  • android:gravity,可以选项比较多,不同的选项可以取值可以荣国 “ | ”组合使用可以取值

可选项含义
top将图片放在容器顶部,不改变图片大小
bottom将图片放在容器底部,不改变图片大小
left将图片放在容器左侧,不改变图片大小
right将图片放在容器右侧,不改变图片大小
center_vertical是图片垂直居中,不改变图片大小
fill_vertical图片垂直方向填充容器
center_horizontal图片水平居中,不改变图片大小
fill_horizontal图片水平方向填充容器
center图片在水平和竖直方向同时居中 ,不改变图片大小
fill图片在水平和竖直方向均填充容器,默认值
clip_vertical竖直方向裁剪,较少使用
clip_horizontal水平方向裁剪,较少使用
  • android:mipMap
    这是一种图片相关的处理技术,也叫纹理映射,比较抽象,默认为false,不常用
  • android:filter
    是否开启过滤效果,当图片尺寸被拉伸或者压缩时,开启过滤效果会保持比较好的显示效果,所以这个也可开启。
  • android:tileMode
    平铺模式,有四种选项[“disabled” | “clamp” | “repeat” | “mirror”]。当开启平铺模式后,gravity属性会被忽略。repeat是指水平和竖直方向上的平铺效果;mirror是指在水平和竖直方向上的镜面投影效果;clamp是指图片四周的像素会扩展到周围区域,这个比较特别。
    demo

还有.9图片的使用

<?xml version="1.0" encoding="utf-8"?>
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
    android:dither="true"
    android:src="@drawable/nine_pic">
</nine-patch>

.9图片的使用大多在可拉伸图片的场景下使用。例如微信聊天的文字背景,语音背景就是简单地例子。

2 ShapeDrawable

ShapeDrawable主要用来画一些 shape,和各种颜色。语法比较多。

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

    <corners
        android:bottomLeftRadius="10dp"
        android:bottomRightRadius="10dp"
        android:radius="10dp"
        android:topLeftRadius="10dp"
        android:topRightRadius="10dp" />

    <gradient
        android:angle="10"
        android:centerColor="@color/colorPrimary"
        android:centerX="10"
        android:centerY="10"
        android:endColor="@color/colorPrimary"
        android:gradientRadius="10dp"
        android:startColor="@color/colorAccent"
        android:type="linear"
        android:useLevel="true" />

    <padding
        android:bottom="10dp"
        android:left="10dp"
        android:right="10dp"
        android:top="10dp" />

    <size
        android:width="100dp"
        android:height="100dp" />

    <solid android:color="@color/colorAccent" />

    <stroke
        android:width="100dp"
        android:color="@color/colorPrimaryDark"
        android:dashGap="@dimen/activity_horizontal_margin"
        android:dashWidth="10dp" />

</shape>
  • android:shape
    表示图片的形状,有四个选项,line(横线),oval(椭圆),rectangle(矩形),ring(圆环),他的默认值是矩形,而且line(横线)和ring(圆环)都必须通过stroke标签来指定宽高,颜色等信息,否则无法达到预期的效果

  • 针对ring的形状,有五个特殊的属性

  1. android:innerRadius
  2. android:tickness
  3. android:innerRadiusRatio
  4. android:ticknessRatio
  5. android:useLevel
value含义
android:innerRadius圆环的内半径,和 android:innerRadiusRatio同时存在时候以 前者为准
android:tickness圆环厚度,即外半径减去内半径,android:innerRadiusRatio同时存在时候以 前者为准
android:innerRadiusRatio内半径占整个drawable的比例 ,默认为9,如果为n,内半径=宽度/n
android:ticknessRatio厚度占整个宽度的比例,默认为3,如果为n,厚度=宽度/n
android:useLevel一般使用false,除非被当做LeveListDrawable 使用
  • 表示shape的四个角度,它只是用于矩形的shape,这里的角度是指圆角的成都,用px来表示,他有五个属性

    android:radius:为四个角同时设置相同的角度,优先级较低,会被其他四个覆盖
    android:topLeftRadius:设置最上角的角度
    android:topRightRadius:设置右上角的角度
    android:bottomLeftRadius:设置最下角的角度
    android:bottomRightRadius:设置右下角的角度

  • < gradient>

    他与solid标签是互相排斥的,因为solid表示纯色,而他表示渐变,属性如下

    android:angle:渐变的角度,默认为0,其值必须为45的倍数,0表示从左往右,90表示从上到下
    android:centerColor:渐变的中心颜色
    android:centerX:渐变中心点的横坐标
    android:centerY:渐变中心点的纵坐标
    android:endColor:渐变的结束颜色
    android:gradientRadius:渐变半径,只有当type = radial 时才有效
    android:startColor:渐变的开始颜色
    android:type:渐变的类型 (linear–线性、radial–径向渐变、sweep–扫描渐变,线性渐变默认)
    android:useLevel:false

  • < solid>
    这个标签表示纯色填充,通过android:color来表示填充颜色

  • shape的描边
    android:width:宽度
    android:color:颜色
    android:dashwidth:虚线线段的宽度
    android:dashGap:组成虚线的线段之间的间隔
    注意:如果android:dashGapandroid:dashwidth有任何一个为0的话,那么虚线就不能生效了

  • < padding>
    这个表示空白,但是他表示的不是shape的空白,而是包含他view的空白,而且有四个属性
    android:left
    android:right
    android:top
    android:bottom
    类似View 的padding

  • < size>
    shape的大小,有两个属性,android:widthandroid:height 分别表示shape的宽和高。但是作为背景的时候,会被拉伸或者缩放为View 的宽和高。

整体的看一些例子


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="line">
    <stroke
        android:width="4dp"
        android:color="@android:color/holo_red_light"
        android:dashGap="4dp"
        android:dashWidth="4dp" />
</shape>

line


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <stroke
        android:width="4dp"
        android:color="@android:color/holo_red_light"
        android:dashGap="4dp"
        android:dashWidth="4dp" />
</shape>

rectangle


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <stroke
        android:width="4dp"
        android:color="@android:color/holo_red_light" />
    <corners
        android:radius="20dp" />
</shape>

re


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="ring"
    android:innerRadius="10dp"
    android:thickness="20dp"
    android:useLevel="false">
    <stroke
        android:color="@android:color/holo_red_light"
        android:width="4dp"
        />
</shape>

ring


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="ring"
    android:innerRadius="10dp"
    android:thickness="50dp"
    android:useLevel="false">

    <stroke
        android:width="0dp"
        android:color="@android:color/holo_red_light"
        />

    <gradient
        android:type="sweep"
        android:startColor="@android:color/holo_red_light"
        android:endColor="@android:color/holo_blue_bright"
        />
</shape>

ringsweep

具体看需求

  • 3 LayerDrawable

    LayerDrawable对应的xml是<layer-list>,他可以理解为图层,通过不同的view达到叠加的效果
    属性很简单,一个layer-list包含多个item,形成叠加的图层效果,我们可以看一个例子

    <?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="#f00" />
            </shape>
        </item>
    
        <item android:bottom="111dp">
            <shape android:shape="rectangle">
                <solid android:color="#fff" />
            </shape>
        </item>
    
        <item
            android:bottom="1dp"
            android:left="1dp"
            android:right="1dp">
            <shape android:shape="rectangle">
                <solid android:color="#fff"/>
            </shape>
        </item>
    </layer-list>
    

    demo

  • 4 StateListDrawable

    StateListDrawable对应的是<selector>标签,他会根据view的状态来选择出现的drawable,语法如下

    <?xml version="1.0" encoding="utf-8"?>
    <selector 
        xmlns:android="http://schemas.android.com/apk/res/android" 
        android:constantSize="true" 
        android:dither="true" 
        android:variablePadding="true">
    
        <item
            android:drawable="@drawable/ic_launcher"
            android:state_pressed="true"
            android:state_focused="true"
            android:state_hovered="true"
            android:state_selected="true"
            android:state_checkable="true"
            android:state_checked="true"
            android:state_enabled="true"
            android:state_activated="true"
            android:state_window_focused="true" />
    </selector>
    
    • android:constantSize
      StateListDrawable的固有大小是不随其状态的改变发生改变的,因为状态的改变会导致他切换不同的drawable,而不同的drawable具有不同的drawable,true表示StateListDrawable的固有大小不变,这时他的固有大小就是内部所有drawable的固有大小的最大值,false则是跟随状态改变,默认false

    • android:dither
      是否开启抖动效果,这个在之前就已经提过,开启此选项可以让图片在低质量的屏幕上显示较好的效果,默认为true

    • android:variablePadding
      StateListDrawablepading是跟随其状态发生改变的而改变,fasle为最大值,跟constantSize类似,不建议开启,默认false

      <item>标签标示的是一个具体的Drawable,他的结构也比较简单,其中drawable标示已经资源的id,剩下的就是各种状态了:

      含义
      roid:state_pressed
      roid:state_focused
      roid:state_selected
      roid:state_checked
      roid:state_enabled
      roid:state_hovered
      roid:state_checkable
      roid:state_activated
      roid:state_window_focused

    来看一个例子吧:

      ```
      <?xml version="1.0" encoding="utf-8"?>
      <selector xmlns:android="http://schemas.android.com/apk/res/android"
          android:constantSize="false"
          android:dither="true"
          android:variablePadding="true">
      
          <item android:drawable="@color/gray" android:state_pressed="true" /><!--press-->
          <item android:drawable="@color/white" /> <!--normal-->
      </selector>
      	```
    

    drawable
    图片按下去的时候是另外一种状态,背景颜色会发生改变,这就是所谓的背景选择器,大多用在按钮。当然也可以给其他空间来定义属于它们的漂亮的选择器

  • 5 LevelListDrawable

    LevenlListDrawable对应着标签,同样表示一个drawable的集合。集合中的每一个Drawable都有一个等级,根据不同的等级切换不同的Item

    <?xml version="1.0" encoding="utf-8"?>
    <level-list
    	    xmlns:android="http://schemas.android.com/apk/res/android" >
    	    <item
    	        android:drawable="@color/red"
    	        android:maxLevel="1" />
    	    <item
    	        android:drawable="@color/orange"
    	        android:maxLevel="2" />
    	    <item
    	        android:drawable="@color/green"
    	        android:maxLevel="3" />
    </level-list>
    

    这样的等级在我们的APP 中还是很常见的比如:输入密码的时候等级检测旁边就会显示不同颜色的密码等级;在五星好评也可以使用这种思路来做(LayerDrawable 和 此LevenlListDrawable相结合)。

  • 6 TransitionDrawable

    TransitionDrawable对应的是用于实现两个Drawable的淡入淡出语法如下:
    <?xml version="1.0" encoding="utf-8"?> <transition xmlns:android="http://schemas.android.com/apk/res/android"> <item android:bottom="@dimen/activity_horizontal_margin" android:drawable="@color/colorAccent" android:left="@dimen/activity_horizontal_margin" android:right="@dimen/activity_horizontal_margin" android:top="@dimen/activity_horizontal_margin" /> </transition>
    android:bottom android:left android:right android:top 对应着drawable 在对应方向上面的margin。
    大多数用于Viewdrawable 属性,图片的淡入淡出效果,如下
    <?xml version="1.0" encoding="utf-8"?> <transition xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/colorAccent" /> <item android:drawable="@color/colorPrimary" /> </transition>
    接着将上面的设置为View的背景,最后通过startTransition和resetTransition来操作
    TransitionDrawable drawable = (TransitionDrawable) view.getBackground(); drawable.startTransition(1000);

  • 7 InsetDrawable

    InsetDrawable对应的是,他可以将其他的Drawable内嵌到自己当中,并且可以在四周留下一定的距离

    <?xml version="1.0" encoding="utf-8"?>
    <inset xmlns:android="http://schemas.android.com/apk/res/android"
        android:insetBottom="60dp"
        android:drawable="@color/red"
        android:insetLeft="30dp"
        android:insetRight="30dp"
        android:insetTop="60dp" >
    </inset>
    
  • 8 ScaleDrawable

    ScaleDrawable对应的是,他可以指定自己的等级将指定的Drawable缩放带一定的比例,语法如下

    <?xml version="1.0" encoding="utf-8"?>
    <scale xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@mipmap/ic_launcher"
        android:scaleGravity="center"
        android:scaleHeight="10%"
        android:scaleWidth="50%">
    </scale>
    

    在上门的属性中,scaleGravity的含义等同于shape中的gravity,而这个宽高就是缩放比例,以百分比的形式
    android:scaleHeight 的百分比越大图片上线高度就比较低,值越小,上线拉伸的高度越高。注意:在使用的时候还要配合这个代码

    ImageView view = (ImageView) findViewById(R.id.imgView);
    ScaleDrawable drawable = (ScaleDrawable) view.getDrawable();
    drawable.setLevel(1); //	这个数值小于10000就好
    

    因为这个 ScaleDrawable 源码中有这么一段代码

    @Override
    public void draw(Canvas canvas) {
        final Drawable d = getDrawable();
        if (d != null && d.getLevel() != 0) {
            d.draw(canvas);
        }
    }
    
  • 9 ClipDrawable

    ClipDrawable对应的是<clip>标签,他可以根据自己的等级裁剪另一个Drawable,裁剪的方法可以通过android:clipOrientationandroid:gravity 来共同控制,先看下语法

    <?xml version="1.0" encoding="utf-8"?>
     <clip
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:drawable="@drawable/drawable_resource"
     android:clipOrientation=["horizontal" | "vertical"]
     android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
                      "fill_vertical" | "center_horizontal" | "fill_horizontal" |
                      "center" | "fill" | "clip_vertical" | "clip_horizontal"] />
    

    其中 android:clipOrientation表示裁剪方向,android:gravity可选参数比较多,可以通过 |符号来组合使用。
    下面我们举个例子来实现一张图片从上往下进行裁剪的效果,那么我们定义一个ClipDrawable

    <?xml version="1.0" encoding="utf-8"?>
    <clip xmlns:android="http://schemas.android.com/apk/res/android"
        android:clipOrientation="vertical"
        android:gravity="bottom">
        <shape android:shape="rectangle" >
            <solid android:color="@color/green"/>
        </shape>
    </clip>
    

    ImageView 的使用

    <ImageView
         	 android:layout_width="18dp"
         	 android:layout_height="40dp"
            android:id="@+id/imgView"
            android:background="@drawable/clip_drawable"/>
    

    在配合如下代码设置一下Level.

    ImageView view = (ImageView) findViewById(R.id.imgView);
    mClipDrawable = (ClipDrawable)view.getBackground();
    mClipDrawable.setLevel(50*100);
    

    这个知识点我做了一个小电池充电的效果 : 充电效果demo

    demo

  • 10 自定义Drawable

    drawable 的用途很简单,就是给View 做背景,或者作为ImageView 的图像演示。其中最重要的就是onDraw方法

    public class CustomDrawable extends Drawable {
    
        private Paint mPaint;
    
        public CustomDrawable(int color) {
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setColor(color);
        }
    
        @Override
        public void draw(Canvas canvas) {
            final Rect f = getBounds();
            float cx = f.exactCenterX();
            float cy = f.exactCenterY();
            canvas.drawCircle(cx, cy, Math.min(cx, cy), mPaint);
        }
    
        @Override
        public void setAlpha(int alpha) {
            mPaint.setAlpha(alpha);
            invalidateSelf();
        }
    
        @Override
        public void setColorFilter(ColorFilter colorFilter) {
            mPaint.setColorFilter(colorFilter);
            invalidateSelf();
        }
    
        @Override
        public int getOpacity() {
            return PixelFormat.TRANSLUCENT;
        }
    }
    

    上面的例子中这几个方法都必须要实现,虽然简单,但是五脏俱全。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值