1.5.36 Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition

本文主要是介绍1.5.36 Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Property animation系统还提供了对ViewGroup中的View改变加入动画的功能。

  你可以使用 LayoutTransition 对ViewGroup中的View改变进行动画显示。

  注意,本文所说的动画效果都是设置给容器(ViewGroup),然而效果是通过容器存放的View来体现的。

四种容器转换动画类型

  当你添加或者移除ViewGroup中的View时,或者你调用View的setVisibility()方法来控制其显示或消失时,就处于一个转换状态。这种事件就有可能会激发动画。

  当前被增加或者移除的View可以经历一个出现的动画或者一个消失的动画。

  而且不止是当前要控制的View,ViewGroup中的其他View也可以随之进行变动,比如经历一个动画移动到新的位置。

  所以一共有四种相关的动画类型

  1.View本身的出现动画;

  2.消失动画;

  3.由于新增了其他View而需要改变位置的动画;

  4.由于移除了其他View而需要改变位置的动画。

  (如果增加或移除了其他View之后,当前View的位置不需要改变,则无动画)。

  你可以自定义这些动画,通过setAnimator() 方法把它们设置进一个 LayoutTransition 对象中去。

  设置的时候需要一个 Animator 对象和一个常数:

  APPEARING - A flag indicating the animation that runs on items that are appearing in the container.

  CHANGE_APPEARING - A flag indicating the animation that runs on items that are changing due to a new item appearing in the container.

  DISAPPEARING - A flag indicating the animation that runs on items that are disappearing from the container.

  CHANGE_DISAPPEARING - A flag indicating the animation that runs on items that are changing due to an item disappearing from the container.

 

  你可以自己定义这四种事件类型的动画,也可以使用默认的动画。

  最后通过setLayoutTransition(LayoutTransition)方法把这些动画以一个 LayoutTransition 对象的形式设置给一个ViewGroup即可。

  比如下面这个方法就生成了一个全新的LayoutTransition对象并set给容器(ViewGroup类型),这样四个动画就全是默认动画。

 

    // 重新生成LayoutTransition对象并设置给containerprivate void resetTransition() {mTransitioner = new LayoutTransition();container.setLayoutTransition(mTransitioner);}

 

  为这个mTransitioner对象生成四个自定义动画:

 

    // 生成自定义动画private void setupCustomAnimations() {// 动画:CHANGE_APPEARING// Changing while AddingPropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1);PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1);PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0,1);PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom",0, 1);PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofFloat("scaleX",1f, 0f, 1f);PropertyValuesHolder pvhScaleY = PropertyValuesHolder.ofFloat("scaleY",1f, 0f, 1f);final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScaleX,pvhScaleY).setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_APPEARING));mTransitioner.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);changeIn.addListener(new AnimatorListenerAdapter() {public void onAnimationEnd(Animator anim) {View view = (View) ((ObjectAnimator) anim).getTarget();view.setScaleX(1f);view.setScaleY(1f);}});// 动画:CHANGE_DISAPPEARING// Changing while RemovingKeyframe kf0 = Keyframe.ofFloat(0f, 0f);Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);Keyframe kf2 = Keyframe.ofFloat(1f, 0f);PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder(this, pvhLeft, pvhTop, pvhRight,pvhBottom, pvhRotation).setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_DISAPPEARING));mTransitioner.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,changeOut);changeOut.addListener(new AnimatorListenerAdapter() {public void onAnimationEnd(Animator anim) {View view = (View) ((ObjectAnimator) anim).getTarget();view.setRotation(0f);}});// 动画:APPEARING// AddingObjectAnimator animIn = ObjectAnimator.ofFloat(null, "rotationY", 90f,0f).setDuration(mTransitioner.getDuration(LayoutTransition.APPEARING));mTransitioner.setAnimator(LayoutTransition.APPEARING, animIn);animIn.addListener(new AnimatorListenerAdapter() {public void onAnimationEnd(Animator anim) {View view = (View) ((ObjectAnimator) anim).getTarget();view.setRotationY(0f);}});// 动画:DISAPPEARING// RemovingObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotationX", 0f,90f).setDuration(mTransitioner.getDuration(LayoutTransition.DISAPPEARING));mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, animOut);animOut.addListener(new AnimatorListenerAdapter() {public void onAnimationEnd(Animator anim) {View view = (View) ((ObjectAnimator) anim).getTarget();view.setRotationX(0f);}});}

 

默认的布局转换动画

  如果你要使用默认的动画,一个非常简单的方式是在ViewGroupd的XMl布局文件中                                             把android:animateLayoutchanges 属性设置为true。

  这样就自动地按照默认方式来对要移除或添加的View,还有Group中的其他View进行动画。

  比如ApiDemos中的LayoutAnimationsByDefault:

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><Buttonandroid:id="@+id/addNewButton"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Add Button" /><!--<GridLayoutandroid:columnCount="4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/gridContainer"android:animateLayoutChanges="true"/>--><LinearLayoutandroid:id="@+id/gridContainer"android:layout_width="wrap_content"android:layout_height="wrap_content"android:animateLayoutChanges="true" android:orientation="vertical"></LinearLayout></LinearLayout>

 

  我把布局改成了线性布局,只要是ViewGroup类型都可以。

  默认情况下,DISAPPEARING和CHANGE_APPEARING动画是立即开始的,其他动画都有一个默认的开始延迟。

  这是因为,比如:当一个新的View出现的时候,其他View要立即执行CHANGE_APPEARING动画腾出位置,而新出现的View在一定延迟之后再执行APPEARING出现;

  相反地,一个View消失的时候,它需要先DISAPPEARING动画消失,而其他的View需要先等它消失后再执行CHANGE_DISAPPEARING。

  当然这些默认的行为都可以通过 setDuration(int, long) 和setStartDelay(int, long)等方法改变。

API Demos代码

  ApiDemos中布局动画相关的类有:LayoutAnimationsByDefault 、LayoutAnimations、LayoutAnimationsHideShow。

  完整的项目可以去github下载。https://github.com/mengdd/AnimationApiDemos

 

以上转载:http://www.cnblogs.com/mengdd/archive/2013/09/06/3305973.html

这篇关于1.5.36 Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1094209

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

CSS弹性布局常用设置方式

《CSS弹性布局常用设置方式》文章总结了CSS布局与样式的常用属性和技巧,包括视口单位、弹性盒子布局、浮动元素、背景和边框样式、文本和阴影效果、溢出隐藏、定位以及背景渐变等,通过这些技巧,可以实现复杂... 一、单位元素vm 1vm 为视口的1%vh 视口高的1%vmin 参照长边vmax 参照长边re

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

MySQL 缓存机制与架构解析(最新推荐)

《MySQL缓存机制与架构解析(最新推荐)》本文详细介绍了MySQL的缓存机制和整体架构,包括一级缓存(InnoDBBufferPool)和二级缓存(QueryCache),文章还探讨了SQL... 目录一、mysql缓存机制概述二、MySQL整体架构三、SQL查询执行全流程四、MySQL 8.0为何移除查

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

使用Java实现一个解析CURL脚本小工具

《使用Java实现一个解析CURL脚本小工具》文章介绍了如何使用Java实现一个解析CURL脚本的工具,该工具可以将CURL脚本中的Header解析为KVMap结构,获取URL路径、请求类型,解析UR... 目录使用示例实现原理具体实现CurlParserUtilCurlEntityICurlHandler