Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 341a31b1 authored by Chet Haase's avatar Chet Haase Committed by Android (Google) Code Review
Browse files

Merge "First draft of Scenes & Transitions feature"

parents cabe99bb faebd8f0
Loading
Loading
Loading
Loading
+145 −0
Original line number Diff line number Diff line
@@ -512,6 +512,7 @@ package android {
    field public static final int freezesText = 16843116; // 0x101016c
    field public static final int fromAlpha = 16843210; // 0x10101ca
    field public static final int fromDegrees = 16843187; // 0x10101b3
    field public static final int fromScene = 16843737; // 0x10103d9
    field public static final int fromXDelta = 16843206; // 0x10101c6
    field public static final int fromXScale = 16843202; // 0x10101c2
    field public static final int fromYDelta = 16843208; // 0x10101c8
@@ -1012,6 +1013,7 @@ package android {
    field public static final int targetActivity = 16843266; // 0x1010202
    field public static final int targetClass = 16842799; // 0x101002f
    field public static final int targetDescriptions = 16843680; // 0x10103a0
    field public static final int targetID = 16843736; // 0x10103d8
    field public static final int targetPackage = 16842785; // 0x1010021
    field public static final int targetSdkVersion = 16843376; // 0x1010270
    field public static final int taskAffinity = 16842770; // 0x1010012
@@ -1100,6 +1102,7 @@ package android {
    field public static final int titleTextStyle = 16843512; // 0x10102f8
    field public static final int toAlpha = 16843211; // 0x10101cb
    field public static final int toDegrees = 16843188; // 0x10101b4
    field public static final int toScene = 16843738; // 0x10103da
    field public static final int toXDelta = 16843207; // 0x10101c7
    field public static final int toXScale = 16843203; // 0x10101c3
    field public static final int toYDelta = 16843209; // 0x10101c9
@@ -1114,6 +1117,7 @@ package android {
    field public static final int transcriptMode = 16843008; // 0x1010100
    field public static final int transformPivotX = 16843552; // 0x1010320
    field public static final int transformPivotY = 16843553; // 0x1010321
    field public static final int transition = 16843739; // 0x10103db
    field public static final int translationX = 16843554; // 0x1010322
    field public static final int translationY = 16843555; // 0x1010323
    field public static final int type = 16843169; // 0x10101a1
@@ -25965,6 +25969,7 @@ package android.view {
    method public java.lang.CharSequence getContentDescription();
    method public final android.content.Context getContext();
    method protected android.view.ContextMenu.ContextMenuInfo getContextMenuInfo();
    method public android.view.transition.Scene getCurrentScene();
    method public static int getDefaultSize(int, int);
    method public android.view.Display getDisplay();
    method public final int[] getDrawableState();
@@ -28112,6 +28117,146 @@ package android.view.textservice {
}
package android.view.transition {
  public class AutoTransition extends android.view.transition.TransitionGroup {
    ctor public AutoTransition();
  }
  public class Crossfade extends android.view.transition.Transition {
    ctor public Crossfade();
    method protected void captureValues(android.view.transition.TransitionValues, boolean);
    method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
  }
  public class Fade extends android.view.transition.Visibility {
    ctor public Fade();
    ctor public Fade(int);
    field public static final int IN = 1; // 0x1
    field public static final int OUT = 2; // 0x2
  }
  public class Move extends android.view.transition.Transition {
    ctor public Move();
    method protected void captureValues(android.view.transition.TransitionValues, boolean);
    method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
    method public void setReparent(boolean);
    method public void setResizeClip(boolean);
  }
  public class Recolor extends android.view.transition.Transition {
    ctor public Recolor();
    method protected void captureValues(android.view.transition.TransitionValues, boolean);
    method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
  }
  public class Rotate extends android.view.transition.Transition {
    ctor public Rotate();
    method protected void captureValues(android.view.transition.TransitionValues, boolean);
    method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
  }
  public final class Scene {
    ctor public Scene(android.view.ViewGroup);
    ctor public Scene(android.view.ViewGroup, int, android.content.Context);
    ctor public Scene(android.view.ViewGroup, android.view.ViewGroup);
    method public void enter();
    method public void exit();
    method public android.view.ViewGroup getSceneRoot();
    method public void setEnterAction(java.lang.Runnable);
    method public void setExitAction(java.lang.Runnable);
  }
  public class Slide extends android.view.transition.Visibility {
    ctor public Slide();
  }
  public class TextChange extends android.view.transition.Transition {
    ctor public TextChange();
    method protected void captureValues(android.view.transition.TransitionValues, boolean);
    method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
  }
  public abstract class Transition {
    ctor public Transition();
    method public void addListener(android.view.transition.Transition.TransitionListener);
    method protected void cancelTransition();
    method protected abstract void captureValues(android.view.transition.TransitionValues, boolean);
    method public long getDuration();
    method public android.animation.TimeInterpolator getInterpolator();
    method public java.util.ArrayList<android.view.transition.Transition.TransitionListener> getListeners();
    method public long getStartDelay();
    method public int[] getTargetIds();
    method public android.view.View[] getTargets();
    method protected void onTransitionCancel();
    method protected void onTransitionEnd();
    method protected void onTransitionStart();
    method protected abstract android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
    method protected boolean prePlay(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
    method public void removeListener(android.view.transition.Transition.TransitionListener);
    method public android.view.transition.Transition setDuration(long);
    method public void setInterpolator(android.animation.TimeInterpolator);
    method public void setStartDelay(long);
    method public android.view.transition.Transition setTargetIds(int...);
    method public android.view.transition.Transition setTargets(android.view.View...);
  }
  public static abstract interface Transition.TransitionListener {
    method public abstract void onTransitionCancel(android.view.transition.Transition);
    method public abstract void onTransitionEnd(android.view.transition.Transition);
    method public abstract void onTransitionStart(android.view.transition.Transition);
  }
  public class TransitionGroup extends android.view.transition.Transition {
    ctor public TransitionGroup();
    ctor public TransitionGroup(int);
    method public void addTransitions(android.view.transition.Transition...);
    method protected void captureValues(android.view.transition.TransitionValues, boolean);
    method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
    method public void removeTransition(android.view.transition.Transition);
    method public void setOrdering(int);
    field public static final int SEQUENTIALLY = 1; // 0x1
    field public static final int TOGETHER = 0; // 0x0
  }
  public class TransitionInflater {
    method public static android.view.transition.TransitionInflater from(android.content.Context);
    method public android.view.transition.Scene inflateScene(int, android.view.ViewGroup);
    method public android.view.transition.Transition inflateTransition(int);
    method public android.view.transition.TransitionManager inflateTransitionManager(int, android.view.ViewGroup);
  }
  public class TransitionManager {
    ctor public TransitionManager();
    method public android.view.transition.Transition getDefaultTransition();
    method public static void go(android.view.transition.Scene);
    method public static void go(android.view.transition.Scene, android.view.transition.Transition);
    method public static void go(android.view.ViewGroup, java.lang.Runnable);
    method public static void go(android.view.ViewGroup, java.lang.Runnable, android.view.transition.Transition);
    method public void setDefaultTransition(android.view.transition.Transition);
    method public void setTransition(android.view.transition.Scene, android.view.transition.Transition);
    method public void setTransition(android.view.transition.Scene, android.view.transition.Scene, android.view.transition.Transition);
    method public void transitionTo(android.view.transition.Scene);
  }
  public class TransitionValues {
    ctor public TransitionValues();
    field public final java.util.HashMap values;
    field public android.view.View view;
  }
  public abstract class Visibility extends android.view.transition.Transition {
    ctor public Visibility();
    method protected android.animation.Animator appear(android.view.ViewGroup, android.view.View, int, android.view.View, int);
    method protected void captureValues(android.view.transition.TransitionValues, boolean);
    method protected android.animation.Animator disappear(android.view.ViewGroup, android.view.View, int, android.view.View, int);
    method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
    method protected boolean preAppear(android.view.ViewGroup, android.view.View, int, android.view.View, int);
    method protected boolean preDisappear(android.view.ViewGroup, android.view.View, int, android.view.View, int);
  }
}
package android.webkit {
  public class ConsoleMessage {
+30 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ import android.view.animation.Transformation;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.transition.Scene;
import android.widget.ScrollBarDrawable;
import static android.os.Build.VERSION_CODES.*;
@@ -1572,6 +1573,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    protected Object mTag;
    private Scene mCurrentScene = null;
    // for mPrivateFlags:
    /** {@hide} */
    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
@@ -12037,6 +12040,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        mCurrentAnimation = null;
        mCurrentScene = null;
        resetAccessibilityStateChanged();
    }
@@ -17757,6 +17762,31 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        return mAnimator;
    }
    /**
     * Set the current Scene that this view is in. The current scene is set only
     * on the root view of a scene, not for every view in that hierarchy. This
     * information is used by Scene to determine whether there is a previous
     * scene which should be exited before the new scene is entered.
     *
     * @param scene The new scene being set on the view
     *
     * @hide
     */
    public void setCurrentScene(Scene scene) {
        mCurrentScene = scene;
    }
    /**
     * Gets the current {@link Scene} set on this view. A scene is set on a view
     * only if that view is the scene root.
     *
     * @return The current Scene set on this view. A value of null indicates that
     * no Scene is current set.
     */
    public Scene getCurrentScene() {
        return mCurrentScene;
    }
    /**
     * Interface definition for a callback to be invoked when a hardware key event is
     * dispatched to this view. The callback will be invoked before the key event is
+34 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.view.transition;

/**
 * Utility class for creating a default transition that automatically fades,
 * moves, and resizes views during a scene change.
 */
public class AutoTransition extends TransitionGroup {

    /**
     * Constructs an AutoTransition object, which is a TransitionGroup which
     * first fades out disappearing targets, then moves and resizes existing
     * targets, and finally fades in appearing targets.
     *
     */
    public AutoTransition() {
        setOrdering(SEQUENTIALLY);
        addTransitions(new Fade(Fade.OUT), new Move(), new Fade(Fade.IN));
    }
}
+163 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.view.transition;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.RectEvaluator;
import android.animation.ValueAnimator;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;

import java.util.HashMap;

/**
 * This transition captures bitmap representations of target views before and
 * after the scene change and fades between them.
 *
 * <p>Note: This transition is not compatible with {@link TextureView}
 * or {@link SurfaceView}.</p>
 */
public class Crossfade extends Transition {
    // TODO: Add a hook that lets a Transition call user code to query whether it should run on
    // a given target view. This would save bitmap comparisons in this transition, for example.

    private static final String LOG_TAG = "Crossfade";

    private static final String PROPNAME_BITMAP = "android:crossfade:bitmap";
    private static final String PROPNAME_DRAWABLE = "android:crossfade:drawable";
    private static final String PROPNAME_BOUNDS = "android:crossfade:bounds";

    private static RectEvaluator sRectEvaluator = new RectEvaluator();

    @Override
    protected boolean prePlay(ViewGroup sceneRoot, TransitionValues startValues,
            TransitionValues endValues) {
        if (startValues == null || endValues == null) {
            return false;
        }
        final View view = startValues.view;
        HashMap<String, Object> startVals = startValues.values;
        HashMap<String, Object> endVals = endValues.values;
        Bitmap startBitmap = (Bitmap) startVals.get(PROPNAME_BITMAP);
        Bitmap endBitmap = (Bitmap) endVals.get(PROPNAME_BITMAP);
        Drawable startDrawable = (Drawable) startVals.get(PROPNAME_DRAWABLE);
        Drawable endDrawable = (Drawable) endVals.get(PROPNAME_DRAWABLE);
        if (Transition.DBG) {
            Log.d(LOG_TAG, "StartBitmap.sameAs(endBitmap) = " + startBitmap.sameAs(endBitmap) +
                    " for start, end: " + startBitmap + ", " + endBitmap);
        }
        if (startDrawable != null && endDrawable != null && !startBitmap.sameAs(endBitmap)) {
            view.getOverlay().add(endDrawable);
            view.getOverlay().add(startDrawable);
            return true;
        } else {
            return false;
        }
    }

    @Override
    protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
            TransitionValues endValues) {
        if (startValues == null || endValues == null) {
            return null;
        }
        HashMap<String, Object> startVals = startValues.values;
        HashMap<String, Object> endVals = endValues.values;

        final View view = endValues.view;
        Rect startBounds = (Rect) startVals.get(PROPNAME_BOUNDS);
        Rect endBounds = (Rect) endVals.get(PROPNAME_BOUNDS);
        final BitmapDrawable startDrawable = (BitmapDrawable) startVals.get(PROPNAME_DRAWABLE);
        final BitmapDrawable endDrawable = (BitmapDrawable) endVals.get(PROPNAME_DRAWABLE);

        // The transition works by placing the end drawable under the start drawable and
        // gradually fading out the start drawable. So it's not really a cross-fade, but rather
        // a reveal of the end scene over time. Also, animate the bounds of both drawables
        // to mimic the change in the size of the view itself between scenes.
        ObjectAnimator anim = ObjectAnimator.ofInt(startDrawable, "alpha", 0);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // TODO: some way to auto-invalidate views based on drawable changes? callbacks?
                view.invalidate(startDrawable.getBounds());
            }
        });
        if (Transition.DBG) {
            Log.d(LOG_TAG, "Crossfade: created anim " + anim + " for start, end values " +
                    startValues + ", " + endValues);
        }
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                view.getOverlay().remove(startDrawable);
                view.getOverlay().remove(endDrawable);
            }
        });
        AnimatorSet set = new AnimatorSet();
        set.playTogether(anim);
        if (!startBounds.equals(endBounds)) {
            if (Transition.DBG) {
                Log.d(LOG_TAG, "animating from startBounds to endBounds: " +
                        startBounds + ", " + endBounds);
            }
            Animator anim2 = ObjectAnimator.ofObject(startDrawable, "bounds",
                    sRectEvaluator, startBounds, endBounds);
            Animator anim3 = ObjectAnimator.ofObject(endDrawable, "bounds",
                    sRectEvaluator, startBounds, endBounds);
            set.playTogether(anim2);
            set.playTogether(anim3);
        }
        return set;
    }

    @Override
    protected void captureValues(TransitionValues values, boolean start) {
        View view = values.view;
        values.values.put(PROPNAME_BOUNDS, new Rect(0, 0,
                view.getWidth(), view.getHeight()));

        if (Transition.DBG) {
            Log.d(LOG_TAG, "Captured bounds " + values.values.get(PROPNAME_BOUNDS) + ": start = " +
                    start);
        }
        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
                Bitmap.Config.ARGB_8888);
        if (view instanceof TextureView) {
            bitmap = ((TextureView) view).getBitmap();
        } else {
            Canvas c = new Canvas(bitmap);
            view.draw(c);
        }
        values.values.put(PROPNAME_BITMAP, bitmap);
        // TODO: I don't have resources, can't call the non-deprecated method?
        BitmapDrawable drawable = new BitmapDrawable(bitmap);
        // TODO: lrtb will be wrong if the view has transXY set
        drawable.setBounds(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
        values.values.put(PROPNAME_DRAWABLE, drawable);
    }

}
+209 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading