在iOS应用开发过程中,视图切换时的过渡动画是一个不可缺少的部分,简单的在Storyboard中托几个VC后连接上segue就可以实现,并可以选择几种如push,popover之类的动画效果,复杂的可以通过编码实现自定义的酷炫过渡动画效果(Github上有许多开源项目可以参考)。
最近一直在参研Android L的UI新特性,看到了更多注重UX的设计理解(当然也包括许多酷炫的效果,如OverScroll的新EdgeEffect、大部分控件的触摸效果,Reveal Effect等),其实从4.0 ICS开始,Android UI部分就有了很大的改进,当然也包括本篇要记录的过渡动画效果。4.0之前的UI动画主要是以Animation框架实现的,而4.0后加入了新的ObjectAnimator框架(貌似是3.0就有了,不过3.x是在没有存在感…),可以提供更多的动画控制从而实现更多的动画效果,这里记录下ObjectAnimator XML动画资源用于Activity和Fragment切换过渡动画的基本方法。
ObjectAnimator是以对一系列可变属性,如位移、旋转、缩放、Alpha等的改变来实现动画效果的,既可以使用写代码也可以使用定义XML资源文件的方式完成,这里以XML资源为例,在Android项目中存放于res/animator中,下面贴出几个简单动画效果示例:
card_flip_left_in.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <? xml version = "1.0" encoding = "utf-8" ?> <!-- Before rotating, immediately set the alpha to 0. --> < objectAnimator android:valueFrom = "1.0" android:valueTo = "0.0" android:propertyName = "alpha" android:duration = "0" /> <!-- Rotate. --> < objectAnimator android:valueFrom = "-180" android:valueTo = "0" android:propertyName = "rotationY" android:interpolator = "@android:interpolator/accelerate_decelerate" android:duration = "@android:integer/config_longAnimTime" /> <!-- Half-way through the rotation (see startOffset), set the alpha to 1. --> < objectAnimator android:valueFrom = "0.0" android:valueTo = "1.0" android:propertyName = "alpha" android:startOffset = "@android:integer/config_mediumAnimTime" android:duration = "1" /> </ set > |
card_flip_left_out.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <? xml version = "1.0" encoding = "utf-8" ?> <!-- Rotate. --> < objectAnimator android:valueFrom = "0" android:valueTo = "180" android:propertyName = "rotationY" android:interpolator = "@android:interpolator/accelerate_decelerate" android:duration = "@android:integer/config_longAnimTime" /> <!-- Half-way through the rotation (see startOffset), set the alpha to 0. --> < objectAnimator android:valueFrom = "1.0" android:valueTo = "0.0" android:propertyName = "alpha" android:startOffset = "@android:integer/config_mediumAnimTime" android:duration = "1" /> </ set > |
card_flip_right_in.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <? xml version = "1.0" encoding = "utf-8" ?> <!-- Before rotating, immediately set the alpha to 0. --> < objectAnimator android:valueFrom = "1.0" android:valueTo = "0.0" android:propertyName = "alpha" android:duration = "0" /> <!-- Rotate. --> < objectAnimator android:valueFrom = "180" android:valueTo = "0" android:propertyName = "rotationY" android:interpolator = "@android:interpolator/accelerate_decelerate" android:duration = "@android:integer/config_longAnimTime" /> <!-- Half-way through the rotation (see startOffset), set the alpha to 1. --> < objectAnimator android:valueFrom = "0.0" android:valueTo = "1.0" android:propertyName = "alpha" android:startOffset = "@android:integer/config_mediumAnimTime" android:duration = "1" /> </ set > |
card_flip_right_out.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <? xml version = "1.0" encoding = "utf-8" ?> <!-- Rotate. --> < objectAnimator android:valueFrom = "0" android:valueTo = "-180" android:propertyName = "rotationY" android:interpolator = "@android:interpolator/accelerate_decelerate" android:duration = "@android:integer/config_longAnimTime" /> <!-- Half-way through the rotation (see startOffset), set the alpha to 0. --> < objectAnimator android:valueFrom = "1.0" android:valueTo = "0.0" android:propertyName = "alpha" android:startOffset = "@android:integer/config_mediumAnimTime" android:duration = "1" /> </ set > |
slide_down.xml:
1 2 3 4 5 6 7 8 9 10 | <? xml version = "1.0" encoding = "utf-8" ?> < objectAnimator android:interpolator = "@android:anim/accelerate_decelerate_interpolator" android:propertyName = "translationY" android:valueType = "floatType" android:valueFrom = "0" android:valueTo = "1280" android:duration = "@android:integer/config_mediumAnimTime" /> |
slide_up.xml:
1 2 3 4 5 6 7 8 9 10 | <? xml version = "1.0" encoding = "utf-8" ?> < objectAnimator android:interpolator = "@android:anim/accelerate_decelerate_interpolator" android:propertyName = "translationY" android:valueType = "floatType" android:valueFrom = "1280" android:valueTo = "0" android:duration = "@android:integer/config_mediumAnimTime" /> |
有了animator资源在代码中就可以通过资源ID方式方便的使用了,对于Activity,要在startActivity后通过调用overridePendingTransition的方式来设置指定的过渡动画,如:
1 | startActivityForResult(intent, 100 ); getActivity().overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); |
两个参数分别为enterAnim和exitAnim,进入、退出动画。
相对而言,Fragment的过渡动画设置方法看着就要专业一些了,对FragmentTransaction调用setCustomAnimations即可,如下:
1 2 3 4 5 | FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.setCustomAnimations(R.animator.card_flip_left_in, R.animator.card_flip_left_out, R.animator.card_flip_right_in, R.animator.card_flip_right_out); |
setCustomAnimations的声明是
1 2 | public abstract FragmentTransaction setCustomAnimations ( int enter, int exit, int popEnter, int popExit) |
也有只有前两个参数的版本,后两个pop版为通过回退栈(back stack)触发的正反向动画。
PS:顺带一提使用Fragment时的Back键pop回退fragment栈中的fragment问题,本来以为在进行过fragment进栈操作后,会自动处理back键pop到没有为止,结果发现就算
1 2 3 4 5 6 7 8 9 10 | FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.setCustomAnimations(R.animator.card_flip_left_in, R.animator.card_flip_left_out, R.animator.card_flip_right_in, R.animator.card_flip_right_out); Fragment frag = SettingsFragment.newInstance(); frag.setArguments( null ); ft.replace(R.id.container, frag); ft.addToBackStack( null ); ft.commit(); |
这样addToBackStack后,当前Activity(我用的是ActionBarActivity)在响应back键时还是会执行默认的退出行为,而不是pop stack上的fragment先,这点可能在其它形式的fragment应用中,比如navigation drawer activity中会先pop吧,总之,这里我还是先通过override onBackPressed来处理了一下:
1 2 3 4 5 6 7 8 9 | public void onBackPressed() { // Pop fragment stack on back button FragmentManager fm = getFragmentManager(); if (fm.getBackStackEntryCount()> 0 ) { fm.popBackStack( null , FragmentManager.POP_BACK_STACK_INCLUSIVE); return ; } super .onBackPressed(); } |
这样就可以了。
博主友情提示:
如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。
加载更多