Android开发艺术探索 - 第6章 Android的Drawable

46 篇文章 0 订阅
39 篇文章 0 订阅

Drawable表示了可绘制对象。
getIntrinsicWidth/getIntrinsicHeight获取固有的宽高。对于BitmapDrawable来说,该方法返回其图片的宽高,对于shape类型的,默认返回-1。显示在View中的drawable会被拉伸或缩小为View的大小,固有宽高和其最终显示在View中的宽高不一定相等。
一部分Drawable中用到的level的范围是0-10000。

1.分类
  1. BitmapDrawable
    支持png/jpg/gif。可以直接通过resource id使用原始图片,或者在xml创建一个他的resource id别名。因为在build的过程中无损图片会被优化,放在res/raw下可以防止被优化。
<?xml version="1.0" encoding="utf-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@[package:]drawable/drawable_resource"
    android:antialias=["true" | "false"]
    android:dither=["true" | "false"]
    android:filter=["true" | "false"]
    android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
                      "fill_vertical" | "center_horizontal" | "fill_horizontal" |
                      "center" | "fill" | "clip_vertical" | "clip_horizontal"]
    android:mipMap=["true" | "false"]
    android:tileMode=["disabled" | "clamp" | "repeat" | "mirror"] />
  • android:src
    资源id
  • android:antialias
    抗锯齿
  • android:dither
    简单的说就是用现有的显示终端能够识别的颜色来模拟产生出其不能产生的像素,也就是用较小数量的颜色去模拟更多数量的颜色,如在16位色设备上显示24位色图片。就是牺牲分辨率换取更多感知颜色数。
  • android:filter
    用于图片拉伸或收缩时,可以保持较好的显示效果。
  • android:gravity
    设置图片小于其容器时在其容器中的位置。
  • android:mipMap
    纹理映射。
  • android:tileMode
    平铺模式。开启之后gravity会失效。repeat:在水平和竖直方向平铺;mirror:水平和垂直方向平铺,相邻的图片是镜像的;clamp:在超出图片原始边界的地方,复制其边缘的颜色。
  1. NinePatchDrawable
<?xml version="1.0" encoding="utf-8"?>
<nine-patch
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@[package:]drawable/drawable_resource"
    android:dither=["true" | "false"] />
  1. ShapeDrawable
    xml resource会被编译为GradientDrawable
<?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" />
    <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"] />
    <padding
        android:left="integer"
        android:top="integer"
        android:right="integer"
        android:bottom="integer" />
    <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>
  • <shape>
    • android:shape
      rectangle:矩形,会填充其View。默认值。
      oval:椭圆,会填充其View。
      line:水平线,其宽度贯穿了其View。需要使用<stroke>指定其线宽。
      ring:圆环。
      针对ring的5个属性:
    • android:innerRadius
      圆环中心孔洞的半径。
    • android:innerRaduisRatio
      圆环中心孔洞的半径,用圆环宽度的比例表示。默认值为9,则innerRadius=width/9。该值会被android:innerRadius覆盖。
    • android:thickness
      圆环厚度。
    • android:thicknessRatio
      圆环厚度,用圆环宽度的比例表示。默认值为3,则thickness=width/9。该值会被android:thickness。
    • android:useLevel
      被当作LevelListDrawable时,设置为true。其他情况设置为false。
  • <corner>
    矩形的圆角度数。用于rectangle。
    android:radius 会被其他四个属性覆盖。
    android:topLeftRadius
    android:topRightRadius
    android:bottomLeftRadius
    android:bottomRightRadius
    tips:每个corner的初始值要设置为大于1的值,否则所有的corner都没有圆角。如果希望某几个corner没有圆角,可以通过radius设置一个大于1的默认值,然后对需要有圆角的设置相应的值,不需要有圆角的设置为0dp。
  • <gradient>
    渐变色填充。
    android:angle 渐变角度。0为左到右,必须为45倍数,逆时针旋转。默认为0。
    android:centerX
    android:centerY
    android:centerColor
    android:endColor
    android:gradientRadius 渐变半径,type为radial时有效。
    android:startColor
    android:type linear线性,radial径向,sweep扫描。
  • <solid>
    纯色填充。
  • <stroke>
    描边。
    android:width
    android:color
    android:dashWidth 虚线线段宽度
    android:dashGap 虚线线段间距
  • <padding>
    指定其与其View的padding
  • <size>
    实则shape的固有宽高。shape类型的drawable默认没有固有宽高,getIntrinsicWidth/getIntrinsicHeight返回-1。设置了该属性后,会返回相应的值,但是作为View背景的时候,还是会被相应的拉伸或缩小。
  1. LayerDrawable
    多个drawable叠加
<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:id="@[+][package:]id/resource_name"
        android:top="dimension"
        android:right="dimension"
        android:bottom="dimension"
        android:left="dimension" />
</layer-list>
  • <item>
    定义了一个drawable。可以包含<bitmap>标签。
    left/right/top/bottom表示的是offset。
    默认情况下,drawable会缩放至View的大小,为了避免缩放,在item中使用bitmap的时候,使用bitmap标签,同时使用gravity设置不缩放的参数。
  1. StateListDrawable
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:constantSize=["true" | "false"]
    android:dither=["true" | "false"]
    android:variablePadding=["true" | "false"] >
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:state_pressed=["true" | "false"]
        android:state_focused=["true" | "false"]
        android:state_hovered=["true" | "false"]
        android:state_selected=["true" | "false"]
        android:state_checkable=["true" | "false"]
        android:state_checked=["true" | "false"]
        android:state_enabled=["true" | "false"]
        android:state_activated=["true" | "false"]
        android:state_window_focused=["true" | "false"] />
</selector>
  • <selector>
    android:constantSize 其固有大小是否不随着state的改变而改变。
    android:variablePadding 其padding是否会随着状态的改变而改变。
  • item的匹配顺序为从上至下,所以默认状态的drawable要放在最下面。
  1. LevelListDrawable
<?xml version="1.0" encoding="utf-8"?>
<level-list
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="@drawable/drawable_resource"
        android:maxLevel="integer"
        android:minLevel="integer" />
</level-list>

通过setLevel方法或者ImageView的setImageLevel方法,使maxLevel>=level的item得到显示。
7. TransitionDrawable
实现两个drawable的淡入淡出。item不能超过两个。

<?xml version="1.0" encoding="utf-8"?>
<transition
xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:id="@[+][package:]id/resource_name"
        android:top="dimension"
        android:right="dimension"
        android:bottom="dimension"
        android:left="dimension" />
</transition>

示例

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/on" />
    <item android:drawable="@drawable/off" />
</transition>
<ImageButton
    android:id="@+id/button"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:src="@drawable/transition" />
ImageButton button = (ImageButton) findViewById(R.id.button);
Drawable drawable = button.getDrawable();
if (drawable instanceof TransitionDrawable) {
    ((TransitionDrawable) drawable).startTransition(500);
}
  1. InsetDrawable
    嵌入其他的drawable,并在四周留有一定的距离。当需要给View设置一个比起边界小的背景时可以用到。
<?xml version="1.0" encoding="utf-8"?>
<inset
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/drawable_resource"
    android:insetTop="dimension"
    android:insetRight="dimension"
    android:insetBottom="dimension"
    android:insetLeft="dimension" />

9.ScaleDrawable
依据drawable的level将其缩放到一定的比例。

<?xml version="1.0" encoding="utf-8"?>
<scale
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/drawable_resource"
    android:scaleGravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
                          "fill_vertical" | "center_horizontal" | "fill_horizontal" |
                          "center" | "fill" | "clip_vertical" | "clip_horizontal"]
    android:scaleHeight="percentage"
    android:scaleWidth="percentage" />
w -= (int) ((w - iw) * (MAX_LEVEL - level) * mState.mScaleWidth / MAX_LEVEL);

level越大,drawable越大;指定的percentage越大,drawable越小。在使用时,level不能为0,否则直接不显示。
10. ClipDrawable

<?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"] />

通过level去控制另外一个drawable的裁剪。level为0为完全裁剪。经常用在进度条。

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/android"
    android:clipOrientation="horizontal"
    android:gravity="left" />
<ImageView
    android:id="@+id/image"
    android:background="@drawable/clip"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content" />
ImageView imageview = (ImageView) findViewById(R.id.image);
Drawable drawable = imageview.getBackground();
if (drawable instanceof CLipDrawable) {
    ((ClipDrawable)drawable).setLevel(drawable.getLevel() + 1000);
}
2.自定义Drawable

Drawable主要用于ImageView中的图像显示,以及View的背景。
View中绘制背景是调用了drawable的draw方法,所以通过实现draw方法可以实现自定义Drawable。
Drawable有固有大小时,需要实现getIntrinsicWidth/getIntrinsicHeight返回正确的数值。
区别于固有大小,实际大小通过getBounds获得。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值