第六章Andorid的Drawable(Android开发艺术探索)

阅读本章将了解:
这里写图片描述
Drawable是没有大小概念的,当用作view的背景时,Drawable会被拉伸到view同等大小

6.2、Drawable的分类

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

6.2.1、BitmapDrawable :最简单的drawable

我们可以通过xml的方式来描述它,常见属性有:
<bitmap  xmlns:android="http://schemas.android.com/apk/res/android"
//图片的资源id
    android:src="@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"]
//平铺模式(默认关闭,当开启平铺时,gravity属性无效)
    android:tileMode=["disabled" | "clamp" | "repeat" | "mirror"] />

下面我们来看看效果
这里写图片描述

需要注意的是:想要有平铺的效果,那么你的控件就必须要比你引用的图片尺寸要大
NinePatchDrawable,它表示一个.9的图片,跟BitmapDrawable 使用方式一样

6.2.2、ShapeDrawable
通过颜色来构造图形
常见属性有:

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    //rectangle(矩形)oval椭圆line横线ring圆环
    android:shape=["rectangle" | "oval" | "line" | "ring"] >
<corners        //当shape为rectangle时使用
    android:radius="integer"        //半径值会被后面的单个半径属性覆盖,默认为1dp
    android:topLeftRadius="integer"
    android:topRightRadius="integer"
    android:bottomLeftRadius="integer"
    android:bottomRightRadius="integer" />
<gradient       //渐变
//渐变的角度,默认是0,值必须是45的倍数,0表示从左到右,90表示从上到下
    android:angle="integer"
//渐变中心点的横坐标
    android:centerX="integer"
//渐变中心点的纵坐标
    android:centerY="integer"
//渐变的起始色
android:startColor="color"
//渐变的中间色
    android:centerColor="integer"
//渐变的结束色
    android:endColor="color"
//渐变半径,仅当android:type = "redial"时有效
    android:gradientRadius="integer"
//渐变的类别:linear :线性渐变,radial:径向渐变,sweep:扫描线渐变
    android:type=["linear" | "radial" | "sweep"]
//一般是false
    android:useLevel=["true" | "false"] />
<padding        //内边距
    android:left="integer"
    android:top="integer"
    android:right="integer"
    android:bottom="integer" />
<size           //指定大小,一般用在imageview配合scaleType属性使用
    android:width="integer"
    android:height="integer" />
<solid          //填充颜色
    android:color="color" />
<stroke         //边框
    android:width="integer"
    android:color="color"
    android:dashWidth="integer"
    android:dashGap="integer" />
    </shape>

具体解释如下:

android:shape :表示图形的形状
<corners>:表示4个角的角度,只适用于shape是rectangle(矩形)的情况
<gradient> :它与<solid>是互相排斥的,<solid>表示纯色,<gradient>表示渐变

这里写图片描述

<solid> :纯色填充,通过andorid:color可以指定shape中填充的颜色
<stroke> :Shape的描边
android:width:描边的宽度,越大边框就越粗
android:color:描边的颜色
android:dishWidth:组成虚线的线段宽度
android:dishGap:组成虚线的每个线段之间的间隔空隙
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

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

    <stroke
        android:dashGap="2dp"
        android:dashWidth="10dp"
        android:width="2dp"
        android:color="#00ff00" />

</shape>

这里写图片描述

<padding>:表示包含它的view与它的pading间距
<size> :shape的固有宽高,但是当作为view的背景时,这个宽高的意义就不大了。

6.2.3、LayerDrawable

对应的xml标签是: :重叠放置达到效果,类似FramLayout
一个 可以包含多个,下面的item会覆盖上面的item,每个item的常用属性是:

andorid:top = ""
andorid:bottom = ""
andorid:left = ""
andorid:right = ""

代表相对view的上下左右的偏移量
andorid:drawable = “@drawable/ic_est”
代表引用drawable资源
代码如下一个小例子:

<?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="#0ac39e" />
        </shape>
    </item>

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

这里写图片描述

6.2.4、StateListDrawable

StateListDrawable对应的是我们常用的标签,常用属性如下:

这里写图片描述

android:constanSize :默认为false,表示固有大小是否随着包含的View的改变而改变
android:dither:是否开启抖动效果,默认true,让在低质量的屏幕上有较好效果
android:variablePadding:是否随着其状态的改变而改变,默认是false,不建议开启此选项
<item>标签表示一个具体的Drawable
android:drawable表示资源ID,其他表示drawable的各种状态

这里写图片描述
用的比较多,就不举例了。

6.2.5、LevelListDrawable

LevelListDrawable对应标签,同样表示一个drawable集合,根据不同的level(等级),会切换到对应的drawable
基本用法如下:

这里写图片描述

通过minLevel和maxLevel来设置等级,0~10000之间
使用场景:
有时候,我们为了在一个ImageView中显示不同的图片,往往会使用:

if (条件1)
{ 
        image.setBackground(R.id.xxx1); 
}
else if (条件2)
{ 
        image.setBackground(R.id.xxx2); 
} ... 

可以用另一个简便的方法实现相同的功能
首先,在res/drawable下建立一个xml文件,内容如下

<level-list xmlns:Android="http://schemas.android.com/apk/res/android">
    <item android:maxLevel="0" android:drawable="@drawable/battery_0" />
    <item android:maxLevel="1" android:drawable="@drawable/battery_1" />
    <item android:maxLevel="2" android:drawable="@drawable/battery_2" />
    <item android:maxLevel="3" android:drawable="@drawable/battery_3" />
    <item android:maxLevel="4" android:drawable="@drawable/battery_4" />
</level-list>

然后在layout中把image view的src设置成已创建好的xml文件
程序中变换图片时,只需要使用

imageview.getDrawable().setImageLevel(1);

Android会根据level的值自动选择对应的图片。手机显示剩余电量就是用这个方法来显示不同图片的。

6.2.6、TransitionDrawable

TransitionDrawable对应标签,transition是过渡,转变的意思,
对应于andnorid中的淡入淡出效果
基本使用如下:
这里写图片描述
代表相对于包含的view的上下左右的偏移量
具体使用如下:线性渐变转为径向渐变

<TextView
    android:id="@+id/test_transition"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:background="@drawable/transition_drawable"
    android:gravity="center"
    android:text="" />

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

    <item android:drawable="@drawable/shape_drawable_gradient_linear"/>
    <item android:drawable="@drawable/shape_drawable_gradient_radius"/>

</transition>

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

    <gradient
        android:centerColor="#00ff00"
        android:endColor="#0000ff"
        android:startColor="#ff0000"
        android:centerX="0.5"
        android:centerY="0.5"
        android:angle="0"
        android:type="linear" />

</shape>

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

    <gradient
        android:centerColor="#00ff00"
        android:endColor="#0000ff"
        android:startColor="#ff0000"
        android:gradientRadius="60"
        android:type="radial" />

</shape>

使用方法:

View v = findViewById(R.id.test_transition);
TransitionDrawable drawable = (TransitionDrawable) v.getBackground();
drawable.startTransition(1000);

拓展:
Android Transition Framwork 主要用来做三件事:
1. Activity间的转场动画;
2. 不同Activity或Fragment间元素共享,让交互更连贯;
3. 同一个Activity之间一些View的变换动画。
参见:http://www.jianshu.com/p/0af52be90ae6

6.2.7、InsetDrawable

insertDrawable对应标签,它可将其他Drawable内嵌到自己当中,适用于当一个view希望自己的背景比自己小的时候,LayerDrawable也可以实现这样的效果
基本用法如下:

这里写图片描述

这4个属性分别代表上下左右内凹的间距

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

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

如图所示

这里写图片描述
6.2.8、ScaleDrawable

对应标签,可以根据自己的等级,将scale缩放的一定的比例
基本用法如下:

这里写图片描述

android:scaleGravity表示位置
android:scaleHeight和android:scaleWidth表示对指定drawable(即android:drawable = “”)的宽高缩放比例,单位为百分比
比如:
android:scaleHeight = 20%
下面一个案例来说明让一个图片缩小为原大小的30%

在res/drawable/scale.xml

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/image1"
    android:scaleHeight="70%"
    android:scaleWidth="70%"
    android:scaleGravity="center" />
<TextView
    android:id="@+id/test_scale"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:background="@drawable/scale"
    android:gravity="center"
    android:text=""
    android:textColor="#ffffff" />

直接使用drawable资源是不行的,还要使用代码设置下等级为大于0小于10000的值

// test scale
View testScale = findViewById(R.id.test_scale);
ScaleDrawable testScaleDrawable = (ScaleDrawable) testScale.getBackground();
testScaleDrawable.setLevel(10);

6.2.8、ClipDrawable

ClipDrawable对应标签,可以根据当前等级来裁剪一个drawable
裁剪方向由android:clipOritation和andorid:grarity共同设置
基本用法如下:

这里写图片描述

android:clipOritation和LineaLayout的属性差不多,纵向和横向
andorid:grarity表示裁剪的方向
比如:bottom表示从上往下裁剪
下面举个例子,实现一张图片从上往下裁剪的效果:
首先在res/drawable/clip.xml

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

然后设置给view当做背景

<ImageView
    android:id="@+id/test_clip"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:gravity="center"
    android:src="@drawable/clip" />

然后在代码中设置等级,同理这个等级也是0~10000之间,0表示完全裁剪(就啥都没有了),10000表示不裁剪(跟没裁剪一样)

// test clip
ImageView testClip = (ImageView) findViewById(R.id.test_clip);
ClipDrawable testClipDrawable = (ClipDrawable) testClip.getDrawable();
testClipDrawable.setLevel(8000);

我们这里设置等级为8000,表示保留8000,裁剪掉了2000,即20%的区域

6.3、自定义Drawable

drawable的使用很单一,作为imageView的图像展示和作为view的背景展示
第五章中,我们知道系统会调用drawable的draw方法来绘制view的背景,那么我们也可以重写drawable的draw方法来自定义drawable
通常我们不需要去自定义drawable,因为自定义的drawable无法在xml中直接使用
特殊情况下,我们想自定义drawable也是可以的
下面我们来自定义drawable 来绘制一个圆形的drawable,并且半径会随着view的变化而变化

步骤如下:

1、继承drawable类
2、draw,setAlpha,setcolorFilter,getOpacity这几个方法是必须要实现的,draw是主要方法
完整代码如下:

package com.ryg.chapter_6.ui;

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;

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 r = getBounds();
        float cx = r.exactCenterX();
        float cy = r.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 cf) {
        mPaint.setColorFilter(cf);
        invalidateSelf();
    }

    @Override
    public int getOpacity() {
        // not sure, so be safe
        return PixelFormat.TRANSLUCENT;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值