原来不知道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"
/>
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>
<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 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>
<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>
<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>
<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>
<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>
<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"
/>
<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) ;
}
}
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>
<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) ;
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 ;
}
}
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 ;
}
}