/*
* 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.byoutline.kickmaterial.utils;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.transition.Transition;
import android.transition.TransitionValues;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class CircleTransition extends Transition {
private static final String PROPERTY_BOUNDS = "circleTransition:bounds";
private static final String PROPERTY_POSITION = "circleTransition:position";
private static final String PROPERTY_IMAGE = "circleTransition:image";
private static final String[] TRANSITION_PROPERTIES = {
PROPERTY_BOUNDS,
PROPERTY_POSITION,
};
public CircleTransition() {
}
public CircleTransition(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public String[] getTransitionProperties() {
return TRANSITION_PROPERTIES;
}
private void captureValues(TransitionValues transitionValues) {
final View view = transitionValues.view;
transitionValues.values.put(PROPERTY_BOUNDS, new Rect(
view.getLeft(), view.getTop(), view.getRight(), view.getBottom()
));
int[] position = new int[2];
transitionValues.view.getLocationInWindow(position);
transitionValues.values.put(PROPERTY_POSITION, position);
}
@Override
public void captureEndValues(TransitionValues transitionValues) {
final View view = transitionValues.view;
if (view.getWidth() <= 0 || view.getHeight() <= 0) {
return;
}
captureValues(transitionValues);
}
@Override
public void captureStartValues(TransitionValues transitionValues) {
final View view = transitionValues.view;
if (view.getWidth() <= 0 || view.getHeight() <= 0) {
return;
}
captureValues(transitionValues);
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
transitionValues.values.put(PROPERTY_IMAGE, bitmap);
}
@Override
public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
final TransitionValues endValues) {
if (startValues == null || endValues == null) {
return null;
}
Rect startBounds = (Rect) startValues.values.get(PROPERTY_BOUNDS);
Rect endBounds = (Rect) endValues.values.get(PROPERTY_BOUNDS);
boolean boundsEqual = startBounds == null || endBounds == null || startBounds.equals(endBounds);
if (boundsEqual) {
return null;
}
int[] sceneRootLoc = new int[2];
sceneRoot.getLocationInWindow(sceneRootLoc);
int[] startLoc = (int[]) startValues.values.get(PROPERTY_POSITION);
final View startView = getStartView(sceneRoot, startValues, sceneRootLoc, startLoc);
final View endView = endValues.view;
endView.setAlpha(0f);
Path circlePath = getMovePath(endValues, startView, sceneRootLoc, startLoc, endView);
Animator circleAnimator = ObjectAnimator.ofFloat(startView, View.TRANSLATION_X,
View.TRANSLATION_Y, circlePath);
circleAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
startView.setVisibility(View.INVISIBLE);
endView.setAlpha(1f);
sceneRoot.getOverlay().remove(startView);
}
});
AnimatorSet moveSet = new AnimatorSet();
float scaleRatio = ((float) endView.getWidth()) / startView.getWidth();
ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(startView, View.SCALE_X, 1, scaleRatio);
ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(startView, View.SCALE_Y, 1, scaleRatio);
moveSet.playTogether(circleAnimator, scaleXAnimator, scaleYAnimator);
// moveSet.setDuration(4000);
return moveSet;
}
private View getStartView(ViewGroup sceneRoot, TransitionValues startValues, int[] sceneRootLoc, int[] startLoc) {
Bitmap startImage = (Bitmap) startValues.values.get(PROPERTY_IMAGE);
Drawable startBackground = new BitmapDrawable(startImage);
final View startView = addViewToOverlay(sceneRoot, startImage.getWidth(),
startImage.getHeight(), startBackground);
int startTranslationX = startLoc[0] - sceneRootLoc[0];
int startTranslationY = startLoc[1] - sceneRootLoc[1];
startView.setTranslationX(startTranslationX);
startView.setTranslationY(startTranslationY);
return startView;
}
private Path getMovePath(TransitionValues endValues, View startView, int[] sceneRootLoc, int[] startLoc, View endView) {
float circleStartX = startLoc[0] - sceneRootLoc[0];
float circleStartY = startLoc[1] - sceneRootLoc[1];
int[] endLoc = (int[]) endValues.values.get(PROPERTY_POSITION);
float circleEndX = endLoc[0] - sceneRootLoc[0] +
((endView.getWidth() - startView.getWidth()) / 2);
float circleEndY = endLoc[1] - sceneRootLoc[1] +
((endView.getHeight() - startView.getHeight()) / 2);
return getPathMotion().getPath(circleStartX, circleStartY, circleEndX,
circleEndY);
}
private View addViewToOverlay(ViewGroup sceneRoot, int width, int height, Drawable background) {
View view = new View(sceneRoot.getContext());
view.setBackground(background);
int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
view.measure(widthSpec, heightSpec);
view.layout(0, 0, width, height);
sceneRoot.getOverlay().add(view);
return view;
}
}