转载请注明出处(万分感谢!):
http://blog.csdn.net/javazejian/article/details/52247337
出自【zejian的博客】
关联文章:
领略千变万化的Android Drawable (一)
领略千变万化的Android Drawable (二)
hello,上篇我们已经分析6种Drawable的使用方法,本篇咱们就继续剩下的Drawable~,闲话莫多说,那就直接开始吧。
7、TransitionDrawable
很多时候我们在实现渐变的动画效果时,都会使用到animation,但实际上我们有既简单又完美的解决方法,没错,它就是TransitionDrawable啦,TransitionDrawable用于实现两个Drawable之间的淡入淡出的效果,它对应的是<transition>标签;其语法如下:
<?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>
语法中的属性比较简单,其中 android:top,android:bottom,android:left,android:right分别表示Drawable四周的偏移量。
android:id
资源ID,drawable资源的唯一标识。使用”@+id/name”方式来给这个item定义一个新的资源ID。可以使用View.findViewById()或者 Activity.findViewById()等方式检索和修改这个item。
同样,我们来看一个实例:
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/image1"/>
<item android:drawable="@drawable/image2" />
</transition>
引用如下:
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@drawable/transition_drawable"
/>
通过它的startTransition和reverseTransition方法实现淡入淡出效果,代码如下:
TransitionDrawable drawable= (TransitionDrawable) imageView.getBackground();
drawable.startTransition(4000);
如果在imageView设置的src属性
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/transition_drawable"
/>
代码控制为:
TransitionDrawable drawable= (TransitionDrawable) imageView.getDrawable();
drawable.startTransition(4000);
最终效果:
最后我们给出代码实现的方式,比较简单,这里不过多分析:
ImageView imageView= (ImageView) findViewById(R.id.tranImage);
Bitmap bitmap1= BitmapFactory.decodeResource(getResources(), R.drawable.image1);
Bitmap bitmap2= BitmapFactory.decodeResource(getResources(), R.drawable.image2);
final TransitionDrawable td = new TransitionDrawable(new Drawable[] { new BitmapDrawable(getResources(), bitmap1),
new BitmapDrawable(getResources(), bitmap2) });
imageView.setImageDrawable(td);
td.startTransition(4000);
8、InsetDrawable
有时候我们可能需要为一个全屏的LinearLayout布局指定背景图,但我们不想让背景图充满屏幕,这时我们就需要使用到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:drawable="@drawable/drawable_resource"
android:insetTop="dimension"
android:insetRight="dimension"
android:insetBottom="dimension"
android:insetLeft="dimension" />
属性解释:
属性 | 含义 |
---|---|
android:insetTop | 图像距离上边的距离 |
android:insetRight | 图像距离右边的距离 |
android:insetBottom | 图像距离底边的距离 |
android:insetLeft | 图像距离左边的距离 |
直接看个例子吧,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetBottom="10dp"
android:drawable="@drawable/transition_bg_1"
android:insetTop="10dp"
android:insetLeft="10dp"
android:insetRight="10dp"
>
</inset>
直接作为根布局的背景
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/inset_drawable"
tools:context="com.zejian.drawble.MainActivity">
</RelativeLayout>
效果如下:
9、ScaleDrawable
ScaleDrawable对应<scale>标签,主要基于当前的level,对指定的Drawable进行缩放操作。有点需要特别注意的是我们如果定义好了ScaleDrawable,要将其显示出来的话,必须给ScaleDrawable设置一个大于0小于10000的等级(级别越大Drawable显示得越大,等级为10000时就没有缩放效果了),否则将无法正常显示。我们可以看看其draw函数的源码:
@Override
public void draw(Canvas canvas) {
final Drawable d = getDrawable();
if (d != null && d.getLevel() != 0) {
d.draw(canvas);
}
}
很明显d.getLevel() != 0
才会去把当前drawable画在画布上然后显示在屏幕上,我们知道这点后再来看看其语法:
<?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" />
android:gravity
当图片小于容器尺寸时,设置此选项可以对图片经典定位,这个属性比较多,不同选项可以使用‘|’来组合使用。
可选项 | 含义 |
---|---|
top | 将图片放在容器顶部,不改变图片大小 |
bottom | 将图片放在容器底部,不改变图片大小 |
left | 将图片放在容器左侧,不改变图片大小 |
right | 将图片放在容器右侧,不改变图片大小 |
center_vertical | 图片竖直居中,不改变图片大小 |
fill_vertical | 图片竖直方向填充容器 |
center_horizontal | 图片水平居中,不改变图片大小 |
fill_horizontal | 图片水平方向填充容器 |
center | 使图片在水平方向和竖直方向同时居中,不改变图片大小 |
fill | 图片填充容器,默认值 |
clip_vertical | 竖直方向剪切,很少使用 |
clip_horizontal | 水平方向剪切,很少使用 |
android:scaleHeight
表示Drawable的高的缩放比例,值越大,内部Drawable的高度显示得越小,例如android:scaleHeight=”70%”,那么显示时Drawable的高度只有原来的30%。
android:scaleWidth
表示Drawable的宽的缩放比例,值越大,内部Drawable的宽显示得越小,例如android:scaleWidth=”70%”,那么显示时Drawable的宽度只有原来的30%。
直接来看个例子呗,我们设置两组宽高分别缩放70%和30%,然后来对比一下情况
<?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"
>
</scale>
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/image1"
android:scaleHeight="30%"
android:scaleWidth="30%"
android:scaleGravity="center"
>
</scale>
必须在java调用设置level(默认为0)的代码才可以正常显示:
ImageView scaleImage= (ImageView) findViewById(R.id.scaleImage);
ScaleDrawable scale= (ScaleDrawable) scaleImage.getBackground();
scale.setLevel(1);
效果对比如下:
我们再来对比一下宽高同等缩放比例(50%)下,level对Drawable的影响效果,分别设置level等级为1,5000,10000.
10、ClipDrawable
ClipDrawable是通过设置一个Drawable的当前显示比例来裁剪出另一张Drawable,我们可以通过调节这个比例来控制裁剪的宽高,以及裁剪内容占整个View的权重,通过ClipDrawable的setLevel()方法控制显示比例,ClipDrawable的level值范围在[0,10000],level的值越大裁剪的内容越少,当level为10000时则完全显示,而0表示完全裁剪,不可见。需要注意的是在给clip元素中android:drawable属性设置背景图片时,图片不能是9图,因为这涉及到裁剪这张图片,如果设置为九图,裁剪的实际情况会与想要的效果不一样。ClipDrawable对应xml的<clip>标签,其语法如下:
<?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"] />
其中android:clipOrientation和android:gravity属性共同控制Drawable被裁剪的方向,其中clipOrientation表示裁剪的方向(水平和垂直两种),gravity比较复杂必须和clipOrientation一起才能起作用,同样的我们可以通过“|”来组合使用gravity的属性值。gravity属性值说明如下:
属性值 | 描述 |
---|---|
top | 将这个对象放在容器的顶部,不改变其大小。当clipOrientation 是”vertical”,裁剪从底部开始 |
bottom | 将这个对象放在容器的底部,不改变其大小。当clipOrientation 是 “vertical”,裁剪从顶部(top)开始 |
left | 将这个对象放在容器的左部,不改变其大小。当clipOrientation 是 “horizontal”,裁剪从drawable的右边(right)开始,默认值 |
right | 将这个对象放在容器的右部,不改变其大小。当clipOrientation 是 “horizontal”,裁剪从drawable的左边(left)开始 |
center_vertical | 将对象放在垂直中间,不改变其大小,如果clipOrientation 是 “vertical”,那么从上下同时开始裁剪 |
fill_vertical | 垂直方向上不发生裁剪。(除非drawable的level是 0,才会不可见,表示全部裁剪完) |
center_horizontal | 将对象放在水平中间,不改变其大小,clipOrientation 是 “horizontal”,那么从左右两边开始裁剪 |
fill_horizontal | 水平方向上不发生裁剪。(除非drawable的level是 0,才会不可见,表示全部裁剪完) |
center | 将这个对象放在水平垂直坐标的中间,不改变其大小。当clipOrientation 是 “horizontal”裁剪发生在左右。当clipOrientation是”vertical”,裁剪发生在上下。 |
fill | 填充整个容器,不会发生裁剪。(除非drawable的level是 0,才会不可见,表示全部裁剪完)。 |
clip_vertical | 附加选项,表示竖直方向的裁剪,很少使用 |
clip_horizontal | 附加选项,表示水平方向的裁剪,很少使用 |
ClipDrawable属性介绍完了,直接来个实战吧,
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/image1"
android:clipOrientation="horizontal"
android:gravity="right"
>
</clip>
在上面的xml中我们实现了左侧裁剪的效果,因此应将clipOrientation设置为水平方向裁剪,gravity要设置为right。然后应用到我的ImageView上代码如下:
<ImageView
android:id="@+id/clipImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@drawable/clip_drawable"
/>
接着在代码中设置ClipDrawable的等级,代码如下:
ImageView clipImage= (ImageView) findViewById(R.id.clipImage);
ClipDrawable clip= (ClipDrawable) clipImage.getBackground();
clip.setLevel(6000);
因为这里我们在xml引用时设置的是背景图所以使用clipImage.getBackground()
,如果在xml引用时使用的是src,那么就使用clipImage.getDrawable()
即可。前面我们已经提到过,ClipDrawable的等级范围是[0,10000],而且level越大裁剪区域越少,当level=10000时,表示不裁剪,我们在这里设置了level为6000则表示裁剪40%的区域,效果如下:
最后我们来实现一个案例,在实际开发中经常会使用到动画来实现一些特殊效果,比如我们可能需要实现一个徐徐展开的图片,这时我们的ClipDrawable就派上用场了,接着我们就是利用ClipDrawable来实现一个拥有徐徐展开效果的图片
思路:
因为ClipDrawable的setLevel(int level)可以控制截取图片的部分,因此我们可以设置一个定时器,让程序每隔一段时间就调用ClipDrawable的setLevel(int level)方法即可实现图片徐徐展开效果。
我们首先来实现一个clip_drawable_image.xml,并设置clipOrientation=”horizontal”,即水平剪切,以及设置gravity=”center”,即左右同时裁剪,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/image1"
android:clipOrientation="horizontal"
android:gravity="center">
</clip>
接着在activity_clip.xml文件布局中引用:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:scaleType="fitStart"
android:src="@drawable/clip_drawable_image"
/>
</RelativeLayout>
代码调用如下:
package com.zejian.drawble;
import android.app.Activity;
import android.graphics.drawable.ClipDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by zejian
* Time 16/8/19.
* Description:
*/
public class Clip_Activity extends Activity {
private final static int IS_CONTUNUE=0x22;
private ClipDrawable drawable;
private ImageView imageView;
Timer timer = new Timer();
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == IS_CONTUNUE) {
/**setlevel()设置图片截取的大小
* 修改ClipDrawable的level值,level值为0--10000;
* 10000:截取图片大小为空白,0:截取图片为整张图片;
*/
drawable.setLevel(drawable.getLevel() + 200);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clip);
imageView = (ImageView) findViewById(R.id.image);
//获取图片所显示的ClipDrawable对象
drawable = (ClipDrawable) imageView.getDrawable();
//定时器
timer.schedule(new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.what = IS_CONTUNUE;
handler.sendMessage(msg);
if (drawable.getLevel() >= 10000) {
timer.cancel();
}
}
}, 0, 200);
}
}
效果如下:
11、ColorDrawable
ColorDrawable 是最简单的Drawable,它实际上是代表了单色可绘制区域,它包装了一种固定的颜色,当ColorDrawable被绘制到画布的时候会使用颜色填充Paint,在画布上绘制一块单色的区域。 在xml文件中对应<color>标签,它只有一个android:color属性,通过它来决定ColorDrawable的颜色。
xml实现如下:
<?xmlversion="1.0" encoding="utf-8"?>
<color xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/normal"
/>
也可以使用代码实现,注意传入的颜色值为16进制的数字:
ColorDrawable cd = new ColorDrawable(0xff000000);
ImageView iv = (ImageView)findViewById(...);
iv.setImageDrawable(cd);
12、GradientDrawable
GradientDrawable 表示一个渐变区域,可以实现线性渐变、发散渐变和平铺渐变效果,实际上这个我们在上一篇的shapeDrawable中就已经分析过了,忘了可以回头复习一下哈~,其对应的标签为<gtadient>一般都是配置shapeDrawable来使用,为其实现渐变颜色。这里给出简单案例如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<gradient android:angle="90"
android:startColor="@color/colorPrimary"
android:centerColor="#fff"
android:endColor="@color/color_state"
android:type="linear"
/>
</shape>
当然GradientDrawable也可以作为View的背景图,案例代码实现如下:
//分别为开始颜色,中间夜色,结束颜色
int colors[] = { 0xff255779 , 0xff3e7492, 0xffa6c0cd };
GradientDrawable gd = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
最后设置给View的背景图即可。
setBackgroundDrawable(gd);
代码实现GradientDrawable还可以设置边框,圆角,边框宽度等等,这里我们就不深究了,感兴趣可以自行研究一下。
到此,常用的Drawable我们已经全部介绍完了,告一段落了哈~,下一篇我们将继续分享如何实现自定义Drawable,欢迎关注。
领略千变万化的Android Drawable (一)
领略千变万化的Android Drawable (二)
主要参考资料:
《android开发艺术探索》
《google android官网》