/* * Copyright (C) 2014 Andrey Kulikov (andkulikov@gmail.com) * * 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.transitionseverywhere.utils; import android.animation.Animator; import android.animation.Animator.AnimatorPauseListener; import android.animation.ObjectAnimator; import android.annotation.TargetApi; import android.graphics.Path; import android.os.Build.VERSION_CODES; import android.util.Property; import android.view.View; import com.transitionseverywhere.PathMotion; public class AnimatorUtils { static class BaseAnimatorCompat { public void addPauseListener(Animator animator, AnimatorPauseListener listener) { } public void pause(Animator animator) { } public void resume(Animator animator) { } public <T> Animator ofPointF(T target, PointFProperty<T> property, float startLeft, float startTop, float endLeft, float endTop) { return null; } public <T> Animator ofPointF(T target, PointFProperty<T> property, Path path) { return null; } public boolean isAnimatorStarted(Animator anim) { return false; } public boolean hasOverlappingRendering(View view) { return true; } public ObjectAnimator ofFloat(View view, Property<View, Float> property, float startFraction, float endFraction) { return null; } public ObjectAnimator ofInt(View view, Property<View, Integer> property, float startFraction, float endFraction) { return null; } } @TargetApi(VERSION_CODES.ICE_CREAM_SANDWICH) static class IceCreamSandwichAnimatorCompat extends BaseAnimatorCompat { @Override public void pause(Animator animator) { animator.cancel(); } @Override public <T> Animator ofPointF(T target, PointFProperty<T> property, float startLeft, float startTop, float endLeft, float endTop) { return PointFAnimator.ofPointF(target, property, startLeft, startTop, endLeft, endTop); } @Override public <T> Animator ofPointF(final T target, final PointFProperty<T> property, final Path path) { return PathAnimatorCompat.ofPointF(target, property, path); } @Override public boolean isAnimatorStarted(Animator anim) { return anim.isStarted(); } @Override public ObjectAnimator ofFloat(View view, Property<View, Float> property, float startFraction, float endFraction) { float start = property.get(view) * startFraction; float end = property.get(view) * endFraction; if (start == end) { return null; } property.set(view, start); return ObjectAnimator.ofFloat(view, property, end); } @Override public ObjectAnimator ofInt(View view, Property<View, Integer> property, float startFraction, float endFraction) { int start = (int) (property.get(view) * startFraction); int end = (int) (property.get(view) * endFraction); if (start == end) { return null; } property.set(view, start); return ObjectAnimator.ofInt(view, property, end); } } @TargetApi(VERSION_CODES.JELLY_BEAN) static class JellyBeanCompat extends IceCreamSandwichAnimatorCompat { @Override public boolean hasOverlappingRendering(View view) { return view.hasOverlappingRendering(); } } @TargetApi(VERSION_CODES.KITKAT) static class KitKatAnimatorCompat extends JellyBeanCompat { @Override public void addPauseListener(Animator animator, final AnimatorPauseListener listener) { animator.addPauseListener(listener); } @Override public void pause(Animator animator) { animator.pause(); } @Override public void resume(Animator animator) { animator.resume(); } } @TargetApi(VERSION_CODES.LOLLIPOP) static class LollipopAnimatorCompat extends KitKatAnimatorCompat { @Override public <T> Animator ofPointF(T target, PointFProperty<T> property, Path path) { return ObjectAnimator.ofObject(target, property, null, path); } } private static final BaseAnimatorCompat IMPL; static { final int version = android.os.Build.VERSION.SDK_INT; if (version >= VERSION_CODES.LOLLIPOP) { IMPL = new LollipopAnimatorCompat(); } else if (version >= VERSION_CODES.KITKAT) { IMPL = new KitKatAnimatorCompat(); } else if (version >= VERSION_CODES.JELLY_BEAN) { IMPL = new JellyBeanCompat(); } else if (version >= VERSION_CODES.ICE_CREAM_SANDWICH) { IMPL = new IceCreamSandwichAnimatorCompat(); } else { IMPL = new BaseAnimatorCompat(); } } public static void addPauseListener(Animator animator, AnimatorPauseListener listener) { IMPL.addPauseListener(animator, listener); } public static void pause(Animator animator) { IMPL.pause(animator); } public static void resume(Animator animator) { IMPL.resume(animator); } public static <T> Animator ofPointF(T target, PointFProperty<T> property, float startLeft, float startTop, float endLeft, float endTop) { return IMPL.ofPointF(target, property, startLeft, startTop, endLeft, endTop); } public static <T> Animator ofPointF(T target, PointFProperty<T> property, Path path) { if (path != null) { return IMPL.ofPointF(target, property, path); } else { return null; } } public static <T> Animator ofPointF(T target, PointFProperty<T> property, PathMotion pathMotion, float startLeft, float startTop, float endLeft, float endTop) { if (startLeft != endLeft || startTop != endTop) { if (pathMotion == null || pathMotion.equals(PathMotion.STRAIGHT_PATH_MOTION)) { return ofPointF(target, property, startLeft, startTop, endLeft, endTop); } else { return ofPointF(target, property, pathMotion.getPath(startLeft, startTop, endLeft, endTop)); } } else { return null; } } public static boolean isAnimatorStarted(Animator anim) { return IMPL.isAnimatorStarted(anim); } public static boolean hasOverlappingRendering(View view) { return IMPL.hasOverlappingRendering(view); } public static ObjectAnimator ofFloat(View view, Property<View, Float> property, float startFraction, float endFraction) { return IMPL.ofFloat(view, property, startFraction, endFraction); } public static ObjectAnimator ofInt(View view, Property<View, Integer> property, float startFraction, float endFraction) { return IMPL.ofInt(view, property, startFraction, endFraction); } }