在activity中实现动画,非常简单。得益于Animation类。但是在widget中实现动画效果,确很麻烦。由于widget中的限制太多,可以使用的控件太少。Gallery之类的都不支持,除非自己在源码环境中自定义添加,使RemoteViews支持。但是不是很实用,只合适编译到Rom中的应用。
由于项目需要实现在一个widget中的imageView里面,多张图片定时切换,并且须带淡入淡出的效果。并且该widget的布局还相对有点复杂,并非简单的就一个imageView控件,其中还包含GridView以及StackView这种显示数据比较多的控件。
查看资料,发现widget中只能使用LayoutAnimation,而LayoutAnimation这个类呢很特别,只有第一次加载的时候才会使包含在该布局内的控件使用指定的动画效果,之后就不会执行内部指定的动画。因此首先想到的是,把动画的执行次数设为infinite,即无限次,那么动画就不会停止了。但是这种方式只合适初始化时的等待动画。在该项目中不适合,因为,需要定时去切换图片,比如3秒,而RemoteViews支持的贴图接口就是setImageView类似这种,一次贴一张的,那么肯定需要一个定时器去计时,时间到了,则去贴一张新图。如果把动画的repeatCount设为无限次,而且动画本身的duration就相当于一个定时器,动画一旦开始,就会按照该时间,无限循环。,因此必须两个动作,即贴图的动作周期和动画执行周期完全一致,才有可能做到上一张图片执行完动画,下一张图片刚好贴上,继续从头开始执行动画。但是这两个定时器之间的同步是不可能的。因为动画的执行时间非常严格没有延时,而贴图动作确存在延时,首先不可能完全同时开始计时,其次贴图动作须在主线程中,加入的是主线程的消息队列,所以就会出现消息处理的延时。
那么唯一的方法就是,遵循加载布局的时候,重新执行动画。这就需要两个完全一样的布局,在贴图前进行切换,但是网上的资料,都是直接把主布局切换掉,对于界面非常简单的数据不多的widget可以这样,但是复杂布局的话,开销太大,不现实。
仔细看了官方文档,发现了RemoteViews的两个接口,哈哈,利用这两个接口,则可以实现,切换掉单个控件的布局,来达到实现轮训动画的目的。 一个是removeAllViews(viewId),另一个是addViews(viewId,nestedView) removeAllVIew则是将制定viewId中的子view清空,而addViews,则是将nestedView中的子view加入到viewId中,同时放入调用者的RemoteViews中。有这样两个接口,那么实现局部的布局切换就简单了。在Res下新建两个布局文件,布局完全一样,只是文件名不同,在布局中就包含单个imageView。在需要切图之前把之前的布局remove掉,放入新的布局。那么就会执行一次动画,以此循环调用,就ok了。
实现步骤:
1 、在Res下,新建一个anim文件夹,在其中设置LayoutAnimation的动画效果。和Activity中一样,只是类为LayoutAnimation如:
<?xml version="1.0" encoding="utf-8"?> <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:animation="@anim/set_fadein" />2 、在Res下的布局文件夹下,添加你需要实现动画的控件的布局,同时需和主布局中的设置一致。
主布局中需要实现动画的imageView设置如下:
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layoutAnimation="@anim/fade" android:id="@+id/special_anim"> <ImageView android:layout_width="fill_parent" android:layout_height="wrap_content" android:scaleType="fitXY" android:id="@+id/special_view"/> </LinearLayout>
在布局中加入layoutAnimation,引用动画效果。其中就只包含一个imageView
3、新建两个布局文件,比如文件名为image1.xml 、image2.xml,其中
image1.xml设置如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layoutAnimation="@anim/fade" android:id="@+id/special_anim1"> <ImageView android:layout_width="fill_parent" android:layout_height="wrap_content" android:scaleType="fitXY" android:id="@+id/special_view"/> </LinearLayout>
image2.xml设置如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layoutAnimation="@anim/fade" android:id="@+id/special_anim2"> <ImageView android:layout_width="fill_parent" android:layout_height="wrap_content" android:scaleType="fitXY" android:layout_marginRight="3dp" android:id="@+id/special_view"/> </LinearLayout>
4、在切换贴图时,作如下处理,即可以实现,每次图片间切换,都可以带上动画效果。
if(layoutId == 1){ RemoteViews subViews = new RemoteViews(this.getPackageName(),R.layout.image2); updateViews.removeAllViews(R.id.special_anim1); updateViews.addView(R.id.special_anim, subViews); updateViews.setImageViewBitmap(R.id.special_view, Bitmap[index]); layoutId = 2; }else{ RemoteViews subViews = new RemoteViews(this.getPackageName(),R.layout.imagelayout1); updateViews.removeAllViews(R.id.special_anim2); updateViews.addView(R.id.special_anim, subViews); updateViews.setImageViewBitmap(R.id.special_view,Bitmap[index]); layoutId = 1; }