Android--LayoutAnimation介绍
1、简介
在Android中,最简单的动画就是补间动画(Tweened Animations)了。通过补间动画,可以对一个控件进行位移、缩放、旋转、改变透明度等动画。但是补间动画只能对一个控件使用,如果要对某一组控件播放一样的动画的话,可以考虑layout-animation。
Layout Animation 可以用来为 ViewGroup 添加动画,并且按照预定的顺序把一个动画或者一个动画集合应用到 ViewGroup 的每一个子View。我们可以使用 LayoutAnimationController 来指定一个应用到 ViewGroup 的每个子View的动画。
2、LayoutAnimationsController
LayoutAnimationsController可以用于实现使多个控件按顺序一个一个的显示。
- LayoutAnimationsController用于为一个layout里面的控件,或者是一个ViewGroup里面的控件设置统一的动画效果。
- 每一个控件都有相同的动画效果。
- 控件的动画效果可以在不同的时间显示出来。
- LayoutAnimationsController可以在xml文件当中设置,以可以在代码当中进行设置。
3、Xml配置
1、在res/anim文件夹下创建一个名为layout_anim.xml文件
2、由于layout-animation是对于某一组控件的操作,就需要一个基本的动画来定义单个控件的动画。另外还可以定义动画的显示顺序和延迟:
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"android:delay="30%"android:animationOrder="reverse"android:animation="@anim/zoom_in"/>
- android:delay表示动画播放的延时,既可以是百分比,也可以是float小数。
- android:animationOrder表示动画的播放顺序,有三个取值normal(顺序)、reverse(倒序)、random(随机)。
- android:animation指向了子控件所要播放的动画。
其中delay的单位为秒,animation为设置动画的文件,animationOrder为进入方式。
<!-- res/anim/zoom_in.xml -->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"android:interpolator="@android:anim/decelerate_interpolator" ><scale
android:duration="1000"android:fromXScale="0.1"android:fromYScale="0.1"android:pivotX="50%"android:pivotY="50%"android:toXScale="1.0"android:toYScale="1.0" /><alpha
android:duration="1000"android:fromAlpha="0"android:toAlpha="1.0" />
</set>
我们写好了 LayoutAnimation 和 子动画,就要把它配置到我们的 ViewGroup里面,这里就用一个简单的ListView。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"><ListView
android:id="@+id/lv"android:scrollbars="vertical"android:layoutAnimation="@anim/layout_anim"android:layout_width="match_parent"android:layout_height="match_parent"/>
</LinearLayout>
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);ListView listView = (ListView) findViewById(R.id.lv);List<String> list = new ArrayList<String>();for(int i=0;i<20;i++){list.add("因人而异"+i);}ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);listView.setAdapter(adapter);}
}
因为我们在 Xml 中已经指定好 ListView 的 LayoutAnimation 啦,所以我们只要给它添加一个适配器就 OK了。
4、Java代码配置
Animation animation = AnimationUtils.loadAnimation(this, R.anim.zoom_in);
LayoutAnimationController lac=new LayoutAnimationController(animation);
lac.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(lac);
listView.startLayoutAnimation();
用 Java 代码配置就不用写LayoutAnimation啦,我们只要在上面的代码中手动去加载子动画,然后用LayoutAnimationController去把子动画配置到每一个子View中就可以啦。
可以看到我们把顺序已经被我们改为正序啦。
5、自定义播放顺序
通过上面的介绍,相信大家对 LayoutAnimationController 的功能已经有了一个比较清晰的认识,这种对 ViewGroup 的操作,对我们的动画效果有很大的帮助,但Android原生布局动画,仅支持顺序、倒序、随机3种动画执行顺序,这就使我们的动画有些简陋,不能适用于所有我们需要的效果。现在我就讲讲如何自定义一个播放 LayoutAnimation动画的顺序。
我们要自定义,首先就要知道 Android API 是如何实现顺序、倒序、随机这3种动画执行顺序的,我们来看看:
protected int getTransformedIndex(AnimationParameters params) {switch (getOrder()) {case ORDER_REVERSE:return params.count - 1 - params.index;case ORDER_RANDOM:if (mRandomizer == null) {mRandomizer = new Random();}return (int) (params.count * mRandomizer.nextFloat());case ORDER_NORMAL:default:return params.index;}}
Android 就是通过 getTransformedIndex 这个方法来实现的,代码很清晰,我们可以看到reverse,normal,random。count 就是ViewGroup里子View的总数,index 则是当前子View的索引。拿 reverse 来举例,不难发现,返回的 int 值随着 index 的增大而变小,可能你已经发现了,没错,这个返回的 int 值就是播放动画的顺序,这样 index 在后面的在播放动画的时候就变到前面播放啦。并且这个方法是protected的,明显就是可由子类来扩展。
public class MyLayoutAnimationController extends LayoutAnimationController {public enum OrderCustom {CUSTOMNORMAL,CUSTOMREVERSE}private Callback onIndexListener;public void setOnIndexListener(Callback onIndexListener) {this.onIndexListener = onIndexListener;}public MyLayoutAnimationController(Animation animation, float delay) {super(animation, delay);}public interface Callback {public int getTransformedIndex(MyLayoutAnimationController controller, int count, int index);}@Overrideprotected int getTransformedIndex(AnimationParameters params) {if (onIndexListener != null) {return onIndexListener.getTransformedIndex(this, params.count, params.index);} else {return super.getTransformedIndex(params);}}public static MyLayoutAnimationController generateController(Animation animation, float delay) {return generateController(animation, delay, null);}public static MyLayoutAnimationController generateController(@NonNull Animation animation,float delay, @Nullable final OrderCustom custom) {MyLayoutAnimationController controller = new MyLayoutAnimationController(animation, delay);controller.setOnIndexListener(new Callback() {@Overridepublic int getTransformedIndex(MyLayoutAnimationController controller, int count, int index) {if (custom != null) {switch (custom) {case CUSTOMNORMAL:return Utils.getTransformedIndex(count, index);case CUSTOMREVERSE:return Utils.getTransformedIndexREVERSE(count, index);default:break;}}return index;}});return controller;}public static void setLayoutAnimation(@NonNull ViewGroup viewGroup,@NonNull Animation animation, float delay, @Nullable final OrderCustom custom) {MyLayoutAnimationController controller = generateController(animation, delay, custom);viewGroup.setLayoutAnimation(controller);}public static void setLayoutAnimation(@NonNull ViewGroup viewGroup,@AnimRes int animResId, float delay, @Nullable final OrderCustom custom) {Animation animation = AnimationUtils.loadAnimation(viewGroup.getContext(), animResId);setLayoutAnimation(viewGroup, animation, delay, custom);}
}
上面的代码就是我自定义的 LayoutAnimation 的动画顺序的实现,首先我们当然要为我们的自定义属性赋值。
public enum OrderCustom {CUSTOMNORMAL,CUSTOMREVERSE}
根据当前枚举类型的值,确定调用哪一种我们定义的顺序。
我把实现顺序的代码放进一个 Utils.java里:
public class Utils {private Utils() {throw new RuntimeException("工具类禁止新建实例");}public static int getTransformedIndexREVERSE(int count, int index){return (count-1) - getTransformedIndex(count, index);}public static int getTransformedIndex(int count, int index){if (index%2==0){//1:index为偶数的项return index/2;}else {//2:index为奇数的项if(count%2==0){//2.1:当总项数是偶数return (count/2-1) + (index+1)/2;}else {//2.2:当总项数是奇数return (count/2) + (index+1)/2;}}}
}
可以看出 CUSTOMNORMAL 对应的是 getTransformedIndex 方法,而方法的目的就是改变当前索引的值,也就是改变当前子View的播放顺序。经过这个方法,我们原来的索引0,2,4…就变成了0,1,2..,1,3,5..就变成了count/2 + 1,count/2 + 2,count/2 + 3啦,也就是先正序播放索引为偶数的,再正序播放索引为奇数的。
getTransformedIndexREVERSE 方法则正好相反,会倒序播放索引为偶数的,再倒序播放索引为奇数的。
private Callback onIndexListener;public void setOnIndexListener(Callback onIndexListener) {this.onIndexListener = onIndexListener;
}public interface Callback {public int getTransformedIndex(MyLayoutAnimationController controller, int count, int index);
}
CallBack 就是我为 MyLayoutAnimationController 设置的回调监听器,去做参数传递和枚举值选择。
@Override
protected int getTransformedIndex(AnimationParameters params) {if (onIndexListener != null) {return onIndexListener.getTransformedIndex(this, params.count, params.index);} else {return super.getTransformedIndex(params);}
}
这就是我们复写的 getTransformedIndex,它会自动调用。这里就用到了我们的 CallBack,如果监听器不为空,则调用CallBack 的getTransformedIndex 去调用我们写得自定义控件播放动画的顺序。否则就调用父类的。
public static MyLayoutAnimationController generateController(@NonNull Animation animation,float delay, @Nullable final OrderCustom custom) {MyLayoutAnimationController controller = new MyLayoutAnimationController(animation, delay);controller.setOnIndexListener(new Callback() {@Overridepublic int getTransformedIndex(MyLayoutAnimationController controller, int count, int index) {if (custom != null) {switch (custom) {case CUSTOMNORMAL:return Utils.getTransformedIndex(count, index);case CUSTOMREVERSE:return Utils.getTransformedIndexREVERSE(count, index);default:break;}}return index;}});return controller;
}
generateController 就是我们用来创建 MyLayoutAnimationController 对象,并且构建监听器的方法。
public static void setLayoutAnimation(@NonNull ViewGroup viewGroup,@NonNull Animation animation, float delay, @Nullable final OrderCustom custom) {MyLayoutAnimationController controller = generateController(animation, delay, custom);viewGroup.setLayoutAnimation(controller);
}public static void setLayoutAnimation(@NonNull ViewGroup viewGroup,@AnimRes int animResId, float delay, @Nullable final OrderCustom custom) {Animation animation = AnimationUtils.loadAnimation(viewGroup.getContext(), animResId);setLayoutAnimation(viewGroup, animation, delay, custom);
}
最后就是我们用来与外部交互的方法啦,根据指定的动画、单个子View动画延时、子View动画执行顺序算法枚举值 创建一个新的MyLayoutAnimationController实例,将此实例作为参数为viewGroup设置布局动画。
代码看上去有些复杂却并不难理解,关键还是如何去复写getTransformedIndex。
现在就把它添加到我们的代码中。
SwitchActivity.java:
public class SwitchActivity extends AppCompatActivity {private LinearLayout ll = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.button);ll = (LinearLayout) findViewById(R.id.ll);int count = ll.getChildCount();for(int i =0;i<count;i++){final int index = i;ll.getChildAt(i).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(SwitchActivity.this, CustomActivity.class);intent.putExtra("index",index);startActivity(intent);}});}}
}
布局就是两个 Button 用来选择使用的自定义控件播放动画的顺序。通过点击的Button的在LinearLayout中索引。
CustomActivity.java:
public class CustomActivity extends AppCompatActivity {private MyLayoutAnimationController.OrderCustom[] customs = new MyLayoutAnimationController.OrderCustom[]{MyLayoutAnimationController.OrderCustom.CUSTOMNORMAL,MyLayoutAnimationController.OrderCustom.CUSTOMREVERSE};private int color = Constant.color_flyme_blue_sky;private LinearLayout ll = null;private int anim = R.anim.scale_anim;private int index = 0;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);index = getIntent().getIntExtra("index", index);int customIndex = index % customs.length;setContentView(R.layout.scale);ll = (LinearLayout) findViewById(R.id.ll);for (int i = 0; i < ll.getChildCount(); i++) {LinearLayout layout = (LinearLayout) ll.getChildAt(i);for (int j = 0; j < layout.getChildCount(); j++) {layout.getChildAt(j).setBackgroundColor(color);}MyLayoutAnimationController.setLayoutAnimation(layout, anim, 0.8f, customs[customIndex]);customIndex = (customIndex + 1) % customs.length;}}
}
这就是实现我们动画的 Activity 啦,activity_main.xml 里有两个LinearLayout,分别有四个Button,这两个LinearLayout分别实现我们自定义的这两种播放动画的顺序。
color是一个对颜色收集的常量类。
public final class Constant {//4种常用背景色public static final int color_info = 0XFF2094F3; //信息public static final int color_confirm = 0XFF4CB04E; //确认public static final int color_warning = 0XFFFEC005; //警告public static final int color_danger = 0XFFF44336; //危险//中国传统36色public static final int color_cn_zhuqing = 0XFF7D9768; //竹青public static final int color_cn_wan = 0XFFBE968E; //绾public static final int color_cn_li = 0XFF76664D; //黎public static final int color_cn_huanglu = 0XFFE3A335; //黄栌public static final int color_cn_ou = 0XFFEED0D8; //藕public static final int color_cn_chabai = 0XFFEFF4ED; //茶白public static final int color_cn_zitan = 0XFF6A2C1F; //紫檀public static final int color_cn_cang = 0XFF8EA7AB; //苍public static final int color_cn_dingxiang = 0XFFD6B5D4; //丁香public static final int color_cn_yuebai = 0XFFEEF6F8; //月白public static final int color_cn_su = 0XFFE1EEE7; //素public static final int color_cn_lanhui = 0XFF9CAAC4; //蓝灰public static final int color_cn_yaluanqing = 0XFFEAF5F1; //鸭卵青public static final int color_cn_xiangyabai = 0XFFFEFEF6; //象牙白public static final int color_cn_ya = 0XFFE9DDB5; //牙public static final int color_cn_xue = 0XFFF8FCFD; //雪public static final int color_cn_dailan = 0XFF566177; //黛蓝public static final int color_cn_shuilv = 0XFFD3EAE2; //水绿public static final int color_cn_wuhei = 0XFF392E3F; //乌黑public static final int color_cn_shuang = 0XFFE9F0F8; //霜public static final int color_cn_fei = 0XFFED5736; //妃public static final int color_cn_mohui = 0XFF748A98; //墨灰public static final int color_cn_xuehui = 0XFFEDEDEF; //雪灰public static final int color_cn_yanzhi = 0XFF97282F; //胭脂public static final int color_cn_yaqing = 0XFF424B50; //鸦青public static final int color_cn_zi = 0XFF493131; //淄public static final int color_cn_qihei = 0XFF131522; //漆黑public static final int color_cn_haitanghong = 0XFFD13658; //海棠红public static final int color_cn_mo = 0XFF272923; //墨public static final int color_cn_liuhuang = 0XFFC9DD23; //柳黄public static final int color_cn_tuoyan = 0XFFF99070; //酡颜public static final int color_cn_pinhong = 0XFFF00057; //品红public static final int color_cn_yan = 0XFFD36870; //嫣public static final int color_cn_xueqing = 0XFFA49BC8; //雪青public static final int color_cn_feicui = 0XFF5BB995; //翡翠public static final int color_cn_hupo = 0XFFCA6924; //琥珀//flyme6中7配色public static final int color_flyme_blue_sky = 0XFF198DED; //天蓝public static final int color_flyme_blue_green = 0XFF04C0CF; //蓝绿public static final int color_flyme_green = 0XFF3BC06B; //绿public static final int color_flyme_yellow = 0XFFFFBE26; //黄public static final int color_flyme_orange = 0XFFFC5B23; //橙public static final int color_flyme_red_dark = 0XFFD33A2A; //深红public static final int color_flyme_red_bright = 0XFFF12528; //鲜红private Constant(){throw new RuntimeException("禁止创建实例!");}
}
动画也很简单,scale_anim.xml:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"android:duration="500"android:fromXScale="1.0"android:toXScale="0.1"android:pivotX="50%"android:pivotY="50%"android:fromYScale="1.0"android:toYScale="0.1" />
可以看到点击不同的 Button,上下两个 LinearLayout 的子View动画播放顺序就交换啦。
好啦,关于LayoutAnimation的介绍就到这里。
结束语:本文仅用来学习记录,参考查阅。
Android--LayoutAnimation介绍相关推荐
- Android LayoutAnimation使用及扩展
文章来源 在Android中,最简单的动画就是补间动画了.通过补间动画,可以对一个控件进行位移.缩放.旋转.改变透明度等动画.但是补间动画只能对一个控件使用,如果要对某一组控件播放一样的动画的话,可以 ...
- android AsyncTask介绍(转)
android AsyncTask介绍 AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接 ...
- Android类库介绍
Android类库介绍 GPhone开发包Android SDK含了很多丰富的类库: android.util 涉及系统底层的辅助类库 android.os 提供了系统服务.消息传输.IPC管道 an ...
- 1.android体系结构介绍
一.Android的介绍 android介绍见百度百科:Android的介绍,度娘把Android介绍的这么清楚,如果谷歌是Android的爹,那度娘就是娘了. 二.Android的架构图 andro ...
- 【转】Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
原文网址:http://blog.csdn.net/xubin341719/article/details/38584469 关键词:蓝牙blueZ A2DP.SINK.sink_connect.s ...
- 作业Android自我介绍
***Android自我介绍***
- Android HIDL 介绍学习之客户端调用
应上一篇文章Android HIDL 介绍学习_Super Jang的博客-CSDN博客_安卓hidl读者的要求,本文更新客户端调用方法. hidl的客户端调用相比服务端的实现要简单很多,本次我们通过 ...
- Android开发介绍
Android开发介绍 这个教程设计是帮助你学习基础的Android开发和快速搭建您的开发环境.这个是在我的Window 7上编写的,当然它也支持Linux(uBuntu).Mac OS其他支持And ...
- Android ViewGroup介绍+实例,大厂架构师经验分享
//每一行的高度,累加至height int lineHeight = 0; int count = getChildCount(); int left = getPaddingLeft(); int ...
- android 模拟器的使用(Android模拟器介绍及创建)
做了这么久的android开发,一直想把在开发过程中积累的经验或问题总结一下,可是都没有时间,现在有一点点空闲,所以慢慢把我在android中遇到的问题整理一下写出来,供自己以后参考,也希望和大家一起 ...
最新文章
- FckEditor-未能映射路径/UserFiles/image/
- Redis专题-持久化方式
- php 二进制权限,基于二进制位的权限控制(数据库里的二进制)
- 51nod 1680区间求和 (dp+树状数组/线段树)
- 计算机网络大连理工大学,大连理工大学计算机网络.doc
- 2013应届毕业生“人人网”校招应聘总结
- c语言char a[10]; sprintf(a,%d,n);,c语言输入输出的一些细节
- 在Ubuntu上安装Docker –分步指南
- Asp.net中汉字转换成为拼音
- Ubuntu HDMI连接后没有声音解决办法
- 微信开发者工具 the permission value is offline verifying 异常
- 【Linux】VirtualBox设置静态ip
- matlab实现证件照换底+美肤的功能
- delphi xe 10.3 firemonkey stringdrig 插入,删除,添加
- Error: keywords ‘java|openjdk version‘ not found in ‘picked up java_tool_options: -df‘
- RabbitMQ mandatory参数 路由器匹配不到队列返回响应
- 异常检测FastFlow论文详解
- 旅游自助管理信息系统概要设计规格 .
- sap miro_使用Miro的Android,iPhone和PSP的简单拖放视频转换
- 倍福--时间戳模块使用
热门文章
- IJCAI 2021 | 会议摘要有难度?快来引入对话篇章结构信息
- 应急医疗通讯解决方案|MESH无线自组网系统
- 教你如何用python俘获女神芳心
- 华为APP安装问题:更新包与已安装应用的签名不一致
- 一、T100之料件管理
- 一次工作失误(理清思路的重要性和事前验证的重要性)
- STEMWIN开发记录指南—-从外部flash显示图片
- 仿微信在对话框文字中插入Emoji表情包
- Paper笔记: 《Towards Evaluating the Robustness of Neural Networks》(CW攻击)
- 怎样知道android的手机号码,怎么看sim卡上自己手机号码是多少 在SIM卡背后的序列号中...