在Android 4.4(KitKat)中,谷歌添加了很多不错的东西。现在我们来看看android.transition框架。
多年来,android不断改进现有的动画工具供开发者使用。在HoneyComb版本中,提供了很多不错的API用于创建丰富、复杂的动画。在此基础上,KitKat的android.transition让我们可以通过一种更直观的方式定义动画效果。
Scene和Transition
先从Scene和Transition概念说起。Scene定义了界面的当前状态信息,而Transition定义了界面之间的切换。
可以从布局文件中载入Scene定义,示例如下:
1 | |
其中
container
在Scene中是一个包含了所有view的ViewGroup。如果是在fragment中,Scene就是传入
onCreateView()
方法的参数。使用Transition的最简单方式就是使用
TransitionManager
处理,示例如下:
1 | |
如果在
TransitionManager
中不明确需要指定哪个Transition,就会默认使用
AutoTransition
,这个我们会后面介绍。也可以用
inflater
载入现有的view来创建Scene,示例如下:
1 2 | |
Andorid.Transition实践
我们来看一个更详细的示例,首先从项目主页下载示例代码AndroidTransitionExample。这已经是一个已完成的项目了,所以也可以用
git checkout
检出代码(以下是详细解释)。
首先新建只包含一个Fragment的项目,这样可以更容易记录一些信息。我们为
TransitionFragment
新建一个xml布局文件,叫做fragment_transition_scene_1.xml。接着往里面添加一个
TextView
,然后在
TextView
下面再添加一个Button,如下:
fragment_transition_scene_1.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
你一定猜得到,我们接下来还要新建另一个xml布局文件,fragment_transition_scene_2.xml。它和上一个布局文件基本一样,只是把Button移到布局底部。示例如下:
1 2 3 4 5 6 7 8 9 | |
这是两个布局的屏幕截图:
为了看Transition的效果,我们从第二个布局文件中创建Scene。点击goButton的时候展示Transition的效果。我们先修改一下
TransitionFragment.onCreateView()
方法的代码,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
这是点击goButton的效果:
为什么会产生这样的效果呢?因为如果view有相同的ID,就会被当做是同一个view,然后也会被改变(通过改变bounds),也就是说,在Scene切换时,view的位置和大小也会改变,需要注意的是两个布局文件的
RelativeLayout
也要有相同的ID。
使用GIT实战
如果你对整个例子代码感兴趣的话,也可以利用GIT检出代码。从AndroidTransitionExample复制一份即可,你可以用GUI git客户端列出项目的历史版本,也可以定位到某个具体的提交点检出。
当然,你也可以使用命令行。使用
cd
命令切换到项目文件夹,然后执行以下命令:
1 | |
此时,你会得到项目的提交列表,像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
以上贴出的对应于simple transition这个提交点,执行以下代码可以把项目设置成这个状态:
1 | |
执行
git checkout
,你可以跳到任意一个提交点上,下面的插入文字会给出指示操作。
修改布局文件
我们来修改一下第二个布局文件,首先把
RelativeLayout
换成
LinearLayout
,然后我们来介绍一个在第一个布局文件中没有出现的view,最后我们重新排布一下这些view,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
我们目前处于“1e7c5be modified layout for scene 2”提交点,在命令行执行
git checkout 1e7c5be
就可以切换上去。可以看到,Transition仍然起作用,在第一个Scene里面,不存在的view竟然出现在屏幕上,然后随着Button和TextView的移动而逐渐消失。
我们详细看看AutoTransition,事实证明,它只是
TransitionSet
的子类,只是它给自己定义了一个执行序列,分别是fading out、changing bounds、fading in。
我们注意到,在第二个Transition中,AutoTransition会改变bounds,目前我们只看到了Button和TextView改变了位置,如果我们改变view的大小会出现什么情况呢?在Button中添加layout_weight属性来看看效果:
1 2 3 4 5 6 | |
现在Button在转变的过程中既改变了位置也改变了大小。
现在切换到“added layout_weight to button”这个点,命令:
git checkout 092ebe0
。现在再做一些变化效果,在Scene中把Button转变成
ImageView
:
1 2 3 4 5 6 7 | |
此时切换到“example of transitioning from Button to ImageView”这个点,命令:
git checkout 6b4629c
。看看从Button变成
ImageView
的效果:
仔细看你会发现,第一个Button首先被一张切割过的图片替换了,然后逐渐移动到最终的位置,逐渐改变大小。
如果我们改变所有views的嵌套结构,比如在Button外面套一层
LinearLayout
,那么Bounds就不会改变了。transition manager要求在Scene的布局文件中,同一层级的view要有和之前相同的ID:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
此时切换到“example of change bounds not working when changing hierarchy”这个点,命令:
git checkout 2b000b3
。
如果我们在第一个Scene中继续用
LinearLayout
包含Button,那么还是不行。想让它起作用的话,可以给
LinearLayout
一个相同的ID。这会得到两种不同的效果。
切换到“restore transition by adding LinearLayout with id”,命令:
git checkout 34e0f8f
下一篇我们我们继续研究怎么控制Transition,以及如何从xml文件中载入Transition。
原文地址 http://blog.jobbole.com/62601/