List of usage examples for android.animation AnimatorSet play
public Builder play(Animator anim)
Builder
object, which is used to set up playing constraints. From source file:com.msn.support.gallery.ZoomActivity.java
/** * "Zooms" in a thumbnail view by assigning the high resolution image to a hidden "zoomed-in" * image view and animating its bounds to fit the entire activity content area. More * specifically:/* www . j a va 2s . c om*/ * <ol> * <li>Assign the high-res image to the hidden "zoomed-in" (expanded) image view.</li> * <li>Calculate the starting and ending bounds for the expanded view.</li> * <li>Animate each of four positioning/sizing properties (X, Y, SCALE_X, SCALE_Y) * simultaneously, from the starting bounds to the ending bounds.</li> * <li>Zoom back out by running the reverse animation on click.</li> * </ol> * ??ImageView? * Activity * <ol> * <li>???ImageView</li> * <li>?ImageView?</li> * <li>??ImageView?/?X, Y, SCALE_X, SCALE_Y * ??</li> * <li>???</li> * @param thumbView The thumbnail view to zoom in. * @param imageResId The high-resolution version of the image represented by the thumbnail. * */ @TargetApi(11) private void zoomImageFromThumb(final View thumbView, int imageResId) { // If there's an animation in progress, cancel it immediately and proceed with this one. // ? if (mCurrentAnimator != null) { mCurrentAnimator.cancel(); } // Load the high-resolution "zoomed-in" image.?ImageView final ImageView expandedImageView = (ImageView) findViewById(R.id.expanded_image); expandedImageView.setImageResource(imageResId); // Calculate the starting and ending bounds for the zoomed-in image. This step // involves lots of math. Yay, math. //?ImageView?? final Rect startBounds = new Rect(); final Rect finalBounds = new Rect(); final Point globalOffset = new Point(); // The start bounds are the global visible rectangle of the thumbnail, and the // final bounds are the global visible rectangle of the container view. Also // set the container view's offset as the origin for the bounds, since that's // the origin for the positioning animation properties (X, Y). // ????? // ???? thumbView.getGlobalVisibleRect(startBounds); findViewById(R.id.container).getGlobalVisibleRect(finalBounds, globalOffset); Log.e("Test", "globalOffset.x=" + globalOffset.x + " globalOffset.y=" + globalOffset.y); Log.e("Test", "startBounds.top=" + startBounds.top + " startBounds.left=" + startBounds.left); startBounds.offset(-globalOffset.x, -globalOffset.y); Log.e("Test", "startBounds2.top=" + startBounds.top + " startBounds2.left=" + startBounds.left); finalBounds.offset(-globalOffset.x, -globalOffset.y); // Adjust the start bounds to be the same aspect ratio as the final bounds using the // "center crop" technique. This prevents undesirable stretching during the animation. // Also calculate the start scaling factor (the end scaling factor is always 1.0). // ??"center crop"??? // ????1.0 float startScale; if ((float) finalBounds.width() / finalBounds.height() > (float) startBounds.width() / startBounds.height()) { // Extend start bounds horizontally ? startScale = (float) startBounds.height() / finalBounds.height(); float startWidth = startScale * finalBounds.width(); float deltaWidth = (startWidth - startBounds.width()) / 2; startBounds.left -= deltaWidth; startBounds.right += deltaWidth; } else { // Extend start bounds vertically ? startScale = (float) startBounds.width() / finalBounds.width(); float startHeight = startScale * finalBounds.height(); float deltaHeight = (startHeight - startBounds.height()) / 2; startBounds.top -= deltaHeight; startBounds.bottom += deltaHeight; } // Hide the thumbnail and show the zoomed-in view. When the animation begins, // it will position the zoomed-in view in the place of the thumbnail. //thumbView.setAlpha(0f); expandedImageView.setVisibility(View.VISIBLE); // Set the pivot point for SCALE_X and SCALE_Y transformations to the top-left corner of // the zoomed-in view (the default is the center of the view). expandedImageView.setPivotX(0f); expandedImageView.setPivotY(0f); // Construct and run the parallel animation of the four translation and scale properties // (X, Y, SCALE_X, and SCALE_Y). AnimatorSet set = new AnimatorSet(); set.play(ObjectAnimator.ofFloat(expandedImageView, View.X, startBounds.left, finalBounds.left)) .with(ObjectAnimator.ofFloat(expandedImageView, View.Y, startBounds.top, finalBounds.top)) .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X, startScale, 1f)) .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y, startScale, 1f)); set.setDuration(mShortAnimationDuration); set.setInterpolator(new DecelerateInterpolator()); set.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mCurrentAnimator = null; } @Override public void onAnimationCancel(Animator animation) { mCurrentAnimator = null; } }); set.start(); mCurrentAnimator = set; // Upon clicking the zoomed-in image, it should zoom back down to the original bounds // and show the thumbnail instead of the expanded image. final float startScaleFinal = startScale; expandedImageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mCurrentAnimator != null) { mCurrentAnimator.cancel(); } // Animate the four positioning/sizing properties in parallel, back to their // original values. AnimatorSet set = new AnimatorSet(); set.play(ObjectAnimator.ofFloat(expandedImageView, View.X, startBounds.left)) .with(ObjectAnimator.ofFloat(expandedImageView, View.Y, startBounds.top)) .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X, startScaleFinal)) .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y, startScaleFinal)); set.setDuration(mShortAnimationDuration); set.setInterpolator(new DecelerateInterpolator()); set.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { thumbView.setAlpha(1f); expandedImageView.setVisibility(View.GONE); mCurrentAnimator = null; } @Override public void onAnimationCancel(Animator animation) { thumbView.setAlpha(1f); expandedImageView.setVisibility(View.GONE); mCurrentAnimator = null; } }); set.start(); mCurrentAnimator = set; } }); }
From source file:com.google.samples.apps.ourstreets.fragment.GalleryFragment.java
/** * Perform the animation from loading progress to the actual fragment's content. */// ww w . j av a2s . c om private void animateProgressToContent() { AnimatorSet animatorSet = new AnimatorSet(); FrameLayout targetView = ((FrameLayout) getView()); //noinspection ConstantConditions animatorSet.play(createCircularReveal(targetView)).with(createColorChange(targetView)); animatorSet.start(); }
From source file:fr.tvbarthel.apps.cameracolorpicker.activities.MainActivity.java
/** * Make a subtle animation for a {@link com.melnykov.fab.FloatingActionButton} drawing attention to the button. * * @param fab the {@link com.melnykov.fab.FloatingActionButton} to animate. *///from w w w .j a v a2 s . co m private void animateFab(final FloatingActionButton fab) { fab.postDelayed(new Runnable() { @Override public void run() { // Play a subtle animation final long duration = 450; final ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(fab, View.SCALE_X, 1f, 1.2f, 1f); scaleXAnimator.setDuration(duration); scaleXAnimator.setRepeatCount(1); final ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(fab, View.SCALE_Y, 1f, 1.2f, 1f); scaleYAnimator.setDuration(duration); scaleYAnimator.setRepeatCount(1); scaleXAnimator.start(); scaleYAnimator.start(); final AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(scaleXAnimator).with(scaleYAnimator); animatorSet.start(); } }, 400); }
From source file:sg.fxl.topekaport.QuizActivity.java
@TargetApi(Build.VERSION_CODES.LOLLIPOP) private void revealFragmentContainerLollipop(final View clickedView, final FrameLayout fragmentContainer) { prepareCircularReveal(clickedView, fragmentContainer); ViewCompat.animate(clickedView).scaleX(0).scaleY(0).alpha(0).setInterpolator(interpolator) .setListener(new ViewPropertyAnimatorListenerAdapter() { @Override/*w w w . jav a 2 s .c o m*/ public void onAnimationEnd(View view) { fragmentContainer.setVisibility(View.VISIBLE); clickedView.setVisibility(View.GONE); } }).start(); fragmentContainer.setVisibility(View.VISIBLE); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(circularReveal).with(colorChange); animatorSet.start(); }
From source file:com.google.samples.apps.topeka.activity.QuizActivity.java
@TargetApi(Build.VERSION_CODES.LOLLIPOP) private void revealFragmentContainerLollipop(final View clickedView, final FrameLayout fragmentContainer) { prepareCircularReveal(clickedView, fragmentContainer); ViewCompat.animate(clickedView).scaleX(0).scaleY(0).alpha(0).setInterpolator(mInterpolator) .setListener(new ViewPropertyAnimatorListenerAdapter() { @Override/*from w w w. j av a 2 s.co m*/ public void onAnimationEnd(View view) { fragmentContainer.setVisibility(View.VISIBLE); clickedView.setVisibility(View.GONE); } }).start(); fragmentContainer.setVisibility(View.VISIBLE); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(mCircularReveal).with(mColorChange); animatorSet.start(); }
From source file:com.google.samples.apps.topeka.view.quiz.QuizActivity.java
@TargetApi(Build.VERSION_CODES.LOLLIPOP) private void revealFragmentContainerLollipop(final View clickedView, final FrameLayout fragmentContainer, int themeAccentColor) { prepareCircularReveal(clickedView, fragmentContainer, themeAccentColor); ViewCompat.animate(clickedView).scaleX(0).scaleY(0).alpha(0).setInterpolator(mInterpolator) .setListener(new ViewPropertyAnimatorListenerAdapter() { @Override/*from w w w .jav a 2 s.co m*/ public void onAnimationEnd(View view) { fragmentContainer.setVisibility(View.VISIBLE); clickedView.setVisibility(View.GONE); } }).start(); fragmentContainer.setVisibility(View.VISIBLE); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(mCircularReveal).with(mColorChange); animatorSet.start(); }
From source file:com.example.imac.animationsdemo.ZoomActivity.java
/** * "Zooms" in a thumbnail view by assigning the high resolution image to a hidden "zoomed-in" * image view and animating its bounds to fit the entire activity content area. More * specifically://ww w. jav a 2 s. c o m * <p/> * <ol> * <li>Assign the high-res image to the hidden "zoomed-in" (expanded) image view.</li> * <li>Calculate the starting and ending bounds for the expanded view.</li> * <li>Animate each of four positioning/sizing properties (X, Y, SCALE_X, SCALE_Y) * simultaneously, from the starting bounds to the ending bounds.</li> * <li>Zoom back out by running the reverse animation on click.</li> * </ol> * * @param thumbView The thumbnail view to zoom in. * @param imageResId The high-resolution version of the image represented by the thumbnail. */ private void zoomImageFromThumb(final View thumbView, int imageResId) { // If there's an animation in progress, cancel it immediately and proceed with this one. if (mCurrentAnimator != null) { mCurrentAnimator.cancel(); } // Load the high-resolution "zoomed-in" image. final ImageView expandedImageView = (ImageView) findViewById(R.id.expanded_image); expandedImageView.setImageResource(imageResId); // Calculate the starting and ending bounds for the zoomed-in image. This step // involves lots of math. Yay, math. final Rect startBounds = new Rect(); final Rect finalBounds = new Rect(); final Point globalOffset = new Point(); // The start bounds are the global visible rectangle of the thumbnail, and the // final bounds are the global visible rectangle of the container view. Also // set the container view's offset as the origin for the bounds, since that's // the origin for the positioning animation properties (X, Y). thumbView.getGlobalVisibleRect(startBounds); //? findViewById(R.id.container).getGlobalVisibleRect(finalBounds, globalOffset); startBounds.offset(-globalOffset.x, -globalOffset.y); finalBounds.offset(-globalOffset.x, -globalOffset.y); // Adjust the start bounds to be the same aspect ratio as the final bounds using the // "center crop" technique. This prevents undesirable stretching during the animation. // Also calculate the start scaling factor (the end scaling factor is always 1.0). float startScale; if ((float) finalBounds.width() / finalBounds.height() > (float) startBounds.width() / startBounds.height()) { // Extend start bounds horizontally startScale = (float) startBounds.height() / finalBounds.height(); float startWidth = startScale * finalBounds.width(); float deltaWidth = (startWidth - startBounds.width()) / 2; startBounds.left -= deltaWidth; startBounds.right += deltaWidth; } else { // Extend start bounds vertically startScale = (float) startBounds.width() / finalBounds.width(); float startHeight = startScale * finalBounds.height(); //?? float deltaHeight = (startHeight - startBounds.height()) / 2; //? ??? 2 ? startBounds.top -= deltaHeight; // startBounds.bottom += deltaHeight; // } // Hide the thumbnail and show the zoomed-in view. When the animation begins, // it will position the zoomed-in view in the place of the thumbnail. thumbView.setAlpha(0f); expandedImageView.setVisibility(View.VISIBLE); // Set the pivot point for SCALE_X and SCALE_Y transformations to the top-left corner of // the zoomed-in view (the default is the center of the view). expandedImageView.setPivotX(0f); expandedImageView.setPivotY(0f); // Construct and run the parallel animation of the four translation and scale properties // (X, Y, SCALE_X, and SCALE_Y). Log.e("==startBounds===", startBounds.left + " " + startBounds.top); AnimatorSet set = new AnimatorSet(); Log.e("=====", startBounds.left + " " + startBounds.top + " " + thumbView.getLeft() + " " + thumbView.getTop()); set.play(ObjectAnimator.ofFloat(expandedImageView, "X", startBounds.left, finalBounds.left)) .with(ObjectAnimator.ofFloat(expandedImageView, "Y", startBounds.top, finalBounds.top)) .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X, startScale, 1f)) .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y, startScale, 1f)); set.setDuration(mShortAnimationDuration); set.setInterpolator(new DecelerateInterpolator()); set.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mCurrentAnimator = null; } @Override public void onAnimationCancel(Animator animation) { mCurrentAnimator = null; } }); set.start(); mCurrentAnimator = set; // Upon clicking the zoomed-in image, it should zoom back down to the original bounds // and show the thumbnail instead of the expanded image. final float startScaleFinal = startScale; expandedImageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mCurrentAnimator != null) { mCurrentAnimator.cancel(); } // Animate the four positioning/sizing properties in parallel, back to their // original values. AnimatorSet set = new AnimatorSet(); set.play(ObjectAnimator.ofFloat(expandedImageView, View.X, startBounds.left)) .with(ObjectAnimator.ofFloat(expandedImageView, View.Y, startBounds.top)) .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X, startScaleFinal)) .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y, startScaleFinal)); set.setDuration(mShortAnimationDuration); set.setInterpolator(new DecelerateInterpolator()); set.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { thumbView.setAlpha(1f); // expandedImageView.setVisibility(View.GONE); mCurrentAnimator = null; } @Override public void onAnimationCancel(Animator animation) { thumbView.setAlpha(1f); // expandedImageView.setVisibility(View.GONE); mCurrentAnimator = null; } }); set.start(); mCurrentAnimator = set; } }); }
From source file:me.hammarstrom.imagerecognition.activities.MainActivity.java
private void convertResponseToString(BatchAnnotateImagesResponse response) { Log.d(TAG, ":: " + response.getResponses().toString()); List<FaceAnnotation> faces = response.getResponses().get(0).getFaceAnnotations(); List<EntityAnnotation> labels = response.getResponses().get(0).getLabelAnnotations(); // Label string to be populated with data for TextToSpeech String label = ""; if (labels != null && labels.size() > 0) { label = "The image may contain "; List<Animator> scoreViewAnimations = new ArrayList<>(); List<Animator> scoreAlphaAnimations = new ArrayList<>(); List<Animator> showScoreAnimations = new ArrayList<>(); for (EntityAnnotation l : labels) { if (l.getScore() < 0.6f) { continue; }//from w w w . jav a2 s .com // Add label description (ex. laptop, desk, person, etc.) label += l.getDescription() + ", "; /** * Create a new {@link ScoreView} and populate it with label description and score */ ScoreView scoreView = new ScoreView(MainActivity.this); int padding = (int) DeviceDimensionsHelper.convertDpToPixel(8, this); scoreView.setPadding(padding, padding, padding, padding); scoreView.setScore(l.getScore()); scoreView.setLabelPosition(ScoreView.LABEL_POSITION_RIGHT); scoreView.setLabelText(l.getDescription()); scoreView.setAlpha(0f); scoreView.setTranslationX((DeviceDimensionsHelper.getDisplayWidth(this) / 2) * -1); // Add ScoreView to result layout mScoreResultLayout.addView(scoreView); // Create animations to used to show the ScoreView in a nice way ObjectAnimator animator = ObjectAnimator.ofFloat(scoreView, "translationX", (DeviceDimensionsHelper.getDisplayWidth(this) / 2) * -1, 0f); animator.setInterpolator(new OvershootInterpolator()); scoreViewAnimations.add(animator); ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(scoreView, "alpha", 0f, 1f); scoreAlphaAnimations.add(alphaAnimator); // Get the animation to show the actual score from ScoreView object showScoreAnimations.addAll(scoreView.getShowScoreAnimationsList()); } // Set reset button visibility to visible mButtonReset.setVisibility(View.VISIBLE); // Setup and play the animations AnimatorSet translationSet = new AnimatorSet(); translationSet.playSequentially(scoreViewAnimations); translationSet.setDuration(300); AnimatorSet alphaSet = new AnimatorSet(); alphaSet.playSequentially(scoreAlphaAnimations); alphaSet.setDuration(300); AnimatorSet showScoreSet = new AnimatorSet(); showScoreSet.playTogether(showScoreAnimations); showLoading(false); AnimatorSet set = new AnimatorSet(); set.play(translationSet).with(alphaSet).before(showScoreSet); set.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mButtonReset.animate().alpha(1f).start(); } }); set.start(); } else { // Set reset button visibility to visible mButtonReset.setVisibility(View.VISIBLE); mButtonReset.setAlpha(1f); } // Handle detected faces String facesFound = ""; if (faces != null && faces.size() > 0) { FaceGraphicOverlay faceGraphicOverlay = new FaceGraphicOverlay(MainActivity.this); faceGraphicOverlay.addFaces(faces); faceGraphicOverlay.setTag("faceOverlay"); mCameraPreviewLayout.addView(faceGraphicOverlay); facesFound = FaceFoundHelper.getFacesFoundString(this, faces); } // Add the detected image data to TTS engine mTts.speak(label, TextToSpeech.QUEUE_FLUSH, null); mTts.speak(facesFound, TextToSpeech.QUEUE_ADD, null); }
From source file:de.dreier.mytargets.utils.transitions.FabTransform.java
@Override public Animator createAnimator(@NonNull final ViewGroup sceneRoot, final TransitionValues startValues, final TransitionValues endValues) { if (startValues == null || endValues == null) { return null; }/*from w w w . j av a 2s .com*/ final Rect startBounds = (Rect) startValues.values.get(PROP_BOUNDS); final Rect endBounds = (Rect) endValues.values.get(PROP_BOUNDS); final boolean fromFab = endBounds.width() > startBounds.width(); final View view = endValues.view; final Rect dialogBounds = fromFab ? endBounds : startBounds; final Rect fabBounds = fromFab ? startBounds : endBounds; final Interpolator fastOutSlowInInterpolator = new FastOutSlowInInterpolator(); final long duration = getDuration(); final long halfDuration = duration / 2; final long twoThirdsDuration = duration * 2 / 3; if (!fromFab) { // Force measure / layout the dialog back to it's original bounds view.measure(makeMeasureSpec(startBounds.width(), View.MeasureSpec.EXACTLY), makeMeasureSpec(startBounds.height(), View.MeasureSpec.EXACTLY)); view.layout(startBounds.left, startBounds.top, startBounds.right, startBounds.bottom); } final int translationX = startBounds.centerX() - endBounds.centerX(); final int translationY = startBounds.centerY() - endBounds.centerY(); if (fromFab) { view.setTranslationX(translationX); view.setTranslationY(translationY); } // Add a color overlay to fake appearance of the FAB final ColorDrawable fabColor = new ColorDrawable(color); fabColor.setBounds(0, 0, dialogBounds.width(), dialogBounds.height()); if (!fromFab) { fabColor.setAlpha(0); } view.getOverlay().add(fabColor); // Add an icon overlay again to fake the appearance of the FAB final Drawable fabIcon = ContextCompat.getDrawable(sceneRoot.getContext(), icon).mutate(); final int iconLeft = (dialogBounds.width() - fabIcon.getIntrinsicWidth()) / 2; final int iconTop = (dialogBounds.height() - fabIcon.getIntrinsicHeight()) / 2; fabIcon.setBounds(iconLeft, iconTop, iconLeft + fabIcon.getIntrinsicWidth(), iconTop + fabIcon.getIntrinsicHeight()); if (!fromFab) { fabIcon.setAlpha(0); } view.getOverlay().add(fabIcon); // Circular clip from/to the FAB size final Animator circularReveal; if (fromFab) { circularReveal = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2, view.getHeight() / 2, startBounds.width() / 2, (float) Math.hypot(endBounds.width() / 2, endBounds.height() / 2)); circularReveal.setInterpolator(new FastOutLinearInInterpolator()); } else { circularReveal = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2, view.getHeight() / 2, (float) Math.hypot(startBounds.width() / 2, startBounds.height() / 2), endBounds.width() / 2); circularReveal.setInterpolator(new LinearOutSlowInInterpolator()); // Persist the end clip i.e. stay at FAB size after the reveal has run circularReveal.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { view.setOutlineProvider(new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { final int left = (view.getWidth() - fabBounds.width()) / 2; final int top = (view.getHeight() - fabBounds.height()) / 2; outline.setOval(left, top, left + fabBounds.width(), top + fabBounds.height()); view.setClipToOutline(true); } }); } }); } circularReveal.setDuration(duration); // Translate to end position along an arc final Animator translate = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y, fromFab ? getPathMotion().getPath(translationX, translationY, 0, 0) : getPathMotion().getPath(0, 0, -translationX, -translationY)); translate.setDuration(duration); translate.setInterpolator(fastOutSlowInInterpolator); // Fade contents of non-FAB view in/out List<Animator> fadeContents = null; if (view instanceof ViewGroup) { final ViewGroup vg = ((ViewGroup) view); fadeContents = new ArrayList<>(vg.getChildCount()); for (int i = vg.getChildCount() - 1; i >= 0; i--) { final View child = vg.getChildAt(i); final Animator fade = ObjectAnimator.ofFloat(child, View.ALPHA, fromFab ? 1f : 0f); if (fromFab) { child.setAlpha(0f); } fade.setDuration(twoThirdsDuration); fade.setInterpolator(fastOutSlowInInterpolator); fadeContents.add(fade); } } // Fade in/out the fab color & icon overlays final Animator colorFade = ObjectAnimator.ofInt(fabColor, "alpha", fromFab ? 0 : 255); final Animator iconFade = ObjectAnimator.ofInt(fabIcon, "alpha", fromFab ? 0 : 255); if (!fromFab) { colorFade.setStartDelay(halfDuration); iconFade.setStartDelay(halfDuration); } colorFade.setDuration(halfDuration); iconFade.setDuration(halfDuration); colorFade.setInterpolator(fastOutSlowInInterpolator); iconFade.setInterpolator(fastOutSlowInInterpolator); // Work around issue with elevation shadows. At the end of the return transition the shared // element's shadow is drawn twice (by each activity) which is jarring. This workaround // still causes the shadow to snap, but it's better than seeing it double drawn. Animator elevation = null; if (!fromFab) { elevation = ObjectAnimator.ofFloat(view, View.TRANSLATION_Z, -view.getElevation()); elevation.setDuration(duration); elevation.setInterpolator(fastOutSlowInInterpolator); } // Run all animations together final AnimatorSet transition = new AnimatorSet(); transition.playTogether(circularReveal, translate, colorFade, iconFade); transition.playTogether(fadeContents); if (elevation != null) { transition.play(elevation); } if (fromFab) { transition.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { // Clean up view.getOverlay().clear(); } }); } return new NoPauseAnimator(transition); }
From source file:com.amitupadhyay.aboutexample.ui.transitions.FabTransform.java
@Override public Animator createAnimator(final ViewGroup sceneRoot, final TransitionValues startValues, final TransitionValues endValues) { if (startValues == null || endValues == null) return null; final Rect startBounds = (Rect) startValues.values.get(PROP_BOUNDS); final Rect endBounds = (Rect) endValues.values.get(PROP_BOUNDS); final boolean fromFab = endBounds.width() > startBounds.width(); final View view = endValues.view; final Rect dialogBounds = fromFab ? endBounds : startBounds; final Rect fabBounds = fromFab ? startBounds : endBounds; final Interpolator fastOutSlowInInterpolator = AnimUtils .getFastOutSlowInInterpolator(sceneRoot.getContext()); final long duration = getDuration(); final long halfDuration = duration / 2; final long twoThirdsDuration = duration * 2 / 3; if (!fromFab) { // Force measure / layout the dialog back to it's original bounds view.measure(makeMeasureSpec(startBounds.width(), View.MeasureSpec.EXACTLY), makeMeasureSpec(startBounds.height(), View.MeasureSpec.EXACTLY)); view.layout(startBounds.left, startBounds.top, startBounds.right, startBounds.bottom); }/*ww w. j ava 2 s. com*/ final int translationX = startBounds.centerX() - endBounds.centerX(); final int translationY = startBounds.centerY() - endBounds.centerY(); if (fromFab) { view.setTranslationX(translationX); view.setTranslationY(translationY); } // Add a color overlay to fake appearance of the FAB final ColorDrawable fabColor = new ColorDrawable(color); fabColor.setBounds(0, 0, dialogBounds.width(), dialogBounds.height()); if (!fromFab) fabColor.setAlpha(0); view.getOverlay().add(fabColor); // Add an icon overlay again to fake the appearance of the FAB final Drawable fabIcon = ContextCompat.getDrawable(sceneRoot.getContext(), icon).mutate(); final int iconLeft = (dialogBounds.width() - fabIcon.getIntrinsicWidth()) / 2; final int iconTop = (dialogBounds.height() - fabIcon.getIntrinsicHeight()) / 2; fabIcon.setBounds(iconLeft, iconTop, iconLeft + fabIcon.getIntrinsicWidth(), iconTop + fabIcon.getIntrinsicHeight()); if (!fromFab) fabIcon.setAlpha(0); view.getOverlay().add(fabIcon); // Circular clip from/to the FAB size final Animator circularReveal; if (fromFab) { circularReveal = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2, view.getHeight() / 2, startBounds.width() / 2, (float) Math.hypot(endBounds.width() / 2, endBounds.height() / 2)); circularReveal.setInterpolator(AnimUtils.getFastOutLinearInInterpolator(sceneRoot.getContext())); } else { circularReveal = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2, view.getHeight() / 2, (float) Math.hypot(startBounds.width() / 2, startBounds.height() / 2), endBounds.width() / 2); circularReveal.setInterpolator(AnimUtils.getLinearOutSlowInInterpolator(sceneRoot.getContext())); // Persist the end clip i.e. stay at FAB size after the reveal has run circularReveal.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { view.setOutlineProvider(new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { final int left = (view.getWidth() - fabBounds.width()) / 2; final int top = (view.getHeight() - fabBounds.height()) / 2; outline.setOval(left, top, left + fabBounds.width(), top + fabBounds.height()); view.setClipToOutline(true); } }); } }); } circularReveal.setDuration(duration); // Translate to end position along an arc final Animator translate = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, View.TRANSLATION_Y, fromFab ? getPathMotion().getPath(translationX, translationY, 0, 0) : getPathMotion().getPath(0, 0, -translationX, -translationY)); translate.setDuration(duration); translate.setInterpolator(fastOutSlowInInterpolator); // Fade contents of non-FAB view in/out List<Animator> fadeContents = null; if (view instanceof ViewGroup) { final ViewGroup vg = ((ViewGroup) view); fadeContents = new ArrayList<>(vg.getChildCount()); for (int i = vg.getChildCount() - 1; i >= 0; i--) { final View child = vg.getChildAt(i); final Animator fade = ObjectAnimator.ofFloat(child, View.ALPHA, fromFab ? 1f : 0f); if (fromFab) { child.setAlpha(0f); } fade.setDuration(twoThirdsDuration); fade.setInterpolator(fastOutSlowInInterpolator); fadeContents.add(fade); } } // Fade in/out the fab color & icon overlays final Animator colorFade = ObjectAnimator.ofInt(fabColor, "alpha", fromFab ? 0 : 255); final Animator iconFade = ObjectAnimator.ofInt(fabIcon, "alpha", fromFab ? 0 : 255); if (!fromFab) { colorFade.setStartDelay(halfDuration); iconFade.setStartDelay(halfDuration); } colorFade.setDuration(halfDuration); iconFade.setDuration(halfDuration); colorFade.setInterpolator(fastOutSlowInInterpolator); iconFade.setInterpolator(fastOutSlowInInterpolator); // Work around issue with elevation shadows. At the end of the return transition the shared // element's shadow is drawn twice (by each activity) which is jarring. This workaround // still causes the shadow to snap, but it's better than seeing it double drawn. Animator elevation = null; if (!fromFab) { elevation = ObjectAnimator.ofFloat(view, View.TRANSLATION_Z, -view.getElevation()); elevation.setDuration(duration); elevation.setInterpolator(fastOutSlowInInterpolator); } // Run all animations together final AnimatorSet transition = new AnimatorSet(); transition.playTogether(circularReveal, translate, colorFade, iconFade); transition.playTogether(fadeContents); if (elevation != null) transition.play(elevation); if (fromFab) { transition.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { // Clean up view.getOverlay().clear(); } }); } return new AnimUtils.NoPauseAnimator(transition); }