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介绍相关推荐

  1. Android LayoutAnimation使用及扩展

    文章来源 在Android中,最简单的动画就是补间动画了.通过补间动画,可以对一个控件进行位移.缩放.旋转.改变透明度等动画.但是补间动画只能对一个控件使用,如果要对某一组控件播放一样的动画的话,可以 ...

  2. android AsyncTask介绍(转)

    android AsyncTask介绍 AsyncTask和Handler对比 1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接 ...

  3. Android类库介绍

    Android类库介绍 GPhone开发包Android SDK含了很多丰富的类库: android.util 涉及系统底层的辅助类库 android.os 提供了系统服务.消息传输.IPC管道 an ...

  4. 1.android体系结构介绍

    一.Android的介绍 android介绍见百度百科:Android的介绍,度娘把Android介绍的这么清楚,如果谷歌是Android的爹,那度娘就是娘了. 二.Android的架构图 andro ...

  5. 【转】Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析

    原文网址:http://blog.csdn.net/xubin341719/article/details/38584469 关键词:蓝牙blueZ  A2DP.SINK.sink_connect.s ...

  6. 作业Android自我介绍

    ***Android自我介绍***

  7. Android HIDL 介绍学习之客户端调用

    应上一篇文章Android HIDL 介绍学习_Super Jang的博客-CSDN博客_安卓hidl读者的要求,本文更新客户端调用方法. hidl的客户端调用相比服务端的实现要简单很多,本次我们通过 ...

  8. Android开发介绍

    Android开发介绍 这个教程设计是帮助你学习基础的Android开发和快速搭建您的开发环境.这个是在我的Window 7上编写的,当然它也支持Linux(uBuntu).Mac OS其他支持And ...

  9. Android ViewGroup介绍+实例,大厂架构师经验分享

    //每一行的高度,累加至height int lineHeight = 0; int count = getChildCount(); int left = getPaddingLeft(); int ...

  10. android 模拟器的使用(Android模拟器介绍及创建)

    做了这么久的android开发,一直想把在开发过程中积累的经验或问题总结一下,可是都没有时间,现在有一点点空闲,所以慢慢把我在android中遇到的问题整理一下写出来,供自己以后参考,也希望和大家一起 ...

最新文章

  1. FckEditor-未能映射路径/UserFiles/image/
  2. Redis专题-持久化方式
  3. php 二进制权限,基于二进制位的权限控制(数据库里的二进制)
  4. 51nod 1680区间求和 (dp+树状数组/线段树)
  5. 计算机网络大连理工大学,大连理工大学计算机网络.doc
  6. 2013应届毕业生“人人网”校招应聘总结
  7. c语言char a[10]; sprintf(a,%d,n);,c语言输入输出的一些细节
  8. 在Ubuntu上安装Docker –分步指南
  9. Asp.net中汉字转换成为拼音
  10. Ubuntu HDMI连接后没有声音解决办法
  11. 微信开发者工具 the permission value is offline verifying 异常
  12. 【Linux】VirtualBox设置静态ip
  13. matlab实现证件照换底+美肤的功能
  14. delphi xe 10.3 firemonkey stringdrig 插入,删除,添加
  15. Error: keywords ‘java|openjdk version‘ not found in ‘picked up java_tool_options: -df‘
  16. RabbitMQ mandatory参数 路由器匹配不到队列返回响应
  17. 异常检测FastFlow论文详解
  18. 旅游自助管理信息系统概要设计规格 .
  19. sap miro_使用Miro的Android,iPhone和PSP的简单拖放视频转换
  20. 倍福--时间戳模块使用

热门文章

  1. IJCAI 2021 | 会议摘要有难度?快来引入对话篇章结构信息
  2. 应急医疗通讯解决方案|MESH无线自组网系统
  3. 教你如何用python俘获女神芳心
  4. 华为APP安装问题:更新包与已安装应用的签名不一致
  5. 一、T100之料件管理
  6. 一次工作失误(理清思路的重要性和事前验证的重要性)
  7. STEMWIN开发记录指南—-从外部flash显示图片
  8. 仿微信在对话框文字中插入Emoji表情包
  9. Paper笔记: 《Towards Evaluating the Robustness of Neural Networks》(CW攻击)
  10. 怎样知道android的手机号码,怎么看sim卡上自己手机号码是多少 在SIM卡背后的序列号中...