Home | History | Annotate | Download | only in com.example.android.customtransition
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.customtransition;
     18 
     19 import android.animation.Animator;
     20 import android.animation.ArgbEvaluator;
     21 import android.animation.ObjectAnimator;
     22 import android.animation.PropertyValuesHolder;
     23 import android.animation.ValueAnimator;
     24 import android.graphics.drawable.ColorDrawable;
     25 import android.graphics.drawable.Drawable;
     26 import android.graphics.drawable.TransitionDrawable;
     27 import android.transition.ChangeBounds;
     28 import android.transition.Transition;
     29 import android.transition.TransitionValues;
     30 import android.view.View;
     31 import android.view.ViewGroup;
     32 import android.view.ViewPropertyAnimator;
     33 
     34 public class ChangeColor extends Transition {
     35 
     36     /** Key to store a color value in TransitionValues object */
     37     private static final String PROPNAME_BACKGROUND = "customtransition:change_color:background";
     38 
     39     // BEGIN_INCLUDE (capture_values)
     40     /**
     41      * Convenience method: Add the background Drawable property value
     42      * to the TransitionsValues.value Map for a target.
     43      */
     44     private void captureValues(TransitionValues values) {
     45         // Capture the property values of views for later use
     46         values.values.put(PROPNAME_BACKGROUND, values.view.getBackground());
     47     }
     48 
     49     @Override
     50     public void captureStartValues(TransitionValues transitionValues) {
     51         captureValues(transitionValues);
     52     }
     53 
     54     // Capture the value of the background drawable property for a target in the ending Scene.
     55     @Override
     56     public void captureEndValues(TransitionValues transitionValues) {
     57         captureValues(transitionValues);
     58     }
     59     // END_INCLUDE (capture_values)
     60 
     61     // BEGIN_INCLUDE (create_animator)
     62     // Create an animation for each target that is in both the starting and ending Scene. For each
     63     // pair of targets, if their background property value is a color (rather than a graphic),
     64     // create a ValueAnimator based on an ArgbEvaluator that interpolates between the starting and
     65     // ending color. Also create an update listener that sets the View background color for each
     66     // animation frame
     67     @Override
     68     public Animator createAnimator(ViewGroup sceneRoot,
     69                                    TransitionValues startValues, TransitionValues endValues) {
     70         // This transition can only be applied to views that are on both starting and ending scenes.
     71         if (null == startValues || null == endValues) {
     72             return null;
     73         }
     74         // Store a convenient reference to the target. Both the starting and ending layout have the
     75         // same target.
     76         final View view = endValues.view;
     77         // Store the object containing the background property for both the starting and ending
     78         // layouts.
     79         Drawable startBackground = (Drawable) startValues.values.get(PROPNAME_BACKGROUND);
     80         Drawable endBackground = (Drawable) endValues.values.get(PROPNAME_BACKGROUND);
     81         // This transition changes background colors for a target. It doesn't animate any other
     82         // background changes. If the property isn't a ColorDrawable, ignore the target.
     83         if (startBackground instanceof ColorDrawable && endBackground instanceof ColorDrawable) {
     84             ColorDrawable startColor = (ColorDrawable) startBackground;
     85             ColorDrawable endColor = (ColorDrawable) endBackground;
     86             // If the background color for the target in the starting and ending layouts is
     87             // different, create an animation.
     88             if (startColor.getColor() != endColor.getColor()) {
     89                 // Create a new Animator object to apply to the targets as the transitions framework
     90                 // changes from the starting to the ending layout. Use the class ValueAnimator,
     91                 // which provides a timing pulse to change property values provided to it. The
     92                 // animation runs on the UI thread. The Evaluator controls what type of
     93                 // interpolation is done. In this case, an ArgbEvaluator interpolates between two
     94                 // #argb values, which are specified as the 2nd and 3rd input arguments.
     95                 ValueAnimator animator = ValueAnimator.ofObject(new ArgbEvaluator(),
     96                         startColor.getColor(), endColor.getColor());
     97                 // Add an update listener to the Animator object.
     98                 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
     99                     @Override
    100                     public void onAnimationUpdate(ValueAnimator animation) {
    101                         Object value = animation.getAnimatedValue();
    102                         // Each time the ValueAnimator produces a new frame in the animation, change
    103                         // the background color of the target. Ensure that the value isn't null.
    104                         if (null != value) {
    105                             view.setBackgroundColor((Integer) value);
    106                         }
    107                     }
    108                 });
    109                 // Return the Animator object to the transitions framework. As the framework changes
    110                 // between the starting and ending layouts, it applies the animation you've created.
    111                 return animator;
    112             }
    113         }
    114         // For non-ColorDrawable backgrounds, we just return null, and no animation will take place.
    115         return null;
    116     }
    117     // END_INCLUDE (create_animator)
    118 
    119 }
    120