All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.robolectric.shadows.ShadowValueAnimator Maven / Gradle / Ivy

package org.robolectric.shadows;

import static android.os.Build.VERSION_CODES.N;
import static org.robolectric.util.reflector.Reflector.reflector;

import android.animation.AnimationHandler;
import android.animation.ValueAnimator;
import android.app.UiAutomation;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.annotation.Resetter;
import org.robolectric.util.ReflectionHelpers;
import org.robolectric.util.reflector.Accessor;
import org.robolectric.util.reflector.Direct;
import org.robolectric.util.reflector.ForType;
import org.robolectric.util.reflector.Static;

@Implements(ValueAnimator.class)
public class ShadowValueAnimator {

  @RealObject private ValueAnimator realObject;

  private int actualRepeatCount;

  @Resetter
  public static void reset() {
    /* ValueAnimator.sAnimationHandler is a static thread local that otherwise would survive between
     * tests. The AnimationHandler.mAnimationScheduled is set to true when the scheduleAnimation() is
     * called and the reset to false when run() is called by the Choreographer. If an animation is
     * already scheduled, it will not post to the Choreographer. This is a problem if a previous
     * test leaves animations on the Choreographers callback queue without running them as it will
     * cause the AnimationHandler not to post a callback. We reset the thread local here so a new
     * one will be created for each test with a fresh state.
     */
    if (RuntimeEnvironment.getApiLevel() >= N) {
      ThreadLocal animatorHandlerTL =
          ReflectionHelpers.getStaticField(AnimationHandler.class, "sAnimatorHandler");
      animatorHandlerTL.remove();
    } else {
      ReflectionHelpers.callStaticMethod(ValueAnimator.class, "clearAllAnimations");
      ThreadLocal animatorHandlerTL =
          ReflectionHelpers.getStaticField(ValueAnimator.class, "sAnimationHandler");
      animatorHandlerTL.remove();
    }

    setDurationScale(1);
  }

  @Implementation
  protected void setRepeatCount(int count) {
    actualRepeatCount = count;
    if (count == ValueAnimator.INFINITE) {
      count = 1;
    }
    reflector(ValueAnimatorReflector.class, realObject).setRepeatCount(count);
  }

  /**
   * Returns the value that was set as the repeat count. This is otherwise the same
   * as getRepeatCount(), except when the count was set to infinite.
   *
   * @return Repeat count.
   */
  public int getActualRepeatCount() {
    return actualRepeatCount;
  }

  /**
   * Sets the duration scale for value animator. To set this value use {@link
   * UiAutomation#setAnimationScale(float)} or {@link
   * ShadowUiAutomation#setAnimationScaleCompat(float)}.
   */
  @Implementation
  protected static void setDurationScale(float duration) {
    reflector(ValueAnimatorReflector.class, null).setDurationScale(duration);
  }

  @ForType(ValueAnimator.class)
  interface ValueAnimatorReflector {

    @Direct
    void setRepeatCount(int count);

    @Static
    @Accessor("sDurationScale")
    void setDurationScale(float duration);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy