多样化的Drawable

来源:互联网 发布:淘宝店铺怎么刷信誉 编辑:程序博客网 时间:2024/06/05 05:32
原来不知道Drawable有这么多东西现在才学到0.0

Drawable有很多种,他们都表示一种图像的概念,通过颜色也可以构造出各式各样的图像效果。Drawable常被用来作为Viewde的背景使用,Drawble一般通过XML来定义,当然我们也可以通过代码创建具体的Drawable对象,知识代码创建会麻烦。Drawble是一个抽象类,它是所有Drawable对象的基类,每个具体的Drawable都是是它的子类,比如ShapDrawable、BitmapDrawable等,具体的看Drawable层次请自行查看。


Drawable的内部宽/高这个参数比较重要,通过getIntrinsicWidth和getIntrinsicHeight这两个方法可以获取到他们。但不是所有的Drawable都有内部宽/高,比如一种图片所形成的Drawable,它的内部宽/高就是图片的宽高,但是一个颜色所形成的Drawable,他就没有内部的宽高的概念。另外注意的是,Drawable的内部宽高不等同于它的大小,一般来说Drawable是没有大小概念的,当作用View的背景时,Drawable会被拉伸至View的同等大小。

Drawable的种类繁多,常见的BitmapDrawable、ShapeDrawable、LayerDrawable以及StateListDrawable



1、BitmapDrawable
它表示一张图片,在实际开发中直接引用图片即可
通过xml设置

<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@mipmap/ic_launcher"
    android:antialias="true"
    android:dither="true"
    android:gravity="center"
    android:filter="true"
    android:mipMap="true"
    android:tileMode="repeat"
    />




android:src 图片的资源ID
android:antialias图片抗锯齿功能
android:dither 抖动效果
android:filter 开启过滤效果
android:gravity  图片定位
android:mipMap 这是一种图像相关的处理技术,也叫纹理映射,比较抽象,这里也不对其深究了,默认值为false,在日常开发中此项不常用
android:tileMode 平铺模式 (4个选择:关闭平铺模式 disable   平铺模式 : repeat 表示的是简单的水平和竖直方向上的效果,mirror表示在水平和竖直方向的镜面投影效果,repeat表示的简单的水平和竖直方向上的平铺效果)


2、ShapeDrawable
通过颜色来构造的图像 它既可以是纯色的图形,也可以是具有渐变的图形。ShapeDrawable的语法稍微复杂点


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners
        android:bottomLeftRadius="50dp"
        android:bottomRightRadius="50dp"
        android:radius="30dp"
        android:topLeftRadius="10dp"
        android:topRightRadius="10dp" />
    <gradient
        android:angle="10dp"
        android:centerColor="@color/colorAccent"
        android:centerX="20dp"
        android:centerY="20dp"
        android:endColor="@color/colorAccent"
        android:gradientRadius="50dp"
        android:startColor="@color/colorAccent"
        android:type="radial"
        android:useLevel="true" />
    <padding
        android:bottom="10dp"
        android:left="10dp"
        android:right="10dp"
        android:top="10dp" />
    <size
        android:width="110dp"
        android:height="110dp" />
    <solid android:color="@color/colorPrimaryDark" />
    <stroke
        android:width="10dp"
        android:color="@color/colorAccent"
        android:dashGap="10dp"
        android:dashWidth="10dp" />
</shape>


android:shape表示图形的形状,有四个选型:rectangle(矩形)、oval(椭圆)、line(横线)和ring(圆环)

它的默认值是矩形,另外line和ring这两个选项必须要通过<stroke>标签来指定线的宽度和颜色等消息,否则将无法达到预期的效果
针对ring这个形状,有5个特殊的属性:
android:innerRadius 圆环的内直径,和android:innerRadiusRatio同时存在,以android:innerRadius为准
android:thickness 圆的厚度,及外半径减去内半径的大小,和android:thiscknessRatio同时存在时,以android:thickness为准
android:innerRadiusRatio:内半径占整个Drawable宽度的比例,默认值为9,如果为n,那么内半径 = 宽度/n
android:thicknessRatio:厚度占整个Drawable宽度的比例,默认值为3。如果为n,那么厚度 = 宽度 / n
android:useLevel:一般都应该使用false,否则有可能无法达到预期的显示效果,除非它被当做LevelListDrawable来使用

<corners>
表示shape的四个角的角度。它只适合用于矩形shape,这里的角度是指圆角的程度 ,用px来表示,它的5个属性:
—android:radius  为4个角度同事设定相同的角度,优先级较低,会被其他四个属性覆盖
—android:topLeftRadius  设定最上角的角度
—android:topRightRadius 设定右上角的角度
—android:bottomLeftRadius  设定最下角的角度
—android:bottomRightRadius  设定右下角的角度

<gradient>
它与<solid>标签是互相排斥的,其中solid表示纯色填充,而gradiect则表示渐变效果,gradient有如下属性:
—android:angle   渐变的角度,默认为0,其值必须为45的倍数,0表示从左到右,90表示从下到上,具体的效果需要自己去调试,总之角度会影响渐变的方向
—android:centerX   渐变的中心点横坐标
—android:centerY   渐变的中心点的纵坐标
—android:startColor    渐变的起始颜色
—android:centerColor  渐变的中间颜色
—android:endColor   渐变的结束颜色
—android:gradientRadius   渐变的半径,仅当android:type: = “radial”时有效
—android:userLevel   一般为false,当Drawable作为StateListDrawable使用时为true;
—android:type   渐变的类别 有linear(线) 、 radial(径向渐变)、sweep(扫描线渐变)默认为线性渐变

<panding>
这个表示空白,但是它的表示表示shape的空白,而是包含它的View的空白,有4个属性:android:left 、android:top、android:right、android:bottom

<solid>表示纯色填充,通过android:color即可指定shape中填充的颜色

<stroke>Shape的描边
—android:width     描边的宽度,越大则shape的边缘线就会看起来越粗
—android:color      描边的颜色
—android:dashWidth     组成虚线的线段的宽度
—android:dashGap      组成虚线线段之间的间隔,间隔越大则虚线看起来空隙就越大。

<size>
shape的大小


3、LayerDrawable 
LayerDrawable对应得XML标签是<layer-list>,表示一种层次化的Drawable集合

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@drawable/shape_rect_stroke_drawable"
        android:bottom="10dp"
        android:top="10dp"
        android:right="10dp"
        android:left="10dp"
        android:id="@+id/textView4"
        >
    </item>
   
    <item>
    </item>
    ........
</layer-list>

一个layer-list中可以包括多个item,每个item表示一个Drawable。我们可以通过android:drawable属性来直接引用一个已有的Drawable资源,也可以在item中自定义Drawable。layer-list中的所有的Drawable都会被缩放至View的大小,对于bitmap来说,需要使用android:gravity属性才能控制图片的显示效果。
例子:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <solid android:color="#0ac39e" />
        </shape>
    </item>

    <item android:bottom="6dp">
        <shape>
            <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>


4、StateListDrawable (重点)
StateListDrawable对应于<selector>标签,它也是表示Drawable集合,每一个Drawable对应着View的一种状态,StateListDrawable主要用于设置可单击的View的背景,最常见的是Button。

<?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/state_list_all_values_drawable"
        android:state_pressed="true"
        android:state_focused="true"
        android:state_hovered="true"
        android:state_selected="true"
        android:state_checked="true"
        android:state_checkable="true"
        android:state_enabled="true"
        android:state_activated="true"
        android:state_window_focused="true"
        />
</selector>

android:constantSize    的固有大小是否不随着其状态的改变和改变的,因为状态的改变会导致StateListDrawable切换到具体的Drawable,而不同的Drawable具有不同的固有大小。True表示StateListDrawable的固有大小保持不变,这是他的固有大小是内部所有Drawable的固有大小的最大值,false则会随着状态的改变而改变。此选项默认值为false。

android:dither   是否开启抖动效果,开启此选项可以让图片在低质量的屏幕上仍然获得较好的显示效果,默认值为True

android:variablePadding    StateListDrawable的padding表示是否随着其状态的改变而改变,true表示会随着状态的改变而改变,false表示StateListDrawable的padding是内部所有Drawable的padding的最大值,此选项默认为false,并且不建议开启此选项。

<item>标签表示一个具体的Drawable

—android:state_pressed 表示按下状态,比如button被按下后仍没有松开时的状态
—android:state_focused 表示View已经获取了焦点
—android:state_selected 表示用户选择了View
—android:state_checked 表示用户选中了View,一般适用于checkBox这类在选中和非选中状态之间进行切换的View
—android:state_enabled 表示view处于可用状态

5、LevelListDrawable

LevelListDrawable对应于<level-list>标签,它同样表示一个Drawable集合,集合中的每一个Drawable都有一个等级的概念。根据不同的等级,LevelListDrawable会切换对应的Drawable

<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@drawable/focused_drawable"
        android:maxLevel="10"
        android:minLevel="10"
        />
</level-list>

每个Item表示一个Drawable,并且有对应的等级范围由android:minLevel和android:mxLevel来指定。

6、TransitionDrawable
TransitionDrawable对应于<transition> 标签,它用于实现两个Drawable之间的淡入浅出效果

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


7、InsetDrawable
InsetDrawable对应于<inset>标签,它可以将其他Drawable内嵌到自己当中,并可以在四周留有一定的间距。

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/focused_drawable"
    android:insetBottom="15dp"
    android:insetLeft="15dp"
    android:insetRight="15dp"
    android:insetTop="15dp">

    <shape android:shape="rectangle">
        <solid android:color="#ff0000" />
    </shape>

</inset>

8、ScaleDrawable
ScaleDrawable对应于<scale>标签,它可以根据自己等级将指定Drawable缩放到一定比例

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

这里记住要想ScaleDrawable可见,那么它的等级就不能为0看源码

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


那么它的等级就得设置大于0的数且小于等于10000

//scale
scaleTV = (TextView) findViewById(R.id.scale_tv);
ScaleDrawable scaleDrawable = (ScaleDrawable) scaleTV.getBackground();
scaleDrawable.setLevel(1);
scaleDrawable.setLevel(1);这里一定要记住


9、ClipDrawable
ClipDrawable对应<clip>标签,它可以根据自己当前等级来裁剪另一个Drawable,裁剪方向可以通过android:clipOrientation和android:gravity这两个属性来共同控制

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

代码设置
//clipe
clipeIMG = (ImageView) findViewById(R.id.clipe_img);
ClipDrawable clipDrawable = (ClipDrawable) clipeIMG.getDrawable();
clipDrawable.setLevel(3000);

这里需要主要的是ClipeDrawable也是有等级,它的范围是0~~10000 值越大裁剪区域越小  反之越大


10、自定义的Drawable
package com.example.jiangtao.aima.view;

import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;

/**
 * Created by jiangtao
 * 16/5/20
 * com.example.jiangtao.aima.view
 * Aima
 */
public class MyDrawable extends Drawable {

    private Paint mPaint;

    public MyDrawable(int color) {
        mPaint new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(color);
    }

    @Override
    public void draw(Canvas canvas) {
        final Rect rect = getBounds();
        float cx = rect.exactCenterX();
        float cy = rect.exactCenterY();

    }

    @Override
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        mPaint.setColorFilter(colorFilter);
        invalidateSelf();
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }
}



Demo





0 0