Source: http://www.cnblogs.com/everhad/p/6271238.html

簡述:transitions framework

下面翻譯transition為“過渡”,強調動畫過程的含義,不過更多時候使用transition單詞本身。
Android 4.4.2 (API level 19) 引入了過渡框架,它用來在兩個view hierarchies(就是ViewGroup實例)切換時執行改變動畫。它通過動態修改views對象的某些property值來實現動畫,實際上就是用的屬性動畫。框架內建了一些transition效果,也可以自定義。并且可以監聽transition執行過程/生命周期(Lifecycle callbacks)各種回調。

框架概覽

在UI改變時——view hierarchy(視圖層級) 發生變化,過渡框架對包含的部分改變了的view對象執行屬性動畫
來表達這樣的視覺提示(visual cues)。

特性

過渡框架包括下面這些特性:

  • 動畫組Group-level animations
    視圖層級發生變化時,可以同時執行多個動畫,它們形成動畫組,類似AnimationSet

  • Transition-based animation
    Runs animations based on the changes between starting and ending view property values.

  • Built-in animations
    Includes predefined animations for common effects such as fade out or movement.

  • Resource file support 支持資源文件方式的使用
    Loads view hierarchies and built-in animations from layout resource files.

  • Lifecycle callbacks
    Defines callbacks that provide finer control over the animation and hierarchy change process.

框架結構

下圖是過渡框架涉及的相關概念和之間的關系:

Relationships in the transitions framework

  • Scene
    一個Scene表示一個view hierarchy,存儲對應的views及其property值。
    一個Scene必須關聯到一個scene-root,它是一個ViewGroup,正是對應view hierarchy要添加到的容器。
    Scene可以從layout文件創建(只能是整個布局文件對應的view hierarchy),或者代碼生成的View/ViewGroup。
    如果僅指定目標Scene,那么框架使用當前scene-root對應的view hierarchy就作為開始的Scene。

  • Transition
    表示兩個Scene之間的過渡動畫,它保存了使用到的animations。
    TransitionManager用來執行專場效果。
    TransitionListener用來實現對過渡過程的監聽。

存在的限制

SurfaceView非UI線程不保證同步;
AdapterView管理childView行為沖突;
TextView改變尺寸時顯示問題;
TextureView非預期效果;

創建Scene

過渡涉及startScene和endScene,它們使用同一個sceneRoot,也就是變化的view hierarchy是在一個ViewGroup下的。

startScene可以不指定,那么就默認是當前view hierarchy。
如果連續執行多個Scene之前的切換,那么上一個endScene就是當前的startScene。

可以通過代碼或layout文件創建Scene。

  • 代碼文件,生成需要的ViewGroup對象即可,適合“動態創建”界面這樣的需求。
Scene mScene;

// Obtain the scene root element
mSceneRoot = (ViewGroup) mSomeLayoutElement;

// Obtain the view hierarchy to add as a child of
// the scene root when this scene is entered
mViewHierarchy = (ViewGroup) someOtherLayoutElement;

// Create a scene
mScene = new Scene(mSceneRoot, mViewHierarchy);
  • layout文件
/**
 * Returns a Scene described by the resource file associated with the given
 * <code>layoutId</code> parameter. If such a Scene has already been created for
 * the given <code>sceneRoot</code>, that same Scene will be returned.
 * This caching of layoutId-based scenes enables sharing of common scenes
 * between those created in code and those referenced by {@link TransitionManager}
 * XML resource files.
 *
 * @param sceneRoot The root of the hierarchy in which scene changes
 * and transitions will take place.
 * @param layoutId The id of a standard layout resource file.
 * @param context The context used in the process of inflating
 * the layout resource.
 * @return The scene for the given root and layout id
 */
public static Scene getSceneForLayout(ViewGroup sceneRoot, int layoutId, Context context);

NOTE:
The framework creates the scene from the entire view hierarchy in the file; you can not create a scene from part of a layout file.

Create Scene Actions

使用Scene.setExitAction() or Scene.setEnterAction() ,傳遞定義的Runnable實例。
可以執行一些操作,比如修改ListView等。

Note:
Do not use scene actions to pass data between views in the starting and ending scenes. For more information, see Defining Transition Lifecycle Callbacks.

應用Transition

創建好startScene、endScene后,在改變UI的邏輯的地方,就可以執行Transition來開啟專場動畫了。

創建Transition

  • 資源文件
    在res/transition/目錄下,創建表示Transition的文件,資源文件的方式更加復用而且簡單。
    這種方式和定義動畫文件的機制類似。

如res/transition/fade_transition.xml:

<fade xmlns:android="http://schemas.android.com/apk/res/android" />

然后加載它:

Transition mFadeTransition =
        TransitionInflater.from(this).
        inflateTransition(R.transition.fade_transition);
  • 代碼方式
    例如:

    Transition mFadeTransition = new Fade();

預提供的類型有ChangeBounds, ChangeClipBounds, ChangeImageTransform, ChangeTransform, TransitionSet, Visibility詳見API文檔。

開啟過渡

使用下面的方法TransitionManager.go()

/**
  * Convenience method to simply change to the given scene using
  * the given transition.
  *
  * <p>Passing in <code>null</code> for the transition parameter will
  * result in the scene changing without any transition running, and is
  * equivalent to calling {@link Scene#exit()} on the scene root's
  * current scene, followed by {@link Scene#enter()} on the scene
  * specified by the <code>scene</code> parameter.</p>
  *
  * @param scene The Scene to change to
  * @param transition The transition to use for this scene change. A
  * value of null causes the scene change to happen with no transition.
  */
 public static void go(Scene scene, Transition transition)

它有一個不含參數transition的重載,默認會使用AutoTransition

選擇指定的目標view

默認情況下Transition的執行是針對Scene關聯的view hierarchy中的所有views執行的。
可以通過Transition的方法removeTarget()、addTarget()來指定它影響的view。
比如若ListView不能通過框架正常完成過渡效果,那么移除它。

動畫組:同時執行多個過渡效果

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
    android:transitionOrdering="sequential">
    <fade android:fadingMode="fade_out" />
    <changeBounds />
    <fade android:fadingMode="fade_in" />
</transitionSet>

對應一個TransitionSet ,它是Transition的子類。

單Scene的過渡

如果UI在變化前后差距很小,例如就是同一個ViewGroup的簡單的addView()/removeView()那么,此時可以不去執行像startScene、endScene那樣的變化,使用delayed transition來在view hierarchy變化的時候開啟過渡:

// Start recording changes to the view hierarchy
TransitionManager.beginDelayedTransition(mRootView, mFade);

// Add the new TextView to the view hierarchy
mRootView.addView(mLabelText);

// When the system redraws the screen to show this update,
// the framework will animate the addition as a fade in

Transition Lifecycle Callbacks

調用public Transition addListener (Transition.TransitionListener listener)
回調方法見Transition.TransitionListener

自定義Transition

A custom transition, like one of the built-in transition types, applies animations to child views of both the starting and ending scenes. Unlike built-in transition types, however, you have to provide the code that captures property values and generates animations. You may also want to define a subset of target views for your animation.

定義Transition子類

public class CustomTransition extends Transition {

    @Override
    public void captureStartValues(TransitionValues values) {}

    @Override
    public void captureEndValues(TransitionValues values) {}

    @Override
    public Animator createAnimator(ViewGroup sceneRoot,
                                   TransitionValues startValues,
                                   TransitionValues endValues) {}
}

方法captureStartValues()和captureEndValues()用來獲取startScene、endScene關聯的view的property值。可以對關心的view的屬性值進行記錄。

類似下面這樣:

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.example.android.customtransition:CustomTransition:background";

    @Override
    public void captureStartValues(TransitionValues transitionValues) {
        // Call the convenience method captureValues
        captureValues(transitionValues);
    }


    // 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());
    }
    ...
}

TransitionValues是一個非常簡單的數據結構,它保存和view關聯的屬性值,startScene和endScene分別使用一個TransitionValues對象來記錄view hierarchy的各個view的狀態。

要記錄的“property_name”需要保存唯一,因為可能和其它Transition沖突,建議格式是:
package_name:transition_name:property_name

創建自定義Animator

過渡框架中的Transition使用屬性動畫作為動畫機制的實現。
子自定義Transition重寫createAnimator()方法來提供需要的動畫邏輯,工作就是根據startValues和endValues來創建Animator。
針對有些view的過渡只在endScene或者startScene中有,所以startValues和endValues可能為null。

框架會為每一個動畫的view創建一個Animator,也就是調用一次createAnimator()。

下面是一個案例ChangeColor.java:

public class ChangeColor extends Transition {

    /** Key to store a color value in TransitionValues object */
    private static final String PROPNAME_BACKGROUND = "customtransition:change_color:background";

    // BEGIN_INCLUDE (capture_values)
    /**
     * Convenience method: Add the background Drawable property value
     * to the TransitionsValues.value Map for a target.
     */
    private void captureValues(TransitionValues values) {
        // Capture the property values of views for later use
        values.values.put(PROPNAME_BACKGROUND, values.view.getBackground());
    }

    @Override
    public void captureStartValues(TransitionValues transitionValues) {
        captureValues(transitionValues);
    }

    // Capture the value of the background drawable property for a target in the ending Scene.
    @Override
    public void captureEndValues(TransitionValues transitionValues) {
        captureValues(transitionValues);
    }
    // END_INCLUDE (capture_values)

    // BEGIN_INCLUDE (create_animator)
    // Create an animation for each target that is in both the starting and ending Scene. For each
    // pair of targets, if their background property value is a color (rather than a graphic),
    // create a ValueAnimator based on an ArgbEvaluator that interpolates between the starting and
    // ending color. Also create an update listener that sets the View background color for each
    // animation frame
    @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)

}

自定義Transition的使用和內建的Fade、ChangeBounds等是完全相同的。

(本文使用Atom編寫)


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 AutoPoster 的頭像
    AutoPoster

    互聯網 - 大數據

    AutoPoster 發表在 痞客邦 留言(0) 人氣()