I\'m trying to do a shared element transition between two activities.
The first activity has a circle imageview and the second activity has a rectangular imageview. I ju
There's some code you need to add: basically you have to implement a custom transition. But most of the code can be reused. I'm going to push the code on github for your reference, but the steps needed are:
SecondAcvitiy Create your custom transition:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Transition transition = new CircularReveal();
transition.setInterpolator(new LinearInterpolator());
getWindow().setSharedElementEnterTransition(transition);
}
CircularReveal capture view bounds (start and end values) and provide two animations, the first one when you need to animate the circular image view to the big one, the second for the reverse case.
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class CircularReveal extends Transition {
private static final String BOUNDS = "viewBounds";
private static final String[] PROPS = {BOUNDS};
@Override
public void captureStartValues(TransitionValues transitionValues) {
captureValues(transitionValues);
}
@Override
public void captureEndValues(TransitionValues transitionValues) {
captureValues(transitionValues);
}
private void captureValues(TransitionValues values) {
View view = values.view;
Rect bounds = new Rect();
bounds.left = view.getLeft();
bounds.right = view.getRight();
bounds.top = view.getTop();
bounds.bottom = view.getBottom();
values.values.put(BOUNDS, bounds);
}
@Override
public String[] getTransitionProperties() {
return PROPS;
}
@Override
public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) {
if (startValues == null || endValues == null) {
return null;
}
Rect startRect = (Rect) startValues.values.get(BOUNDS);
final Rect endRect = (Rect) endValues.values.get(BOUNDS);
final View view = endValues.view;
Animator circularTransition;
if (isReveal(startRect, endRect)) {
circularTransition = createReveal(view, startRect, endRect);
return new NoPauseAnimator(circularTransition);
} else {
layout(startRect, view);
circularTransition = createConceal(view, startRect, endRect);
circularTransition.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
view.setOutlineProvider(new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
Rect bounds = endRect;
bounds.left -= view.getLeft();
bounds.top -= view.getTop();
bounds.right -= view.getLeft();
bounds.bottom -= view.getTop();
outline.setOval(bounds);
view.setClipToOutline(true);
}
});
}
});
return new NoPauseAnimator(circularTransition);
}
}
private void layout(Rect startRect, View view) {
view.layout(startRect.left, startRect.top, startRect.right, startRect.bottom);
}
private Animator createReveal(View view, Rect from, Rect to) {
int centerX = from.centerX();
int centerY = from.centerY();
float finalRadius = (float) Math.hypot(to.width(), to.height());
return ViewAnimationUtils.createCircularReveal(view, centerX, centerY,
from.width()/2, finalRadius);
}
private Animator createConceal(View view, Rect from, Rect to) {
int centerX = to.centerX();
int centerY = to.centerY();
float initialRadius = (float) Math.hypot(from.width(), from.height());
return ViewAnimationUtils.createCircularReveal(view, centerX, centerY,
initialRadius, to.width()/2);
}
private boolean isReveal(Rect startRect, Rect endRect) {
return startRect.width() < endRect.width();
}
}