/* * Copyright (C) 2014 Jerzy Chalupski * Copyright (C) 2016 Thomas Robert Altstidl * * 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.tr4android.support.extension.drawable; import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.view.animation.AnticipateInterpolator; import android.view.animation.Interpolator; import android.view.animation.OvershootInterpolator; import com.tr4android.support.extension.animation.AnimationUtils; import com.tr4android.support.extension.animation.ValueAnimatorCompat; /** * A drawable that animates the rotation and alpha value of the wrapped drawable */ public class RotationTransitionDrawable extends LayerDrawable { private float mRotation; private float mMaxRotation; private boolean mHasSecondDrawable; // Animator private ValueAnimatorCompat mAnimator; private Interpolator mStartInterpolator = new OvershootInterpolator(); private Interpolator mReverseInterpolator = new AnticipateInterpolator(); public RotationTransitionDrawable(Drawable drawable) { this(drawable, null); } public RotationTransitionDrawable(Drawable drawable, Drawable closeDrawable) { super(closeDrawable == null ? new Drawable[]{drawable} : new Drawable[]{drawable, closeDrawable}); mHasSecondDrawable = closeDrawable != null; // The animator used to animate the transition mAnimator = AnimationUtils.createAnimator(); mAnimator.setUpdateListener(new ValueAnimatorCompat.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimatorCompat animator) { setRotation(animator.getAnimatedFloatValue()); } }); } @Override public void draw(Canvas canvas) { canvas.save(); if (mHasSecondDrawable) { int alpha = Math.min(Math.max(0, Math.round(mRotation / mMaxRotation * 255)), 255); canvas.rotate(mRotation, getBounds().centerX(), getBounds().centerY()); getDrawable(0).setAlpha(255 - alpha); getDrawable(0).draw(canvas); canvas.rotate(-mMaxRotation, getBounds().centerX(), getBounds().centerY()); getDrawable(1).setAlpha(alpha); getDrawable(1).draw(canvas); } else { canvas.rotate(mRotation, getBounds().centerX(), getBounds().centerY()); super.draw(canvas); } canvas.restore(); } public Interpolator getStartInterpolator() { return mStartInterpolator; } public void setStartInterpolator(Interpolator interpolator) { mStartInterpolator = interpolator; } public Interpolator getReverseInterpolator() { return mReverseInterpolator; } public void setReverseInterpolator(Interpolator interpolator) { mReverseInterpolator = interpolator; } public float getRotation() { return mRotation; } public void setRotation(float rotation) { mRotation = rotation; invalidateSelf(); } public float getMaxRotation() { return mMaxRotation; } public void setMaxRotation(float rotation) { mMaxRotation = rotation; } public void startTransition(int duration) { mAnimator.cancel(); mAnimator.setFloatValues(mRotation, mMaxRotation); mAnimator.setDuration(duration); mAnimator.setInterpolator(mStartInterpolator); mAnimator.start(); } public void reverseTransition(int duration) { mAnimator.cancel(); mAnimator.setFloatValues(mRotation, 0f); mAnimator.setDuration(duration); mAnimator.setInterpolator(mReverseInterpolator); mAnimator.start(); } }