Support changes in Scene Activity Transition API redo.
This reverts commit 1b3da3748f.
Change-Id: I84fd15c154a404ed10971025b7bb33f58a344965
This commit is contained in:
@@ -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<String, String> sharedElementsMap = new ArrayMap<String, String>();
|
||||
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, Rect> DRAWABLE_BOUNDS
|
||||
= new Property<Drawable, Rect>(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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, Rect> DRAWABLE_BOUNDS
|
||||
= new Property<Drawable, Rect>(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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<View, Float> 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user