Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android最新動畫框架完全解析(二)——Transitions Framework(Transitions 框架)

Android最新動畫框架完全解析(二)——Transitions Framework(Transitions 框架)

編輯:關於Android編程

前面一篇文章講解了Android動畫Animator,但是不知道你有沒有發現,前面講解的所有的動畫都是針對某一Object來進行的,雖然我們可以對整個Layout添加動畫效果,但這是先把整個layout看成一個整體,再對這個整體添加動畫效果。當我們想同時對多個Object添加動畫效果時又該怎麼做呢?

先來看一下效果

效果圖

為什麼要使用Transitions:

ViewGroup級別的動畫效果 只需確定動畫的開始和結束的狀態就可以完成整個動畫 有可以直接使用的常用動畫 支持從資源文件(Resource)載入動畫 生命周期中有回調函數,可以更好的控制動畫效果

Scenes

一個Scene保存了一個ViewGroup中所有元素的狀。同時他還擁有一個關於這個ViewGroup的父ViewGroup的引用,這個父ViewGroup稱為scene root。

Transitions

關於動畫的信息都存在一個Transition 對象中。通過 TransitionManager 使用Transition中動畫。Transitions 框架可以在兩個不同的Scene或者同一Scene的不同元素之間使用動畫。

限制

API Level 19 (Android 4.4.2) 使用在SurfaceView上可能會出錯
SurfaceView 是在一個非UI線程上更新的,所以可能會更其他元素的動畫不同步。 使用在TextureView上可能會出錯 使用在繼承自AdapterView的View,比如ListView上可能會出錯。 當你對TextView 使用動畫的時候,裡面的文字在動畫沒有結束之前可能會跑到其他地方。

創建Scene

Scene mAScene;
Scene mAnotherScene;

// Create the scene root for the scenes in this app
mSceneRoot = (ViewGroup) findViewById(R.id.scene_root);

// Create the scenes
mAScene = Scene.getSceneForLayout(mSceneRoot, R.layout.a_scene, this);
mAnotherScene =
    Scene.getSceneForLayout(mSceneRoot, R.layout.another_scene, this);

創建Scene Actions

Transitions 框架允許自定義進入和退出Scene時的Action。把自定義的Action定義成Runnable對象並把他們作為參數傳到Scene.setExitAction() 或者 Scene.setEnterAction() 中。系統會在進入和退出的時候調用這兩個方法。

創建Transition

從resource文件中創建Transition

步驟如下:

1 . 在項目中添加res/transition/目錄
2 . 在目錄中新建XML文件
res/transition/fade_transition.xml

3 . 在Activity中加載

Transition mFadeTransition =
        TransitionInflater.from(this).
        inflateTransition(R.transition.fade_transition);

在代碼中動態添加Transition

Transition mFadeTransition = new Fade();

調用Transition

TransitionManager.go(mEndingScene, mFadeTransition);

通過這一條語句,scene root中的View就會從初始狀態根據Transition 變為結束狀態。

對特定的View使用Transition

由於Transition框架並不是對所有的對象都適用(比如ListView ),所以有時我們需要指定使用Transition的對象。
每一個使用Transition的對象叫做一個target,當然這個對象需要在Scene中。可以通過在開始transition前調用 removeTarget() 方法去除不支持的對象或者調用addTarget()來添加對象。

使用transitionSet

transitionSet類似Animation中的Set,是一個動畫集合。定義在XML中,如下:


    
    
    

在Activity中調用TransitionInflater.from() 來加載TransitionSet。TransitionSet繼承自Transition,能用Transition的地方都可以使用TransitionSet。

自定義Transitions

繼承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()

框架會對開始Scene中的每一個對象調用captureStartValues()方法,方法的參數是TransitionValues 對象,這個對象包含對應這個View的一個引用和一個Map實例,這個Map實例用來保存你需要的屬性值,為了保證屬性值的Key不與其他的TransitionValues 的Key 沖突,推薦使用如下的命名規則。

package_name:transition_name:property_name

下面是一個重寫 captureStartValues() 的例子:

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

captureEndValues()

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

與captureStartValues()類似,把結束的值放入TransitionValues 的Map對象中,captureEndValues()中的Map對象與captureStartValues()中的Map不是同一個對象,put()的時候請放心~

createAnimator()

創建一個Animator用來負責從初始狀態到結束狀態的動畫效果,並把這個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;
    }

總結

關於Android動畫的所有基本知識到此就講完了,Animation主要為了實現單個對象的動畫效果,Transitions 框架可以同時實現多個對象的動畫效果。在實際項目中還需要根據具體需求選擇。基本知識雖然講完了,但是如何實現優美的效果還是很考驗美術功底的,比如說博主就是一個典型的失敗例子/(ㄒoㄒ)/~~

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved