Android Layout 布局动画的介绍

转载请注明出处http://blog.csdn.net/yegongheng/article/details/38455191


       上一篇博文我们详细地学习了如何使用ValueAnimator和ObjectAnimator实现非常炫的动画效果,不过,都只是对View实现的动画,那今天我们来学习Property Animation如何为ViewGroup对象的动画显示提供支持。

LayoutTransition 类介绍

       我们先来认识一个重要的类--LayoutTransition,该类是Android API提供的用于动画显示ViewGroup中的Layout的帮助类,我们可以使用该类设置动画并绑定目标Layout。那一般在什么情况下为Layout设置动画效果呢?比方说,如果我们需要对一个Layout实现动态地添加或删除子View对象,那么我们可以分别为需添加或删除的View对象在移动到新的位置的过程添加动画形式。一般地,Layout中的View对象有四种动画变化的形式,如下:
      APPEARING —— 元素在容器中显现时需要动画显示。
      CHANGE_APPEARING —— 由于容器中要显现一个新的元素,其它元素的变化需要动画显示。
      DISAPPEARING —— 元素在容器中消失时需要动画显示。
      CHANGE_DISAPPEARING —— 由于容器中某个元素要消失,其它元素的变化需要动画显示。
其实这四种动画形式也很好理解,举个例子,我们有一个GridLayout中有多个Button对象,如果需要删除其中一个Button对象的话,该Button对象可以设置动画(即DISAPPEARING 动画形式),Layout中的其它Button对象此时移动到新的位置的过程中也可以设置相关的动画(即CHANGE_DISAPPEARING 动画形式),如图下:

而当需要为Layout添加一个新的Button对象时,此时我们可以为这个 新添加的Button对象设置动画(即APPEARING 动画形式),Layout中的其它Button对象此时移动到新的位置过程也可以设置相关的动画(即CHANGE_APPEARING动画形式 ),如图下:

那基本了解了这四种动画形式后,我们又应该如何使用呢?LayoutTransition类中有一个setAnimator(int transitionType, Animator animator)用于添加动画以及设置动画形式类型,在开发当中,我们只需要确定好需要在不同的动画类型中显示什么动画,然后创建并设置好相关的动画对象,最后使用该方法将两者进行绑定就行。那废话不多说,下面我们通过一个例子来学习一下如何为Layout添加动画。代码实例在文章末尾提供下载,
下面是LayoutAnimatorFragment主界面及和主要功能代码,如下:
[java]  view plain copy
  1. /** 
  2.  * @author AndroidLeaf 
  3.  *ViewGroup中Layout的动画实现 
  4.  *主要知识点: 
  5.  *调用 LayoutTransition 对象的 setAnimator() 方法来定义下列动画方式,调用参数是 Animator 
  6.  *对象和以下 LayoutTransition 常量: 
  7.  *  (1)APPEARING —— 元素在容器中显现时需要动画显示。 
  8.  *  (2)CHANGE_APPEARING —— 由于容器中要显现一个新的元素,其它元素的变化需要动画显示。 
  9.  *  (3)DISAPPEARING —— 元素在容器中消失时需要动画显示。 
  10.  *  (4)CHANGE_DISAPPEARING —— 由于容器中某个元素要消失,其它元素的变化需要动画显示。 
  11.  */  
  12. public class LayoutAnimatorFragment extends Fragment implements OnClickListener{  
  13.   
  14.     private Button mButtonAdd;  
  15.     private Button mButtonReset;  
  16.     private GridLayout mGridLayout;  
  17.     private int buttonNumbers = 1;  
  18.       
  19.     private LayoutTransition mLayoutTransition;  
  20.       
  21.     @Override  
  22.     public void onActivityCreated(Bundle savedInstanceState) {  
  23.         // TODO Auto-generated method stub  
  24.         super.onActivityCreated(savedInstanceState);  
  25.           
  26.     }  
  27.   
  28.     @Override  
  29.     public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  30.             Bundle savedInstanceState) {  
  31.         // TODO Auto-generated method stub  
  32.         View rootView = inflater.inflate(R.layout.fragment_layoutanimator, container, false);  
  33.         initViews(rootView);  
  34.         return rootView;  
  35.     }  
  36.       
  37.     public void initViews(View rootView){  
  38.           
  39.         mButtonAdd = (Button)rootView.findViewById(R.id.layout_animator_addbutton);  
  40.         mButtonAdd.setOnClickListener(this);  
  41.         mButtonReset = (Button)rootView.findViewById(R.id.layout_animator_resetbutton);  
  42.         mButtonReset.setOnClickListener(this);  
  43.         mGridLayout = (GridLayout)rootView.findViewById(R.id.layout_animator_gridview);  
  44.         mLayoutTransition = new LayoutTransition();  
  45.         //为GridLayout设置mLayoutTransition对象  
  46.         mGridLayout.setLayoutTransition(mLayoutTransition);  
  47.         mLayoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, 30);  
  48.         mLayoutTransition.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 30);  
  49.         //设置每个动画持续的时间  
  50.         mLayoutTransition.setDuration(300);  
  51.         //初始化自定义的动画效果  
  52.         customLayoutTransition();  
  53.     }  
  54.   
  55.     @Override  
  56.     public void onPause() {  
  57.         // TODO Auto-generated method stub  
  58.         super.onPause();  
  59.           
  60.     }  
  61.   
  62.     @Override  
  63.     public void onClick(View v) {  
  64.         // TODO Auto-generated method stub  
  65.         switch (v.getId()) {  
  66.         case R.id.layout_animator_addbutton:  
  67.             addButton();  
  68.             break;  
  69.         case R.id.layout_animator_resetbutton:  
  70.             resetButton();  
  71.             break;  
  72.         default:  
  73.             break;  
  74.         }  
  75.     }  
  76.       
  77.     /** 
  78.      * 增加Button 
  79.      */  
  80.     public void addButton(){  
  81.         Button mButton = new Button(getActivity());  
  82.         LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(5050);  
  83.         mButton.setLayoutParams(mLayoutParams);  
  84.         mButton.setText(String.valueOf(buttonNumbers++));  
  85.         mButton.setTextColor(Color.rgb(000));  
  86.         if(buttonNumbers % 2 == 1){  
  87.             mButton.setBackgroundColor(Color.rgb(4511887));  
  88.         }else{  
  89.             mButton.setBackgroundColor(Color.rgb(225240));  
  90.         }  
  91.         mButton.setOnClickListener(new OnClickListener() {  
  92.               
  93.             @Override  
  94.             public void onClick(View v) {  
  95.                 // TODO Auto-generated method stub  
  96.                 mGridLayout.removeView(v);  
  97.             }  
  98.         });  
  99.           
  100.         mGridLayout.addView(mButton, Math.min(1, mGridLayout.getChildCount()));  
  101.     }  
  102.       
  103.     /** 
  104.      * 删除所有的Button,重置GridLayout 
  105.      */  
  106.     public void resetButton(){  
  107.         mGridLayout.removeAllViews();  
  108.         buttonNumbers = 1;  
  109.     }  
  110.       
  111.     public void customLayoutTransition(){  
  112.           
  113.         /** 
  114.          * Add Button 
  115.          * LayoutTransition.APPEARING 
  116.          * 增加一个Button时,设置该Button的动画效果 
  117.          */  
  118.         ObjectAnimator mAnimatorAppearing = ObjectAnimator.ofFloat(null"rotationY"90.0f,0.0f)  
  119.                 .setDuration(mLayoutTransition.getDuration(LayoutTransition.APPEARING));  
  120.         //为LayoutTransition设置动画及动画类型  
  121.         mLayoutTransition.setAnimator(LayoutTransition.APPEARING, mAnimatorAppearing);  
  122.         mAnimatorAppearing.addListener(new AnimatorListenerAdapter() {  
  123.             @Override  
  124.             public void onAnimationEnd(Animator animation) {  
  125.                 // TODO Auto-generated method stub  
  126.                 super.onAnimationEnd(animation);  
  127.                  View view = (View) ((ObjectAnimator) animation).getTarget();  
  128.                  view.setRotationY(0.0f);  
  129.             }  
  130.         });  
  131.           
  132.         /** 
  133.          * Add Button 
  134.          * LayoutTransition.CHANGE_APPEARING 
  135.          * 当增加一个Button时,设置其他Button的动画效果 
  136.          */  
  137.           
  138.         PropertyValuesHolder pvhLeft =  
  139.                     PropertyValuesHolder.ofInt("left"01);  
  140.         PropertyValuesHolder pvhTop =  
  141.                 PropertyValuesHolder.ofInt("top"01);  
  142.         PropertyValuesHolder pvhRight =  
  143.                 PropertyValuesHolder.ofInt("right"01);  
  144.         PropertyValuesHolder pvhBottom =  
  145.                 PropertyValuesHolder.ofInt("bottom"01);  
  146.           
  147.         PropertyValuesHolder mHolderScaleX = PropertyValuesHolder.ofFloat("scaleX"1.0f,0.0f,1.0f);  
  148.         PropertyValuesHolder mHolderScaleY = PropertyValuesHolder.ofFloat("scaleY"1.0f,0.0f,1.0f);  
  149.         ObjectAnimator mObjectAnimatorChangeAppearing = ObjectAnimator.ofPropertyValuesHolder(this, pvhLeft,  
  150.                 pvhTop,pvhRight,pvhBottom,mHolderScaleX,mHolderScaleY).setDuration(mLayoutTransition  
  151.                         .getDuration(LayoutTransition.CHANGE_APPEARING));  
  152.         mLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, mObjectAnimatorChangeAppearing);  
  153.         mObjectAnimatorChangeAppearing.addListener(new AnimatorListenerAdapter() {  
  154.             @Override  
  155.             public void onAnimationEnd(Animator animation) {  
  156.                 // TODO Auto-generated method stub  
  157.                 super.onAnimationEnd(animation);  
  158.                  View view = (View) ((ObjectAnimator) animation).getTarget();  
  159.                  view.setScaleX(1f);  
  160.                  view.setScaleY(1f);  
  161.             }  
  162.         });  
  163.           
  164.         /** 
  165.          * Delete Button 
  166.          * LayoutTransition.DISAPPEARING 
  167.          * 当删除一个Button时,设置该Button的动画效果 
  168.          */  
  169.         ObjectAnimator mObjectAnimatorDisAppearing = ObjectAnimator.ofFloat(null"rotationX"0.0f,90.0f)  
  170.                 .setDuration(mLayoutTransition.getDuration(LayoutTransition.DISAPPEARING));  
  171.         mLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, mObjectAnimatorDisAppearing);  
  172.         mObjectAnimatorDisAppearing.addListener(new AnimatorListenerAdapter() {  
  173.             @Override  
  174.             public void onAnimationEnd(Animator animation) {  
  175.                 // TODO Auto-generated method stub  
  176.                 super.onAnimationEnd(animation);  
  177.                  View view = (View) ((ObjectAnimator) animation).getTarget();  
  178.                  view.setRotationX(0.0f);  
  179.             }  
  180.         });  
  181.           
  182.         /** 
  183.          * Delete Button 
  184.          * LayoutTransition.CHANGE_DISAPPEARING 
  185.          * 当删除一个Button时,设置其它Button的动画效果 
  186.          */  
  187.         //Keyframe 对象中包含了一个时间/属性值的键值对,用于定义某个时刻的动画状态。  
  188.         Keyframe mKeyframeStart = Keyframe.ofFloat(0.0f, 0.0f);  
  189.         Keyframe mKeyframeMiddle = Keyframe.ofFloat(0.5f, 180.0f);  
  190.         Keyframe mKeyframeEndBefore = Keyframe.ofFloat(0.999f, 360.0f);  
  191.         Keyframe mKeyframeEnd = Keyframe.ofFloat(1.0f, 0.0f);  
  192.           
  193.         PropertyValuesHolder mPropertyValuesHolder = PropertyValuesHolder.ofKeyframe("rotation",   
  194.                 mKeyframeStart,mKeyframeMiddle,mKeyframeEndBefore,mKeyframeEnd);  
  195.         ObjectAnimator mObjectAnimatorChangeDisAppearing = ObjectAnimator.ofPropertyValuesHolder(this, pvhLeft,pvhTop,pvhRight,pvhBottom,mPropertyValuesHolder)  
  196.                 .setDuration(mLayoutTransition.getDuration(LayoutTransition.CHANGE_DISAPPEARING));  
  197.         mLayoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, mObjectAnimatorChangeDisAppearing);  
  198.         mObjectAnimatorChangeDisAppearing.addListener(new AnimatorListenerAdapter() {  
  199.             @Override  
  200.             public void onAnimationEnd(Animator animation) {  
  201.                 // TODO Auto-generated method stub  
  202.                 super.onAnimationEnd(animation);  
  203.                  View view = (View) ((ObjectAnimator) animation).getTarget();  
  204.                   view.setRotation(0.0f);  
  205.             }  
  206.         });  
  207.     }  
  208. }  
LayoutAnimatorFragment的界面布局fragment_layoutanimator.xml代码如下:
[html]  view plain copy
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:background="@color/view_animation_background"  
  6.     android:orientation="vertical"  
  7.      >  
  8.     <LinearLayout   
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:orientation="horizontal"  
  12.         >  
  13.         <Button   
  14.             android:layout_width="0dp"  
  15.             android:layout_weight="1"  
  16.             android:layout_height="wrap_content"  
  17.             android:text="Add Button"  
  18.             android:id="@+id/layout_animator_addbutton"  
  19.             />  
  20.         <Button  
  21.             android:layout_width="0dp"  
  22.             android:layout_weight="1"  
  23.             android:layout_height="wrap_content"  
  24.             android:text="Reset Button"  
  25.             android:id="@+id/layout_animator_resetbutton"   
  26.             />  
  27.     </LinearLayout>  
  28.    <ScrollView   
  29.        android:layout_width="match_parent"  
  30.        android:layout_height="match_parent"  
  31.        >  
  32.        <GridLayout  
  33.         android:layout_width="match_parent"  
  34.         android:layout_height="match_parent"  
  35.         android:columnCount="5"  
  36.         android:animateLayoutChanges="true"   
  37.         android:id="@+id/layout_animator_gridview"  
  38.         />  
  39.    </ScrollView>  
  40.       
  41. </LinearLayout>  
布局界面比较简单,唯一要注意的是GridLayout布局中的android:animateLayoutChanges属性,该属性的值为true或false,true代表当前Layout的布局发生改变时使用动画效果,false则不使用。
最后我们运行程序,看一下运行及操作效果图:


小伙伴们,有没感觉上面的动画效果比较炫,哈哈,想要实现的伙伴们赶紧动手吧!

源代码下载,请戳下面:
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值