概述
场景用于存储视图结构的状态,包括所有的View对象和它们的属性值。Transitions框架可以在开始场景和结束场景之间应用动画。开始场景通常自动由用户界面的当期状态决定。对于结束场景,框架允许通过资源文件创建或者通过代码动态创建。
本节将介绍如何在应用程序中创建场景以及如何定义场景动作,下一节将介绍如何在两个场景之间应用转场效果。
注意:该框架也可以不使用场景而只对单独一个视图结构执行动画。但是本节内容是学习使用转场框架的基础。
通过布局资源文件创建一个场景
可以直接通过布局资源文件来创建一个场景实例。该种方式适合于被文件锁描述的视图结构在整个程序中保持基本稳定的情况。获取到的场景代表创建该场景实例的那个时间点的视图结构的状态。如果改变了视图结构,需要重新创建场景实例。框架将通过布局文件中的整个视图结构来创建场景,而不允许仅通过其中一部来创建。
通过布局文件来创建场景时,获取场景的根视图并作为一个ViewGroup对象,然后调用Scene.getSceneForLayout()方法来创建。该方法需要传递用于创建场景的布局文件的ID和该布局文件的根视图作为参数。
定义用于创建场景的布局文件
The code snippets in the rest of this section show you how to create two different scenes with the same scene root element. The snippets also demonstrate that you can load multiple unrelated Scene objects without implying that they are related to each other.
以下代码将展示如何通过相同的场景根视图元素来创建两个不同的场景,代码同样表明,可以加载不相关的场景对象,这些对象之间并没有隐含的关联性。
布局文件中包含如下布局定义:
- Activity的主视图,其中包括了一个文本标签和一个子视图。
- 用于代表第一个场景的相对布局,其中包括两个文本。
- 用于代表第二个场景的相对布局,依然包括之前的两个文本,但是顺序发生改变。
这样定义之后,所有的动画效果将发生在Activity主视图中的子布局中,而主布局中的文本标签将不受任何影响。
Activity的主布局如下:
res/layout/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/master_layout">
<TextView
android:id="@+id/title"
...
android:text="Title"/>
<FrameLayout
android:id="@+id/scene_root">
<include layout="@layout/a_scene" />
</FrameLayout>
</LinearLayout>
该布局定义包含一个文本和一个作为场景根视图的子布局。第一个场景的布局文件被include到主布局中。这样做将使得场景布局成为初始用户界面的一部分,同时也作为一个场景被加载进来,因为框架只能把整个布局文件作为场景加载而不能把一个布局文件中的一部分内容作为场景加载。
第一个场景布局文件如下:
res/layout/a_scene.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scene_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/text_view1
android:text="Text Line 1" />
<TextView
android:id="@+id/text_view2
android:text="Text Line 2" />
</RelativeLayout>
第二个场景的布局文件如下,其中包含两个与第一个场景ID相同的文本,但是与第一个场景中的排列顺序不同:
res/layout/another_scene.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scene_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/text_view2
android:text="Text Line 2" />
<TextView
android:id="@+id/text_view1
android:text="Text Line 1" />
</RelativeLayout>
使用布局文件创建场景
定义了以上两个场景布局文件之后,就可以使用其中每一个分别创建一个场景,之后就可以在两种UI配置之间应用转场。想要获取一个场景,需要场景根视图和场景对应的布局资源文件的ID。
以下代码演示了如何获取场景根视图以及如何通过布局文件创建两个场景对象:
Scene mAScene;
Scene mAnotherScene;
// 创建场景根视图
mSceneRoot = (ViewGroup) findViewById(R.id.scene_root);
// 创建一个场景
mAScene = Scene.getSceneForLayout(mSceneRoot, R.layout.a_scene, this);
mAnotherScene =
Scene.getSceneForLayout(mSceneRoot, R.layout.another_scene, this);
应用程序中现在就有了两个基于视图结构的场景对象了。每个场景对象都使用res/layout/activity_main.xml中的FrameLayout元素作为场景的根视图。
通过代码创建场景
也可以在代码中通过一个ViewGroup对象来创建一个场景。当需要动态创建视图结构或者需要直接修改视图结构的时候使用这种方式。
在代码中创建场景对象需要使用Scene(sceneRoot, viewHierarchy)构造器。当已经填充了一个布局之后,调用该方法与调用Scene.getSceneForLayout()方法的效果一样。
以下代码演示了如何通过场景根视图和视图结构在代码中创建于一个场景对象:
Scene mScene;
// 获取场景根视图
mSceneRoot = (ViewGroup) mSomeLayoutElement;
// 获取视图结构作为场景根视图的子视图
mViewHierarchy = (ViewGroup) someOtherLayoutElement;
// 创建一个场景
mScene = new Scene(mSceneRoot, mViewHierarchy);
创建场景动作
框架允许自定义进入场景和离开场景时的场景动作。在大多数情况下,没有比要自定义场景动作,因为框架会在场景切换的时候自动应用动画。
场景动作用于处理以下情况:
- 对不属于统一视图结构的View应用动画。可以使用进入和离开场景动作对开始场景和结束场景中的View添加动画。
- 对框架不能自动应用动画的View应用动画,比如ListView对象。
定义自定义场景动作时,首先需要把需要执行的场景动作定义为一个Runnable对象,然后传递给Scene.setExitAction或者Scene.setEnterAction()方法。框架在执行转场效果之前会调用开始场景的setExitAction()方法设置的场景动作,在执行转场效果之后会调用结束场景的setEnterAction()方法设置的场景动作。
注意:不要通过转场动作向开始场景和结束场景中的View传递数据。