diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
index 26fcbabe7..7e8c9e1eb 100644
--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -1295,8 +1295,8 @@
+ android:enabled="@bool/atLeastHoneycomb"
+ android:theme="@style/ActivityTransitionTheme">
@@ -1304,9 +1304,9 @@
+ android:label="Animation/Details of a specific thingy"
+ android:enabled="@bool/atLeastHoneycomb"
+ android:theme="@style/ActivityTransitionTheme">
diff --git a/samples/ApiDemos/res/layout/image_block.xml b/samples/ApiDemos/res/layout/image_block.xml
index 50d7d049e..58d6a23d1 100644
--- a/samples/ApiDemos/res/layout/image_block.xml
+++ b/samples/ApiDemos/res/layout/image_block.xml
@@ -1,20 +1,21 @@
\ No newline at end of file
diff --git a/samples/ApiDemos/res/layout/image_details.xml b/samples/ApiDemos/res/layout/image_details.xml
index a1a745921..c58d70409 100644
--- a/samples/ApiDemos/res/layout/image_details.xml
+++ b/samples/ApiDemos/res/layout/image_details.xml
@@ -4,15 +4,22 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
+ android:clipChildren="false"
>
-
+
+
+
@@ -30,7 +37,7 @@
android:layout_height="2dp"
android:background="#808080"/>
@@ -38,7 +45,7 @@
android:layout_height="2dp"
android:background="#808080"/>
@@ -46,7 +53,7 @@
android:layout_height="2dp"
android:background="#808080"/>
@@ -54,7 +61,7 @@
android:layout_height="2dp"
android:background="#808080"/>
@@ -62,7 +69,7 @@
android:layout_height="2dp"
android:background="#808080"/>
@@ -70,7 +77,7 @@
android:layout_height="2dp"
android:background="#808080"/>
@@ -78,7 +85,7 @@
android:layout_height="2dp"
android:background="#808080"/>
diff --git a/samples/ApiDemos/src/com/example/android/apis/animation/ActivityTransition.java b/samples/ApiDemos/src/com/example/android/apis/animation/ActivityTransition.java
index c3171c43e..2c8c0428c 100644
--- a/samples/ApiDemos/src/com/example/android/apis/animation/ActivityTransition.java
+++ b/samples/ApiDemos/src/com/example/android/apis/animation/ActivityTransition.java
@@ -17,23 +17,18 @@ package com.example.android.apis.animation;
import com.example.android.apis.R;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.RectEvaluator;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Intent;
-import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.transition.ChangeBounds;
+import android.transition.Transition;
import android.transition.TransitionManager;
import android.transition.TransitionSet;
-import android.util.Property;
+import android.util.ArrayMap;
+import android.util.Pair;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroupOverlay;
import android.view.Window;
import android.widget.ImageView;
@@ -43,138 +38,52 @@ import java.util.Random;
*
*/
public class ActivityTransition extends Activity {
+
private static final String TAG = "ActivityTransition";
- private static final String KEY_LEFT_ON_SCREEN = "ViewTransitionValues:left:";
- private static final String KEY_TOP_ON_SCREEN = "ViewTransitionValues:top:";
- private static final String KEY_WIDTH = "ViewTransitionValues:width:";
- private static final String KEY_HEIGHT = "ViewTransitionValues:height:";
private static final String KEY_ID = "ViewTransitionValues:id";
private Random mRandom = new Random();
- private boolean mComeBack;
- private Fall mFall;
+
+ private ImageView mHero;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CONTENT_TRANSITIONS);
- setEarlyBackgroundTransition(false);
+ getWindow().setTriggerEarlyEnterTransition(true);
getWindow().setBackgroundDrawable(new ColorDrawable(randomColor()));
setContentView(R.layout.image_block);
- View hero = getHero();
- if (hero != null) {
- hero.setSharedElementName("hero");
- }
+ setupHero();
TransitionManager transitionManager = getContentTransitionManager();
TransitionSet transitions = new TransitionSet();
Fall fall = new Fall();
fall.setDuration(600);
- fall.setStartDelay(600);
- fall.setHero(hero);
transitions.addTransition(fall);
+ transitions.addTransition(new ScaleTransition());
+ transitions.addTransition(new ChangeBounds());
transitions.addTransition(new Up());
- transitionManager.setTransition("null", getContentScene(), transitions);
-
- transitions = new TransitionSet();
- mFall = new Fall();
- mFall.setDuration(600);
- transitions.addTransition(mFall);
- transitions.addTransition(new Up());
- transitionManager.setTransition(getContentScene(), "null", transitions);
+ transitionManager.setTransition(getContentScene(), transitions);
+ transitionManager.setExitTransition(getContentScene(), transitions);
}
- @Override
- protected void onResume() {
- super.onResume();
- if (mComeBack) {
- mComeBack = false;
- setContentView(R.layout.image_block);
+ private void setupHero() {
+ int id = getIntent().getIntExtra(KEY_ID, 0);
+ mHero = (ImageView) findViewById(id);
+ if (mHero != null) {
+ ArrayMap sharedElementsMap = new ArrayMap();
+ sharedElementsMap.put("hero", mHero.getSharedElementName());
+ getWindow().mapTransitionTargets(sharedElementsMap);
}
}
- private View getHero() {
- Bundle transitionArgs = getTransitionArgs();
- if (transitionArgs == null) {
- return null;
- }
- int id = transitionArgs.getInt(KEY_ID);
- return findViewById(id);
- }
-
- private static Property DRAWABLE_BOUNDS
- = new Property(Rect.class, "bounds") {
- @Override
- public Rect get(Drawable object) {
- return null;
- }
-
- @Override
- public void set(Drawable object, Rect value) {
- object.setBounds(value);
- object.invalidateSelf();
- }
- };
-
- @Override
- public void startSharedElementTransition(Bundle transitionArgs) {
- final ImageView hero = (ImageView)getHero();
- hero.setSharedElementName(null);
- hero.setVisibility(View.INVISIBLE);
-
- int[] loc = new int[2];
- hero.getLocationOnScreen(loc);
- int endScreenLeft = loc[0];
- int endScreenTop = loc[1];
- int originalWidth = hero.getWidth();
- int originalHeight = hero.getHeight();
-
- hero.setVisibility(View.INVISIBLE);
- ViewGroup sceneRoot = getContentScene().getSceneRoot();
- sceneRoot.getLocationOnScreen(loc);
- int overlayLeft = loc[0];
- int overlayTop = loc[1];
- final ViewGroupOverlay overlay = sceneRoot.getOverlay();
-
- int endX = endScreenLeft - overlayLeft;
- int endY = endScreenTop - overlayTop;
-
- int startX = transitionArgs.getInt(KEY_LEFT_ON_SCREEN) - overlayLeft;
- int startY = transitionArgs.getInt(KEY_TOP_ON_SCREEN) - overlayTop;
- int startWidth = transitionArgs.getInt(KEY_WIDTH);
- int startHeight = transitionArgs.getInt(KEY_HEIGHT);
-
- int endHeight = originalWidth * startHeight / startWidth;
- final Drawable image = hero.getDrawable();
- Rect startBounds = new Rect(startX, startY, startX + startWidth, startY + startHeight);
- endY += originalHeight - endHeight;
- Rect endBounds = new Rect(endX, endY, endX + originalWidth, endY + endHeight);
- ObjectAnimator boundsAnimator = ObjectAnimator.ofObject(image, DRAWABLE_BOUNDS,
- new RectEvaluator(new Rect()), startBounds, endBounds);
- hero.setImageDrawable(null);
- image.setBounds(startBounds);
- overlay.add(image);
-
- boundsAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- overlay.remove(image);
- hero.setImageDrawable(image);
- hero.setVisibility(View.VISIBLE);
- }
- });
- boundsAnimator.start();
- }
-
public void clicked(View v) {
- v.setSharedElementName("hero");
- mFall.setHero(v);
+ mHero = (ImageView) v;
Intent intent = new Intent(this, ActivityTransitionDetails.class);
- Bundle args = getHeroInfo(v);
- ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(args);
- startActivity(intent, options.toBundle());
- //v.setTranslationZ(300);
- mComeBack = true;
+ intent.putExtra(KEY_ID, v.getId());
+ ActivityOptions activityOptions
+ = ActivityOptions.makeSceneTransitionAnimation(mHero, "hero");
+ startActivity(intent, activityOptions.toBundle());
}
private int randomColor() {
@@ -184,15 +93,25 @@ public class ActivityTransition extends Activity {
return 0xFF000000 | (red << 16) | (green << 8) | blue;
}
- static Bundle getHeroInfo(View view) {
- int[] loc = new int[2];
- view.getLocationOnScreen(loc);
- Bundle bundle = new Bundle();
- bundle.putInt(KEY_LEFT_ON_SCREEN, loc[0]);
- bundle.putInt(KEY_TOP_ON_SCREEN, loc[1]);
- bundle.putInt(KEY_WIDTH, view.getWidth());
- bundle.putInt(KEY_HEIGHT, view.getHeight());
- bundle.putInt(KEY_ID, view.getId());
- return bundle;
+ @Override
+ public void onCaptureSharedElementStart(Transition transition) {
+ int width = mHero.getWidth();
+ int newTop = mHero.getBottom() - width;
+ mHero.setTop(newTop);
+
+ int imageWidth = mHero.getDrawable().getIntrinsicWidth();
+ mHero.setPivotX(0);
+ mHero.setPivotY(0);
+ float scale = ((float)width)/imageWidth;
+ mHero.setScaleX(scale);
+ mHero.setScaleY(scale);
+ }
+
+ @Override
+ public void onCaptureSharedElementEnd() {
+ mHero.setPivotX(0);
+ mHero.setPivotY(0);
+ mHero.setScaleX(1);
+ mHero.setScaleY(1);
}
}
diff --git a/samples/ApiDemos/src/com/example/android/apis/animation/ActivityTransitionDetails.java b/samples/ApiDemos/src/com/example/android/apis/animation/ActivityTransitionDetails.java
index d0b2c4f5a..2e40d9eb4 100644
--- a/samples/ApiDemos/src/com/example/android/apis/animation/ActivityTransitionDetails.java
+++ b/samples/ApiDemos/src/com/example/android/apis/animation/ActivityTransitionDetails.java
@@ -17,26 +17,18 @@ package com.example.android.apis.animation;
import com.example.android.apis.R;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.RectEvaluator;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Intent;
-import android.graphics.Matrix;
-import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.transition.ChangeBounds;
+import android.transition.Transition;
import android.transition.TransitionManager;
import android.transition.TransitionSet;
-import android.util.Log;
-import android.util.Property;
+import android.util.Pair;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroupOverlay;
-import android.view.ViewTreeObserver;
import android.view.Window;
import android.widget.ImageView;
@@ -46,72 +38,94 @@ import java.util.Random;
*
*/
public class ActivityTransitionDetails extends Activity {
+
private static final String TAG = "ActivityTransitionDetails";
- private static final String KEY_LEFT_ON_SCREEN = "ViewTransitionValues:left:";
- private static final String KEY_TOP_ON_SCREEN = "ViewTransitionValues:top:";
- private static final String KEY_WIDTH = "ViewTransitionValues:width:";
- private static final String KEY_HEIGHT = "ViewTransitionValues:height:";
private static final String KEY_ID = "ViewTransitionValues:id";
private Random mRandom = new Random();
- private boolean mComeBack;
+
private int mImageResourceId = R.drawable.ducky;
- private int mId;
+
+ private int mId = R.id.ducky;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CONTENT_TRANSITIONS);
- setEarlyBackgroundTransition(false);
+ getWindow().setTriggerEarlyEnterTransition(false);
getWindow().setBackgroundDrawable(new ColorDrawable(randomColor()));
setContentView(R.layout.image_details);
- setImageMatrix();
- ImageView hero = (ImageView)findViewById(R.id.titleImage);
- hero.setImageDrawable(getHeroDrawable());
- //hero.setTranslationZ(300);
+ ImageView titleImage = (ImageView) findViewById(R.id.titleImage);
+ titleImage.setImageDrawable(getHeroDrawable());
+
TransitionManager transitionManager = getContentTransitionManager();
TransitionSet transitions = new TransitionSet();
+
Fall fall = new Fall();
fall.setDuration(600);
- fall.setStartDelay(600);
transitions.addTransition(fall);
transitions.addTransition(new Up());
- transitionManager.setTransition("null", getContentScene(), transitions);
-
- transitions = new TransitionSet();
- fall = new Fall();
- fall.setDuration(600);
- transitions.addTransition(fall);
- transitions.addTransition(new Up());
- transitionManager.setTransition(getContentScene(), "null", transitions);
+ transitions.addTransition(new ChangeBounds());
+ transitions.addTransition(new ScaleTransition());
+ transitionManager.setTransition(getContentScene(), transitions);
+ transitionManager.setExitTransition(getContentScene(), transitions);
}
@Override
- protected void onResume() {
- super.onResume();
- if (mComeBack) {
- mComeBack = false;
- setContentView(R.layout.image_details);
- ImageView hero = (ImageView)findViewById(R.id.titleImage);
- hero.setImageDrawable(getHeroDrawable());
- setImageMatrix();
- }
+ public void onCaptureSharedElementStart(Transition transition) {
+ ImageView imageView = (ImageView) findViewById(R.id.titleImage);
+ imageView.setScaleX(1);
+ imageView.setScaleY(1);
+ imageView.offsetTopAndBottom(-imageView.getTop());
+ }
+
+ @Override
+ public void onCaptureSharedElementEnd() {
+ setScale();
+ }
+
+ private void setScale() {
+ ImageView imageView = (ImageView) findViewById(R.id.titleImage);
+ Drawable drawable = imageView.getDrawable();
+ float intrinsicWidth = drawable.getIntrinsicWidth();
+ View sharedElementTarget = findViewById(R.id.shared_element);
+ float scale = sharedElementTarget.getWidth()/intrinsicWidth;
+ imageView.setPivotY(imageView.getHeight());
+ imageView.setScaleX(scale);
+ imageView.setScaleY(scale);
}
private Drawable getHeroDrawable() {
- Bundle args = getTransitionArgs();
- int id = args == null ? 0 : args.getInt(KEY_ID);
+ int id = getIntent().getIntExtra(KEY_ID, mId);
+ mId = id;
+
int resourceId;
switch (id) {
- case R.id.ducky: resourceId = R.drawable.ducky; break;
- case R.id.jellies: resourceId = R.drawable.jellies; break;
- case R.id.mug: resourceId = R.drawable.mug; break;
- case R.id.pencil: resourceId = R.drawable.pencil; break;
- case R.id.scissors: resourceId = R.drawable.scissors; break;
- case R.id.woot: resourceId = R.drawable.woot; break;
- case R.id.ball: resourceId = R.drawable.ball; break;
- case R.id.block: resourceId = R.drawable.block; break;
+ case R.id.ducky:
+ resourceId = R.drawable.ducky;
+ break;
+ case R.id.jellies:
+ resourceId = R.drawable.jellies;
+ break;
+ case R.id.mug:
+ resourceId = R.drawable.mug;
+ break;
+ case R.id.pencil:
+ resourceId = R.drawable.pencil;
+ break;
+ case R.id.scissors:
+ resourceId = R.drawable.scissors;
+ break;
+ case R.id.woot:
+ resourceId = R.drawable.woot;
+ break;
+ case R.id.ball:
+ resourceId = R.drawable.ball;
+ break;
+ case R.id.block:
+ resourceId = R.drawable.block;
+ break;
default:
resourceId = mImageResourceId;
break;
@@ -120,96 +134,11 @@ public class ActivityTransitionDetails extends Activity {
return getResources().getDrawable(resourceId);
}
- private static Property DRAWABLE_BOUNDS
- = new Property(Rect.class, "bounds") {
- @Override
- public Rect get(Drawable object) {
- return null;
- }
-
- @Override
- public void set(Drawable object, Rect value) {
- object.setBounds(value);
- object.invalidateSelf();
- }
- };
-
- private void setImageMatrix() {
- getWindow().getDecorView().getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- getWindow().getDecorView().getViewTreeObserver().removeOnPreDrawListener(this);
- // Use an image matrix such that it aligns with the bottom.
- final ImageView hero = (ImageView)findViewById(R.id.titleImage);
- hero.setScaleType(ImageView.ScaleType.MATRIX);
- Matrix matrix = hero.getImageMatrix();
- int height = hero.getHeight();
- int width = hero.getWidth();
- Drawable image = hero.getDrawable();
- int intrinsicHeight = image.getIntrinsicHeight();
- int intrinsicWidth = image.getIntrinsicWidth();
- int scaledHeight = intrinsicHeight * width / intrinsicWidth;
- matrix.postTranslate(0, (height - scaledHeight) / 2);
- hero.setImageMatrix(matrix);
- return true;
- }
- });
- }
-
- @Override
- public void startSharedElementTransition(Bundle transitionArgs) {
- mId = transitionArgs.getInt(KEY_ID);
- final ImageView hero = (ImageView)findViewById(R.id.titleImage);
- int[] loc = new int[2];
- hero.getLocationOnScreen(loc);
- int endScreenLeft = loc[0];
- int endScreenTop = loc[1];
- int originalWidth = hero.getWidth();
- int originalHeight = hero.getHeight();
-
- hero.setVisibility(View.INVISIBLE);
- ViewGroup sceneRoot = getContentScene().getSceneRoot();
- sceneRoot.getLocationOnScreen(loc);
- int overlayLeft = loc[0];
- int overlayTop = loc[1];
- final ViewGroupOverlay overlay = sceneRoot.getOverlay();
-
- int endX = endScreenLeft - overlayLeft;
- int endY = endScreenTop - overlayTop;
-
- int startX = transitionArgs.getInt(KEY_LEFT_ON_SCREEN) - overlayLeft;
- int startY = transitionArgs.getInt(KEY_TOP_ON_SCREEN) - overlayTop;
- int startWidth = transitionArgs.getInt(KEY_WIDTH);
- int startHeight = transitionArgs.getInt(KEY_HEIGHT);
-
- int endHeight = originalWidth * startHeight / startWidth;
- final Drawable image = hero.getDrawable();
- Rect startBounds = new Rect(startX, startY, startX + startWidth, startY + startHeight);
- endY += originalHeight - endHeight;
- Rect endBounds = new Rect(endX, endY, endX + originalWidth, endY + endHeight);
- ObjectAnimator boundsAnimator = ObjectAnimator.ofObject(image, DRAWABLE_BOUNDS,
- new RectEvaluator(new Rect()), startBounds, endBounds);
- hero.setImageDrawable(null);
- image.setBounds(startBounds);
- overlay.add(image);
-
- boundsAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- overlay.remove(image);
- hero.setImageDrawable(image);
- hero.setVisibility(View.VISIBLE);
- }
- });
- boundsAnimator.start();
- }
-
public void clicked(View v) {
Intent intent = new Intent(this, ActivityTransition.class);
- Bundle args = getHeroInfo((ImageView)v);
- ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(args);
- startActivity(intent, options.toBundle());
- mComeBack = true;
+ intent.putExtra(KEY_ID, mId);
+ ActivityOptions activityOptions = ActivityOptions.makeSceneTransitionAnimation(v, "hero");
+ startActivity(intent, activityOptions.toBundle());
}
private int randomColor() {
@@ -219,22 +148,4 @@ public class ActivityTransitionDetails extends Activity {
return 0xFF000000 | (red << 16) | (green << 8) | blue;
}
- private Bundle getHeroInfo(ImageView view) {
- int[] loc = new int[2];
- view.getLocationOnScreen(loc);
- Bundle bundle = new Bundle();
- Drawable image = view.getDrawable();
- int intrinsicWidth = image.getIntrinsicWidth();
- int intrinsicHeight = image.getIntrinsicHeight();
- int width = view.getWidth();
- int height = intrinsicHeight * width / intrinsicWidth;
- int top = loc[1] + view.getHeight() - height;
- bundle.putInt(KEY_LEFT_ON_SCREEN, loc[0]);
- bundle.putInt(KEY_TOP_ON_SCREEN, top);
- bundle.putInt(KEY_WIDTH, width);
- bundle.putInt(KEY_HEIGHT, height);
- bundle.putInt(KEY_ID, mId);
- return bundle;
- }
-
}
diff --git a/samples/ApiDemos/src/com/example/android/apis/animation/Fall.java b/samples/ApiDemos/src/com/example/android/apis/animation/Fall.java
index e7281b383..6a866e572 100644
--- a/samples/ApiDemos/src/com/example/android/apis/animation/Fall.java
+++ b/samples/ApiDemos/src/com/example/android/apis/animation/Fall.java
@@ -20,11 +20,9 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
import android.transition.Transition;
import android.transition.TransitionValues;
import android.transition.Visibility;
-import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
@@ -39,11 +37,7 @@ public class Fall extends Visibility {
private static final String TAG = "Fall";
private static final String PROPNAME_SCREEN_LOCATION = "android:fade:screen_location";
- private View mHero;
-
- public void setHero(View hero) {
- mHero = hero;
- }
+ private View mFocusElement;
private Animator createAnimation(final View view, long startDelay, final float startY,
float endY, AnimatorListenerAdapter listener, TimeInterpolator interpolator) {
@@ -99,7 +93,6 @@ public class Fall extends Visibility {
return null;
}
final View endView = endValues.view;
- Log.v(TAG, "onAppear: " + endView.getId());
final float endY = endView.getTranslationY();
final float startY = endY + sceneRoot.getHeight();
@@ -136,8 +129,9 @@ public class Fall extends Visibility {
}
};
addListener(transitionListener);
+ View sharedElement = getFocusElement(sceneRoot);
int[] loc = (int[]) endValues.values.get(PROPNAME_SCREEN_LOCATION);
- long startDelay = calculateRiseStartDelay(sceneRoot, endView, loc);
+ long startDelay = calculateRiseStartDelay(sceneRoot, sharedElement, endView, loc);
return createAnimation(endView, startDelay, startY, endY, null, sDecelerate);
}
@@ -190,12 +184,13 @@ public class Fall extends Visibility {
}
}
final int finalVisibility = endVisibility;
+ View sharedElement = getFocusElement(sceneRoot);
int[] loc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION);
// TODO: add automatic facility to Visibility superclass for keeping views around
if (overlayView != null) {
// TODO: Need to do this for general case of adding to overlay
- long startDelay = calculateFallStartDelay(sceneRoot, overlayView, loc);
+ long startDelay = calculateFallStartDelay(sceneRoot, sharedElement, overlayView, loc);
int screenX = loc[0];
int screenY = loc[1];
loc = new int[2];
@@ -240,7 +235,7 @@ public class Fall extends Visibility {
return createAnimation(view, startDelay, startY, endY, endListener, sAccelerate);
}
if (viewToKeep != null) {
- long startDelay = calculateFallStartDelay(sceneRoot, viewToKeep, loc);
+ long startDelay = calculateFallStartDelay(sceneRoot, sharedElement, viewToKeep, loc);
// TODO: find a different way to do this, like just changing the view to be
// VISIBLE for the duration of the transition
viewToKeep.setVisibility((View.VISIBLE));
@@ -299,37 +294,73 @@ public class Fall extends Visibility {
return null;
}
- private long calculateFallStartDelay(View sceneRoot, View view, int[] viewLoc) {
+ private View getFocusElement(ViewGroup sceneRoot) {
+ if (mFocusElement == null) {
+ mFocusElement = findFocusElement(sceneRoot);
+ if (mFocusElement == null) {
+ mFocusElement = sceneRoot;
+ }
+ }
+ return (mFocusElement == sceneRoot) ? null : mFocusElement;
+ }
+
+ private static View findFocusElement(ViewGroup viewGroup) {
+ int numChildren = viewGroup.getChildCount();
+ for (int i = 0; i < numChildren; i++) {
+ View child = viewGroup.getChildAt(i);
+ String sharedElementName = child.getSharedElementName();
+ if (sharedElementName != null && !sharedElementName.startsWith("android:")) {
+ return child;
+ }
+ if (child instanceof ViewGroup) {
+ View sharedElement = findFocusElement((ViewGroup) child);
+ if (sharedElement != null) {
+ return sharedElement;
+ }
+ }
+ }
+ return null;
+ }
+
+ private long calculateFallStartDelay(ViewGroup sceneRoot, View shared, View view,
+ int[] viewLoc) {
int[] loc = new int[2];
sceneRoot.getLocationOnScreen(loc);
int bottom = loc[1] + sceneRoot.getHeight();
float distance = bottom - viewLoc[1] + view.getTranslationY();
- if (mHero != null) {
- mHero.getLocationOnScreen(loc);
- float heroX = loc[0] + mHero.getTranslationX() + (mHero.getWidth() / 2.0f);
+ if (shared != null) {
+ shared.getLocationOnScreen(loc);
+ float heroX = loc[0] + shared.getTranslationX() + (shared.getWidth() / 2.0f);
float viewX = viewLoc[0] + view.getTranslationX() + (view.getWidth() / 2.0f);
float distanceX = Math.abs(heroX - viewX);
float distanceXRatio = distanceX / sceneRoot.getWidth();
- distance += (1 - distanceXRatio) * mHero.getHeight();
+ distance += (1 - distanceXRatio) * shared.getHeight();
}
float distanceRatio = distance/sceneRoot.getHeight() / 3;
return Math.max(0, Math.round(distanceRatio * getDuration()));
}
- private long calculateRiseStartDelay(View sceneRoot, View view, int[] viewLoc) {
+ private long calculateRiseStartDelay(View sceneRoot, View shared, View view, int[] viewLoc) {
int[] loc = new int[2];
sceneRoot.getLocationOnScreen(loc);
int top = loc[1];
float distance = viewLoc[1] + view.getTranslationY() - top;
- if (mHero != null) {
- mHero.getLocationOnScreen(loc);
- float heroX = loc[0] + mHero.getTranslationX() + (mHero.getWidth() / 2.0f);
+ if (shared != null) {
+ shared.getLocationOnScreen(loc);
+ float heroX = loc[0] + shared.getTranslationX() + (shared.getWidth() / 2.0f);
float viewX = viewLoc[0] + view.getTranslationX() + (view.getWidth() / 2.0f);
float distanceX = Math.abs(heroX - viewX);
float distanceXRatio = distanceX / sceneRoot.getWidth();
- distance += distanceXRatio * mHero.getHeight();
+ distance += distanceXRatio * shared.getHeight();
}
float distanceRatio = distance/sceneRoot.getHeight() / 3;
return Math.max(0, Math.round(distanceRatio * getDuration()));
}
+
+ @Override
+ public Transition clone() {
+ Fall transition = (Fall) super.clone();
+ transition.mFocusElement = null;
+ return transition;
+ }
}
diff --git a/samples/ApiDemos/src/com/example/android/apis/animation/ScaleTransition.java b/samples/ApiDemos/src/com/example/android/apis/animation/ScaleTransition.java
new file mode 100644
index 000000000..787cdb374
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/animation/ScaleTransition.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 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 com.example.android.apis.animation;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.transition.Transition;
+import android.transition.TransitionValues;
+import android.util.Property;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ *
+ */
+public class ScaleTransition extends Transition {
+ private static final String PROPNAME_SCALE_X = "android:scale:x";
+ private static final String PROPNAME_SCALE_Y = "android:scale:y";
+ private static final String[] sTransitionProperties = {
+ PROPNAME_SCALE_X,
+ PROPNAME_SCALE_Y,
+ };
+
+ @Override
+ public String[] getTransitionProperties() {
+ return sTransitionProperties;
+ }
+
+ @Override
+ public void captureStartValues(TransitionValues transitionValues) {
+ captureValues(transitionValues);
+ }
+
+ @Override
+ public void captureEndValues(TransitionValues transitionValues) {
+ captureValues(transitionValues);
+ }
+
+ private void captureValues(TransitionValues transitionValues) {
+ transitionValues.values.put(PROPNAME_SCALE_X, transitionValues.view.getScaleX());
+ transitionValues.values.put(PROPNAME_SCALE_Y, transitionValues.view.getScaleY());
+ }
+
+ @Override
+ public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
+ TransitionValues endValues) {
+ if (startValues == null || endValues == null) {
+ return null;
+ }
+ Animator scaleXAnimator = createScaleAnimator(startValues, endValues, PROPNAME_SCALE_X,
+ View.SCALE_X);
+ Animator scaleYAnimator = createScaleAnimator(startValues, endValues, PROPNAME_SCALE_Y,
+ View.SCALE_Y);
+ if (scaleXAnimator == null) {
+ return scaleYAnimator;
+ } else if (scaleYAnimator == null) {
+ return scaleXAnimator;
+ }
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.playTogether(scaleXAnimator, scaleYAnimator);
+ return animatorSet;
+ }
+
+ private Animator createScaleAnimator(TransitionValues startValues, TransitionValues endValues,
+ String propertyName, Property scaleProperty) {
+ float start = (Float)startValues.values.get(propertyName);
+ float end = (Float)endValues.values.get(propertyName);
+ if (start == end) {
+ return null;
+ }
+ return ObjectAnimator.ofFloat(endValues.view, scaleProperty, start, end);
+ }
+}