Animating Views Using Scenes and Transitions

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;
        }
    }
原文地址:https://www.cnblogs.com/deman/p/4597027.html