From android 4.4 , it supply one new animation with layout:transition
To help you animate a change between one view hierarchy and another, Android provides the transitions framework.
This framework applies one or more animations to all the views in the hierarchies as it changes between them.
The scene is the source for transition.
It is easily to transfer from one scene to another scene.
You just need to doing this as following.
1.add a new activty named TransitionActivity
define layout like this:scene_layout.xml
<?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" > <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="changed" /> <FrameLayout android:id="@+id/scene_root" android:layout_width="wrap_content" android:layout_height="wrap_content" > <include layout="@layout/a_scene" /> </FrameLayout> </LinearLayout>
R.id.scene_root is the view we want to transiton.
So transition is not animation activity whole layout, you can just start with one layout:as below FrameLayout.
2.we need to define two scene view to show transtion:
a_scene.xml:
<?xml version="1.0" encoding="utf-8"?> <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:layout_alignParentRight="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextLine1" /> <TextView android:id="@+id/text_view2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="TextLine2" /> </RelativeLayout>
and another_scene.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/text_view2" android:layout_alignParentTop="true" android:paddingTop="100dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Text Line 3" /> <TextView android:id="@+id/text_view1" android:layout_alignParentBottom="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Text Line 4" /> </RelativeLayout>
You can find there children's id is same.
Yes, android transition framework need using view id to calculater transition animation .
3.define transition manager
Here we will define how one scene go to another scene.
transitions_mgr.xml
<transitionManager xmlns:android="http://schemas.android.com/apk/res/android"> <transition android:fromScene="@layout/a_scene" android:toScene="@layout/another_scene" android:transition="@transition/changebounds_fadein_together"/> <transition android:fromScene="@layout/another_scene" android:toScene="@layout/a_scene" android:transition="@transition/changebounds_fadeout_sequential"/> </transitionManager>
4. showing the TransitionActivity
mAScene = Scene.getSceneForLayout(mSceneRoot, R.layout.a_scene, this); mAnotherScene = Scene.getSceneForLayout(mSceneRoot, R.layout.another_scene, this);
Scene android.transition.Scene.getSceneForLayout(ViewGroup sceneRoot, int layoutId, Context context)
as you see: mSceneRoot is the layout what your scene will showing. and R.layout.a_scene & R.layout.another_scene is the layout for scene.
mSceneRoot = (ViewGroup) findViewById(R.id.scene_root);
TransitionInflater inflater = TransitionInflater.from(this); mTransitionManager = inflater.inflateTransitionManager(R.transition.transitions_mgr, mSceneRoot);
get an mTransitionManager form R.transition.transitions_mgr . Thus you can define transiton animation detail from one scene to another one.
package com.joyfulmath.androidstudy.transition; import com.joyfulmath.androidstudy.R; import android.app.Activity; import android.os.Bundle; import android.transition.Scene; import android.transition.TransitionInflater; import android.transition.TransitionManager; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; public class TransitionActivity extends Activity { Scene mAScene; Scene mAnotherScene; private ViewGroup mSceneRoot; private TransitionManager mTransitionManager; View mTitle = null; int currentId = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.scene_layout); mSceneRoot = (ViewGroup) findViewById(R.id.scene_root); mTitle = findViewById(R.id.title); mAScene = Scene.getSceneForLayout(mSceneRoot, R.layout.a_scene, this); mAnotherScene = Scene.getSceneForLayout(mSceneRoot, R.layout.another_scene, this); TransitionInflater inflater = TransitionInflater.from(this); mTransitionManager = inflater.inflateTransitionManager(R.transition.transitions_mgr, mSceneRoot); mTitle.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { setScene(3-currentId); } }); } public void setScene(int id) { if(id == currentId) { return; } currentId = id; switch (id) { case 1: mTransitionManager.transitionTo(mAScene); break; case 2: mTransitionManager.transitionTo(mAnotherScene); break; } } }
5.define special transition animation:
Two way: fade & changeBounds
<changeBounds/> just defined Moves and resizes views.
<fade android:fadingMode="fade_out|fade_in|fade_in_out" >
</fade>
6.Custom Transition
package com.joyfulmath.androidstudy.transition; import android.animation.Animator; import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.transition.Transition; import android.transition.TransitionValues; import android.view.View; import android.view.ViewGroup; public class CustomTransition extends Transition { // Define a key for storing a property value in // TransitionValues.values with the syntax // package_name:transition_class:property_name to avoid collisions private static final String PROPNAME_BACKGROUND = "com.joyfulmath.androidstudy.transition:CustomTransition:background"; @Override public void captureEndValues(TransitionValues transitionValues) { captureValues(transitionValues); } @Override public void captureStartValues(TransitionValues transitionValues) { // Call the convenience method captureValues captureValues(transitionValues); } @Override public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) { // This transition can only be applied to views that are on both starting and ending scenes. if (null == startValues || null == endValues) { return null; } // Store a convenient reference to the target. Both the starting and ending layout have the // same target. final View view = endValues.view; // Store the object containing the background property for both the starting and ending // layouts. Drawable startBackground = (Drawable) startValues.values.get(PROPNAME_BACKGROUND); Drawable endBackground = (Drawable) endValues.values.get(PROPNAME_BACKGROUND); // This transition changes background colors for a target. It doesn't animate any other // background changes. If the property isn't a ColorDrawable, ignore the target. if (startBackground instanceof ColorDrawable && endBackground instanceof ColorDrawable) { ColorDrawable startColor = (ColorDrawable) startBackground; ColorDrawable endColor = (ColorDrawable) endBackground; // If the background color for the target in the starting and ending layouts is // different, create an animation. if (startColor.getColor() != endColor.getColor()) { // Create a new Animator object to apply to the targets as the transitions framework // changes from the starting to the ending layout. Use the class ValueAnimator, // which provides a timing pulse to change property values provided to it. The // animation runs on the UI thread. The Evaluator controls what type of // interpolation is done. In this case, an ArgbEvaluator interpolates between two // #argb values, which are specified as the 2nd and 3rd input arguments. ValueAnimator animator = ValueAnimator.ofObject(new ArgbEvaluator(), startColor.getColor(), endColor.getColor()); // Add an update listener to the Animator object. animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Object value = animation.getAnimatedValue(); // Each time the ValueAnimator produces a new frame in the animation, change // the background color of the target. Ensure that the value isn't null. if (null != value) { view.setBackgroundColor((Integer) value); } } }); // Return the Animator object to the transitions framework. As the framework changes // between the starting and ending layouts, it applies the animation you've created. return animator; } } // For non-ColorDrawable backgrounds, we just return null, and no animation will take place. return null; } // END_INCLUDE (create_animator) // For the view in transitionValues.view, get the values you // want and put them in transitionValues.values private void captureValues(TransitionValues transitionValues) { // Get a reference to the view View view = transitionValues.view; // Store its background property in the values map transitionValues.values.put(PROPNAME_BACKGROUND, view.getBackground()); } }
public void setScene(int id) { if(id == currentId) { return; } currentId = id; switch (id) { case 1: // mTransitionManager.transitionTo(mAScene); TransitionManager.go(mAScene, mTransition); break; case 2: // mTransitionManager.transitionTo(mAnotherScene); TransitionManager.go(mAnotherScene, mTransition); break; } }