Android的Drawable

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chaoyangsun/article/details/82350063

Android开发艺术探索读书笔记系列

Drawable是一个抽象类,它有众多子类如ShapeDrawable BitmapDrawable等. 它有一个重要的参数是内部宽高,通过getIntrinsicWidthgetIntrinsicHeight获取! 内部大小不等于它的大小,一般来说Drawable没有大小,当其作为View的背景时,Drawable会被拉伸至View的同等大小!

Drawable的分类及层次关系
这里写图片描述
BitmapDrawable
它表示一张图片,实际开发中可以直接引用图片,也可以通过XML的方式描述,这种方式可以实现更多效果,它有众多属性:
- android:src 图片资源id
- android:antialias 是否开启抗锯齿
- android:dither 是否开启抖动效果
- android:filter 是否开启过滤效果
- android:mipMap 纹理映射
- android:tileMode 平铺模式

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

NinePatchDrawable
NinePatchDrawable表示一张.9格式的图片,各属性和BitmapDrawable一样!

ShapeDrawable
ShapeDrawable可以理解为一种用颜色来构造的图形, 语法比较复杂,其子节点有corners、gradient、padding、size、solid、stroke, 它有一个属性shape有四个选项:rectangle(矩形)、oval(椭圆)、line(线)、ring(圆环), 默认是矩形,当其值是line或ring时必须要有子节点stroke来指定线的宽度和颜色,否则无效!

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

    <!--设置渐变色和solid不能共存-->
    <gradient
        android:endColor="@color/colorPrimary"
        android:centerColor="#000"
        android:type="sweep"
        android:startColor="#fff" />
    <size
        android:width="300dp"
        android:height="300dp" />
    <stroke
        android:width="1dp"
        android:color="#fff" />

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

LayerDrawable
LayerDrawable对应XML标签的<layer-list>,他是一种层次化的Drawable集合!可以包含多个item,每一个item表示一个Drawable, 下面的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="@color/colorPrimary" />
        </shape>
    </item>
    <!--然后铺上一层白色 并控制偏移量 内边距-->
    <item
        android:bottom="5dp"
        android:left="8dp"
        android:right="2dp">
        <shape android:shape="rectangle">
            <solid android:color="#ffffff" />
            <padding android:left="16dp"
                android:right="15dp"
                android:bottom="8dp"
                />
        </shape>
    </item>

</layer-list>

下图是上面几个例子的运行结果(不包过那条线):
这里写图片描述
StateListDrawable
StateListDrawable对应于<selector>标签, 也是表示Drawable集合! 每个Drawable对应View的一种状态, 系统根据View的状态选择合适的Drawable!

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!--pressed-->
    <item android:state_pressed="true" android:drawable="@color/colorPrimary"/>
    <!--focused-->
    <item android:state_focused="true" android:drawable="@color/colorAccent"/>
    <!--default-->
    <item android:drawable="@color/gray"/>
</selector>

LevelListDrawable
LevelListDrawable对应于<level-list>标签, 同样表示一个Drawable集合! 每个Drawable都有一个level的概念, 根据不同等级切换不同的Drawable!
当其作为View的背景时, 可以通过Drawable的getLevel和setLevel方法操作, 范围0~10000, 最小等级0,这也是默认值! 当其作为ImageView前景时,也可以使用setImageLevel方法来切换Drawable!

<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@color/colorPrimary"
        android:maxLevel="0" />
    <item
        android:drawable="@color/gray"
        android:maxLevel="1" />
</level-list>

TransitionDrawable
TransitionDrawable对应于<transition>, 它用于实现连个Drawable之间的淡入淡出效果.

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

然后通过View的startTransition和reverseTransition方法来实现淡入淡出的效果以及它的逆过程, 方法参数就是其变换的时长, 单位毫秒!

InsetDrawable
InsetDrawable对应于<inset>, 它可以将其他Drawable内嵌到自己当中,并可以在四周留出一定的间距, 当一个View希望其背景小于自己的实际区域时,可以用InsetDrawable, 当然LayerDrawable也可以!

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetBottom="20dp"
    android:insetLeft="30dp"
    android:drawable="@drawable/myshape"
    />
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:inset="10dp"
    >
    <shape android:shape="oval" >
        <solid android:color="@color/colorAccent"/>
    </shape>

</inset>

ScaleDrawable
ScaleDrawable对应于<scale>, 可根据自己的level将指定的Drawable缩放到一定比例! 属性android:scaleWidthandroid:scaleHeight分别表示宽高的缩放比例! 有一点比较费解就是 等级为0表示 表示ScaleDrawable不可见,这也是默认值,要想可见,还需手动设置level不为0!

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
     android:scaleWidth="60%"
     android:scaleHeight="60%"
    android:drawable="@drawable/myshape"
    />
myScale.getBackground().setLevel(1);

上面xml里面表示将图片缩小到原来的40%即缩小了60%, 值越大显示的越小; 下面的level(0 ~ 10000)正好相反,值越大显示越大, 0表示不显示, level设置为10000表示没有缩放效果! 具体level的缩放比例可以在ScaleDrawable的onBoundsChange方法里看到:


    @Override
    protected void onBoundsChange(Rect bounds) {
        final Drawable d = getDrawable();
        final Rect r = mTmpRect;
        final boolean min = mState.mUseIntrinsicSizeAsMin;
        final int level = getLevel();
        //宽度的缩放
        int w = bounds.width();
        if (mState.mScaleWidth > 0) {
            final int iw = min ? d.getIntrinsicWidth() : 0;
            w -= (int) ((w - iw) * (MAX_LEVEL - level) * mState.mScaleWidth / MAX_LEVEL);
        }
        //高度的缩放
        int h = bounds.height();
        if (mState.mScaleHeight > 0) {
            final int ih = min ? d.getIntrinsicHeight() : 0;
            h -= (int) ((h - ih) * (MAX_LEVEL - level) * mState.mScaleHeight / MAX_LEVEL);
        }

        final int layoutDirection = getLayoutDirection();
        Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection);

        if (w > 0 && h > 0) {
            d.setBounds(r.left, r.top, r.right, r.bottom);
        }
    }

以宽度为例MAX_LEVEL为10000, iw一般为0, 缩放比例公式可以简化为w -= (int) (w * (10000 - level) * mState.mScaleWidth / 10000);

ClipDrawable
ClipDrawable对应于<clip>, 它可以根据自己的level(0~10000)来裁剪一个Drawable,默认值0表示完全裁剪即不可见, 10000表示不裁剪! 裁剪方向可以通过android:clipOrientationandroid:gravity这两个属性来共同控制!clipOrientation表示裁剪方向, gravity比较复杂需要和clipOrientation配合才能起到作用!
gravity属性:
这里写图片描述

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="vertical"
    android:drawable="@drawable/ic_test"
    android:gravity="top"
    />
myclip.getBackground().setLevel(8000);//表示裁剪了20%

这里写图片描述

阅读更多
换一批

没有更多推荐了,返回首页