美文网首页
Android的Drawable

Android的Drawable

作者: Cris_Ma | 来源:发表于2017-06-01 23:33 被阅读0次

    Drawable简介

    提到Drawable,第一反应肯定是存放图片的位置,实际上,Drawable并不仅仅指图片。它可以理解为一种图片的概念,比如颜色填充,也可以理解为一种图片。

    Drawable类是一个抽象类,它有BitmapDrawable,ShapeDrawable,LayerDrawable,StateListDrawable等常用子类。

    BitmapDrawable

    BitmapDrawable就是一张图片,通过src属性定义指向的图片资源,然后对该图片进行相关设置主要属性如下:

    <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
        android:src="@drawable/ic_launcher"
        android:gravity="bottom"//设定图片在容器中的位置,默认值为fill,在水平和竖直方向填充容器
        android:antialias="true"//设置抗锯齿
        android:tint 给图片着色,比如图片本来是黑色的,着色后可以变成白色
        android:tintMode 着色模式,也是API Level 21(Android 5.0)才添加的属性
        android:alpha 设置图片的透明度,取值范围为0.0~1.0之间,API Level最低要求是11,即Android 3.0
        android:filter="true"//开启过滤效果
        android:dither="true"//开启抖动效果
        android:tileMode="clamp"//设置平铺方式,disable,clamp,repeat,mirror
       >
    </bitmap>
    //使用代码进行动态设置:
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
            BitmapDrawable bitmapDrawable = new BitmapDrawable(bitmap);
            bitmapDrawable.setTileModeXY(Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            bitmapDrawable.setAntiAlias(true);
            bitmapDrawable.setDither(true);
    

    除了针对常见图片的BitmapDrawable之外,NinePatchDrawable对应的是.9图片,用法同BitmapDrawable一样,根标签是nine-patch

    ColorDrawable

    ColorDrawable用纯色填充一块区域,使用也最简单,只有一个属性,color:

    <color xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/colorBlack">
    </color>
    //代码设定:
    ColorDrawable colorDrawable = new ColorDrawable(0xffff0000);
    //使用颜色:
    mImageView.setBackground(new ColorDrawable(0xffff0000));
    mImageView.setBackgroundColor(Color.argb(255,00,255,00));
    

    Android中对颜色的设定采用ARGB模式,xml中可以不指定alpha值,但是在代码中使用十六进制数值设置颜色时,必须制定alpha值,否则默认为0x00,全透明,是看不到颜色的。

    GradientDrawable(ShapeDrawable)

    GradientDrawable表示一个渐变区域,可以实现线性渐变、发散渐变、和平铺渐变。它的主要属性如下:

    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="line">//设置Shape形状,rectangle(矩形),oval(椭圆),line(直线),ring(圆形)四个可选值
    <!-- 下面的属性只有在android:shape="ring时可用:
    android:innerRadius         尺寸,内环的半径。
    android:innerRadiusRatio    浮点型,以环的宽度比率来表示内环的半径,
    android:thickness           尺寸,环的厚度
    android:thicknessRatio      浮点型,以环的宽度比率来表示环的厚度,例如,如果android:thicknessRatio="2",
    android:useLevel            boolean值,如果当做是LevelListDrawable使用时值为true,否则为false.  "-->
        <corners //只有rectangle有效,用来设置四个角的圆角半径
            android:radius="50px"//对四个角统一设置,优先级较低,会被以下属性覆盖
            android:topLeftRadius="40dp"
            android:topRightRadius="40dp"
            android:bottomLeftRadius="40dp"
            android:bottomRightRadius="40dp"/>
        <gradient//渐变效果
            android:angle="45"//渐变的方向角度,必须为45的倍数,默认为0
            android:centerX="100"//渐变中心点X坐标
            android:centerY="250"
            android:startColor="@color/colorBlack"//渐变起始色
            android:centerColor="@color/colorDarkGreen"//渐变中间颜色
            android:endColor="@color/colorWhite"//结束颜色
            android:gradientRadius="50dp"//渐变半径,只有type值为radial时有效
            android:type="linear"//渐变类型,有Linear(线性),radial(径向),sweep(扫描线)三种。默认为线型渐变
            android:useLevel="false"/>//一般为false,只有当Drawable作为StateListDrawable使用才设置true
        <solid//纯色填充,与gradient互斥
            android:color="@color/colorDarkGreen"/>
        <stroke//Shape描边效果
            android:width="5dp"//描边宽度
            android:color="@color/colorLightRed"
            android:dashWidth="15dp"//线条长度
            android:dashGap="5dp"/>//线条间距
        <padding//设置内边距
            android:left="5dp"
            android:right="5dp"
            android:bottom="5dp"
            android:top="5dp"/>
        <size//设置尺寸。Drawable本身是没有尺寸概念的,使用getIntrinsicWidth/Height获取到的值是-1。通过Size设定Drawable固有尺寸。
                但是作为背景的时候,Shape仍然会拉伸为适合view的大小
            android:width="200dp"
            android:height="200dp"/>
    </shape>
    

    LayerDrawable

    LayerDrawable包含多个item,每个item表示一个drawable,LayerDrawable将所包含的item放置在不同的层次上,第一个item在最底层,依次向上叠加:

    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item
            android:left="2dp"
            android:top="4dp">
            <shape>
                <solid android:color="@android:color/darker_gray" />
                <corners android:radius="10dp" />
            </shape>
        </item>
        <item
            android:bottom="4dp"
            android:right="2dp">
            <shape>
                <solid android:color="#FFFFFF" />
                <corners android:radius="10dp" />
            </shape>
        </item>
    </layer-list>
    

    item子节点可以直接定义一个Drawable,也可以使用android:drawable属性来引用一个Drawable,layer-list没有属性节点,只包含Item子节点。Item节点属性除了android:drawable,还有android:top/left/right/bottom用来设定各个方向的偏移距离

    StateListDrawable

    StatelistDrawable也是一个Drawable集合,每个Drawable对应View的一种状态,只要用在设置View的背景。它使用selector标签:

    <selector xmlns:android="http://schemas.android.com/apk/res/android"
        android:constantSize="true" //默认为false。因为状态改变的时候会切换到不同的Drawable,大小也是不同的,设置为true表示尺寸固定不变
        android:dither="true"
        android:variablePadding="true"//默认为false,表示padding不随着状态的改变而变化。
        android:enterFadeDuration="500"//状态改变时切入的动作事件,ms
        android:exitFadeDuration="500">
        <item
            android:drawable="@color/colorBlack"//指定Drawable资源,也可以是color
            android:state_pressed="true"//按下状态
            android:state_focused="true"//获取到焦点
            android:state_hovered="true"//API14加入,true表示鼠标在其上滑动
            android:state_selected="true"//选择了view
            android:state_checkable="true"//可选择状态。类似于enable,它用来设置CheckBox等可勾选的控件
            android:state_checked="true"//是否选中状态
            android:state_enabled="false"//是否可用状态。通常只设置false
            android:state_activated="true"/是否被激活状态,API Level 11及以上才支持,可通过代码调用控件的setActivated(boolean)方法设置是否激活该控件
            android:state_window_focused="true"/>//当前窗口是否获取焦点。比如弹出对话框就会失去焦点
    </selector>
    

    系统会根据View的当前状态从selector中选择对应的item,选择的时候会从上向下一直找到第一条匹配的item,通常会设置一个默认的item放在最后,不设置任何的状态。这样当系统在上边的item中找不到对应的状态时,就会选择最后一个默认的item,它不附带任何状态,可以匹配给所以状态。

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- 当前窗口失去焦点时 -->
        <item android:color="@android:color/black" android:state_window_focused="false" />
        <!-- 不可用时 -->
        <item android:color="@android:color/background_light" android:state_enabled="false" />
        <!-- 按压时 -->
        <item android:color="@android:color/holo_blue_light" android:state_pressed="true" />
        <!-- 被选中时 -->
        <item android:color="@android:color/holo_green_dark" android:state_selected="true" />
        <!-- 被激活时 -->
        <item android:color="@android:color/holo_green_light" android:state_activated="true" />
        <!-- 默认时 -->
        <item android:color="@android:color/white" />
    </selector>
    //在控件中使用Drawable
    <Button 
        android:id="@+id/btn_default"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:background="@drawable/bg_btn_selector"
        android:text="默认按钮"
        android:textColor="@color/text_btn_selector" />
    

    LevelListDrawable

    LevelListDrawable也是一系列Drawable集合,它通过Level来匹配item。

    <level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@color/colorBlack"
        android:maxLevel="10000"
        android:minLevel="0"/>
    </level-list>
    

    item子节点除了指定Drawable之外,只有两个属性android:maxLevel指定最高Level(10000),android:minLevel指定最低Level(0),在这两个值中间就会匹配该item。匹配的时候也是从上向下,直到匹配到一条合适的item 。所以,通常只需要指定maxLevel就可以了,将item按maxLevel从小到大依次排列下来。

    Level的设置使用Drawable的setLevel方法来设定。如果是作为ImageView的前景,也可以通过ImageView的setImageLevel来设定。

    TransitionDrawable

    transition其实是继承自layer-list的,只是,transition只能管理两层drawable,另外提供了两层drawable之间切换的方法,切换时还会有淡入淡出的动画效果。示例代码如下:

    <transition xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/on" />
        <item android:drawable="@drawable/off" />
    </transition>
    

    然后在控件中指定背景:

    <Button
            android:id="@+id/btn1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/transition_drawable"
            />
    

    transition标签生成的Drawable对应的类为TransitionDrawable,要切换时,需要主动调用TransitionDrawable的startTransition()方法,参数为动画的毫秒数,也可以调用reverseTransition()方法逆向切换。

    Button mButton = (Button) findViewById(R.id.btn1);
    TransitionDrawable transitionDrawable = mButton.getBackground();
    transitionDrawable.startTransition(500); //正向切换,即从第一个drawable切换到第二个
    transitionDrawable.reverseTransition(500); //逆向切换,即从第二个drawable切换回第一个
    

    InsetDrawable

    InsetDrawable使用<inset>标签,可以将指定的Drawable内嵌到自己当中,特殊的是它可以设置四周的间距,作为背景时,设定值为背景与view边框的距离,用layerList同样可以实现。

    android:drawable 指定drawable资源,如果不设置该属性,也可以定义drawable类型的子标签
    android:visible 设置初始的可见性状态,默认为false
    android:insetLeft 左边距
    android:insetRight 右边距
    android:insetTop 顶部边距
    android:insetBottom 底部边距
    android:inset 设置统一边距,会覆盖上面四个属性,但API Level要求为21,即Android 5.0
    

    ScaleDrawable

    ScaleDrawable使用<scale>标签,它可以对指定的drawable进行缩放。它的scaleGravity属性作用同BItmap一样。另外还有两个特殊属性,scaleHeight和scaleWidt指定宽和高的缩放比例,接收百分比数值。需要注意的是,ScaleDrawable缩放效果不仅仅受scaleHeight和scaleWidth影响,还要指定Level。默认的Level为0,这时候ScaleDrawable是不会绘制的。下面来看一个例子:

    <scale xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@drawable/ic_launcher"
        android:scaleGravity="center"
        android:scaleHeight="30%"//实际大小约为70%
        android:scaleWidth="30%"
        android:level="1"/>//API 24以上才支持
    //在控件中使用:这时候是看不到图片的,没有设置Level,图片不会绘制出来
        <ImageView
            android:id="@+id/scaleimg"
            android:src="@drawable/scaledraw"
            android:layout_width="150dp"
            android:layout_height="150dp"/>
    //设置Level:
    mScaleImageView.setImageLevel(1);
    

    注意的是,Level对缩放比例的影响,Level值越大,Drawable就越大,如果设置为10000(Level最大值),那么不管缩放比例设置多少,都不会进行缩放。而scaleHeight和scaleWidth相反,值越大,Drawable越小。

    ClipDrawable

    ClipDrawable用来对Drawable进行裁剪,它也是根据Level来决定裁剪范围,10000表示不裁剪,0表示全部裁剪,就看不到了。裁剪的方向通过clipOritation来设置vertical和horizontal,除此之外还有一个Gravity属性,它和clipOritation一起决定了裁剪方式。
    Gravity有以下取值:

    top: Drawable放在容器顶部,竖直裁剪的时候从底部开始
    bottom:Drawable放在容器底部,竖直裁剪时从顶部开始
    left:默认值。Drawable放在容器左边,水平裁剪时从右边开始
    right:放在右边,水平裁剪从左边开始
    center_vertical:Drawable竖直居中,不改变大小,竖直裁剪从上下同时开始
    fill_vertical:竖直方向填充容器。竖直裁剪的时候,只有clipDrawable的level为0,才有裁剪行为
    center_horizontal:水平居中,不改变大小,水平裁剪从左右同时开始
    fill_horizontal:水平填充,水平裁剪只有当clipDrawable的level为0,才有裁剪行为
    center:水平和垂直居中,竖直方向上下,水平方向左右同时裁剪
    fill:水平和竖直方向填充容器,只有当clipDrawable的level为0,才有裁剪行为

    其他标签

    • rotate
      <rotate>标签用来控制Drawable的旋转,主要用以下属性:

      android:drawable 指定drawable资源,如果不设置该属性,也可以定义drawable类型的子标签
      android:fromDegrees 起始的角度度数
      android:toDegrees 结束的角度度数,正数表示顺时针,负数表示逆时针
      android:pivotX 旋转中心的X坐标,浮点数或是百分比。浮点数表示相对于drawable的左边缘距离单位为px,如5; 百分比表示相对于drawable的左边缘距离按百分比计算,如5%; 另一种百分比表示相对于父容器的左边缘,如5%p; 一般设置为50%表示在drawable中心
      android:pivotY 旋转中心的Y坐标
      android:visible 设置初始的可见性状态,默认为false

      将一张图片旋转180度代码如下:

    <rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@drawable/ic_arrow"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="180" />
    

    rotate同样与Level有关。Level值从0-10000分别对应fromDegrees和toDegrees,比如Level设置5000就会旋转90度。因为level值默认为0,所以默认是不会旋转的,如果要旋转的话可以将android:fromDegrees直接设置180度,开始的状态就已经完成旋转了。

    • animation-list
      <animation-list>用来将一系列drawable构建成帧动画。通过添加item子标签设置每一帧使用的drawable资源,以及每一帧持续的时间。示例代码如下:
    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
        android:oneshot="false">
        <item
            android:drawable="@drawable/anim1"
            android:duration="1000" />
        <item
            android:drawable="@mipmap/anim2"
            android:duration="1000" />
        <item
            android:drawable="@mipmap/anim3"
            android:duration="1000" />
    </animation-list>
    

    android:oneshot属性设置是否循环播放,设为true时,只播放一轮就结束,设为false时,则会轮询播放。
    android:duration属性设置该帧持续的时间,以毫秒数为单位。
    animation-list对应的Drawable类为AnimationDrawable,要让动画运行起来,需要主动调用AnimationDrawable的start()方法。另外,如果在Activity的onCreate()方法里直接调用start()方法会没有效果,因为view还没有初始化完成是播放不了动画的。

    • animation-rotate

      rotate标签只是将原有的drawable转个角度变成另一个drawable,它是静态的。而animated-rotate则会让drawable不停地做旋转动画。
      animated-rotate可设置的属性只有四个:

    android:drawable 指定drawable资源,如果不设置该属性,也可以定义drawable类型的子标签
    android:pivotX 旋转中心的X坐标
    android:pivotY 旋转中心的Y坐标
    android:visible 设置初始的可见性状态,默认为false

    示例代码:

    <animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@drawable/img_daisy"
        android:pivotX="50%"
        android:pivotY="50%"
        android:visible="false" />
    

    相关文章

      网友评论

          本文标题:Android的Drawable

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