Skip to content

Commit

Permalink
Let animation factories be used for multiple loads
Browse files Browse the repository at this point in the history
  • Loading branch information
sjudd committed Oct 12, 2014
1 parent 7080b40 commit cd2c3ba
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.ImageView;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -17,6 +14,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand All @@ -34,7 +32,7 @@ public void setup() {
public void testStartsDefaultAnimationIfNoPreviousDrawableIsNotSet() {
when(harness.adapter.getView()).thenReturn(harness.view);
harness.animation.animate(harness.current, harness.adapter);
verify(harness.view).startAnimation(any(Animation.class));
verify(harness.defaultAnimation).animate(eq(harness.current), eq(harness.adapter));
}

@Test
Expand Down Expand Up @@ -69,7 +67,7 @@ private static class CrossFadeHarness {
Drawable current = new ColorDrawable(Color.GRAY);
ViewAdapter adapter = mock(ViewAdapter.class);
ImageView view = mock(ImageView.class);
Animation defaultAnimation = new AlphaAnimation(0f, 1f);
GlideAnimation<Drawable> defaultAnimation = mock(GlideAnimation.class);
int duration = 200;
DrawableCrossFadeViewAnimation<Drawable> animation = new DrawableCrossFadeViewAnimation<Drawable>(
defaultAnimation, duration);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package com.bumptech.glide.request.animation;

import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.ImageView;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand All @@ -17,19 +16,19 @@

@RunWith(RobolectricTestRunner.class)
public class ViewAnimationTest {
private AlphaAnimation animation;
private ViewAnimation viewAnimation;
private ViewAnimation<Object> viewAnimation;
private ViewAdapter adapter;
private ImageView view;
private ViewAnimation.AnimationFactory animationFactory;

@SuppressWarnings("unchecked")
@Before
public void setUp() {
animation = new AlphaAnimation(0f, 1f);
animationFactory = mock(ViewAnimation.AnimationFactory.class);
view = mock(ImageView.class);
adapter = mock(ViewAdapter.class);
when(adapter.getView()).thenReturn(view);
viewAnimation = new ViewAnimation(animation);
viewAnimation = new ViewAnimation<Object>(animationFactory);
}

@Test
Expand All @@ -46,7 +45,10 @@ public void testAlwaysReturnsFalse() {

@Test
public void testStartsAnimationOnAnimate() {
Animation animation = mock(Animation.class);
when(animationFactory.build()).thenReturn(animation);
viewAnimation.animate(null, adapter);
verify(view).clearAnimation();
verify(view).startAnimation(eq(animation));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ public BitmapRequestBuilder<ModelType, TranscodeType> animate(int animationId) {
/**
* {@inheritDoc}
*/
@Deprecated
@SuppressWarnings("deprecation")
@Override
public BitmapRequestBuilder<ModelType, TranscodeType> animate(Animation animation) {
super.animate(animation);
Expand Down
8 changes: 4 additions & 4 deletions library/src/main/java/com/bumptech/glide/DrawableOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ interface DrawableOptions {
*
* @see #crossFade(int)
* @see #crossFade(int, int)
* @see #crossFade(android.view.animation.Animation, int)
*
* @return This request builder.
*/
Expand All @@ -22,7 +21,6 @@ interface DrawableOptions {
*
* @see #crossFade()
* @see #crossFade(int, int)
* @see #crossFade(android.view.animation.Animation, int)
*
* @param duration The duration of the cross fade and initial fade in.
* @return This request builder.
Expand All @@ -39,21 +37,23 @@ interface DrawableOptions {
* @see #crossFade(int)
* @see #crossFade(int, int)
*
* @deprecated If this builder is used for multiple loads, using this method will result in multiple view's being
* asked to start an animation using a single {@link android.view.animation.Animation} object which results in
* views animating repeatedly. Use {@link #crossFade(int, int)}} instead.
* @param animation The Animation to use if no placeholder is set.
* @param duration The duration of the cross fade animation.
* @return This request builder.
*/
@Deprecated

This comment has been minimized.

Copy link
@TWiStErRob

TWiStErRob Oct 13, 2014

Shouldn't there be a replacement animate(AnimationFactory) for custom (code-only) animations?

This comment has been minimized.

Copy link
@sjudd

sjudd Oct 13, 2014

Author Owner

I'll clarify the deprecation warning. You can continue to use this method, you just have to call .crossFade() once per load() call. I agree I should have some other factory based replacement, I filed bumptech#188 to track adding such an API.

GenericRequestBuilder<?, ?, ?, ?> crossFade(Animation animation, int duration);


/**
* Applies a cross fade transformation that des from the placeholder to the loaded
* {@link android.graphics.drawable.Drawable}. If no placeholder is set, the Drawable will instead be animated in
* using the {@link android.view.animation.Animation} loaded from the given animation id.
*
* @see #crossFade()
* @see #crossFade(int)
* @see #crossFade(android.view.animation.Animation, int)
*
* @param animationId The id of the Animation to use if no placeholder is set.
* @param duration The duration of the cross fade animation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ public DrawableRequestBuilder<ModelType> crossFade(int duration) {
/**
* {@inheritDoc}
*/
@Deprecated
public DrawableRequestBuilder<ModelType> crossFade(Animation animation, int duration) {
super.animate(new DrawableCrossFadeViewAnimation.DrawableCrossFadeFactory<GlideDrawable>(animation, duration));
return this;
Expand Down Expand Up @@ -301,6 +302,8 @@ public DrawableRequestBuilder<ModelType> animate(int animationId) {
/**
* {@inheritDoc}
*/
@Deprecated
@SuppressWarnings("deprecation")
@Override
public DrawableRequestBuilder<ModelType> animate(Animation animation) {
super.animate(animation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,22 +366,26 @@ public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> d
* @param animationId The resource id of the animation to run
* @return This request builder.
*/
// This is safe because the view animation doesn't care about the resource type it receives.
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> animate(
int animationId) {
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> animate(int animationId) {
return animate(new ViewAnimation.ViewAnimationFactory<TranscodeType>(context, animationId));
}

/**
* Sets an animation to run on the wrapped target when a resource load finishes. Will only be run if the resource
* was loaded asynchronously (ie was not in the memory cache)
*
* @see #animate(int)
* @see #animate(com.bumptech.glide.request.animation.ViewPropertyAnimation.Animator)
*
* @deprecated If this builder is used for multiple loads, using this method will result in multiple view's being
* asked to start an animation using a single {@link android.view.animation.Animation} object which results in
* views animating repeatedly. Use {@link #animate(int)} or
* {@link #animate(com.bumptech.glide.request.animation.ViewPropertyAnimation.Animator)}.
* @param animation The animation to run
* @return This request builder.
*/
// This is safe because the view animation doesn't care about the resource type it receives.
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> animate(
Animation animation) {
@Deprecated
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> animate(Animation animation) {
return animate(new ViewAnimation.ViewAnimationFactory<TranscodeType>(animation));
}

Expand All @@ -393,7 +397,6 @@ public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> a
* @param animator The {@link com.bumptech.glide.request.animation.ViewPropertyAnimation.Animator} to run.
* @return This request builder.
*/
// This is safe because the view property animation doesn't care about the resource type it receives.
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> animate(
ViewPropertyAnimation.Animator animator) {
return animate(new ViewPropertyAnimation.ViewPropertyAnimationFactory<TranscodeType>(animator));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ public GifRequestBuilder<ModelType> crossFade(int duration) {
/**
* {@inheritDoc}
*/
@Deprecated
@Override
public GifRequestBuilder<ModelType> crossFade(Animation animation, int duration) {
super.animate(new DrawableCrossFadeViewAnimation.DrawableCrossFadeFactory<GifDrawable>(animation, duration));
Expand Down Expand Up @@ -282,6 +283,8 @@ public GifRequestBuilder<ModelType> animate(int animationId) {
/**
* {@inheritDoc}
*/
@Deprecated
@SuppressWarnings("deprecation")
@Override
public GifRequestBuilder<ModelType> animate(Animation animation) {
super.animate(animation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;

/**
* A cross fade {@link GlideAnimation} for {@link android.graphics.drawable.Drawable}s
Expand All @@ -19,15 +17,9 @@
public class DrawableCrossFadeViewAnimation<T extends Drawable> implements GlideAnimation<T> {
// 150 ms.
public static final int DEFAULT_DURATION = 300;
private final Animation defaultAnimation;
private final GlideAnimation<T> defaultAnimation;
private final int duration;

private static Animation getDefaultAnimation() {
AlphaAnimation animation = new AlphaAnimation(0f, 1f);
animation.setDuration(DEFAULT_DURATION / 2);
return animation;
}

/**
* A factory class that produces a new {@link GlideAnimation} that varies depending
* on whether or not the drawable was loaded from the memory cache and whether or not the drawable is the first
Expand All @@ -41,28 +33,28 @@ private static Animation getDefaultAnimation() {
* </p>
*/
public static class DrawableCrossFadeFactory<T extends Drawable> implements GlideAnimationFactory<T> {
private Context context;
private int defaultAnimationId;
private Animation defaultAnimation;
private int duration;
private final ViewAnimation.ViewAnimationFactory<T> animationFactory;
private final int duration;
private DrawableCrossFadeViewAnimation<T> animation;

public DrawableCrossFadeFactory() {
this(getDefaultAnimation(), DEFAULT_DURATION);
this(DEFAULT_DURATION);
}

public DrawableCrossFadeFactory(int duration) {
this(getDefaultAnimation(), duration);
this(new ViewAnimation.ViewAnimationFactory<T>(new DefaultAnimationFactory()), duration);
}

public DrawableCrossFadeFactory(Context context, int defaultAnimationId, int duration) {
this.context = context;
this.defaultAnimationId = defaultAnimationId;
this.duration = duration;
this(new ViewAnimation.ViewAnimationFactory<T>(context, defaultAnimationId), duration);
}

public DrawableCrossFadeFactory(Animation defaultAnimation, int duration) {
this.defaultAnimation = defaultAnimation;
this(new ViewAnimation.ViewAnimationFactory<T>(defaultAnimation), duration);
}

DrawableCrossFadeFactory(ViewAnimation.ViewAnimationFactory<T> animationFactory, int duration) {
this.animationFactory = animationFactory;
this.duration = duration;
}

Expand All @@ -73,9 +65,7 @@ public GlideAnimation<T> build(boolean isFromMemoryCache, boolean isFirstResourc
}

if (animation == null) {
if (defaultAnimation == null) {
defaultAnimation = AnimationUtils.loadAnimation(context, defaultAnimationId);
}
GlideAnimation<T> defaultAnimation = animationFactory.build(false, isFirstResource);
animation = new DrawableCrossFadeViewAnimation<T>(defaultAnimation, duration);
}

Expand All @@ -86,12 +76,10 @@ public GlideAnimation<T> build(boolean isFromMemoryCache, boolean isFirstResourc
/**
* Constructor that takes a default animation and a duration in milliseconds that the cross fade animation should
* last.
* @param defaultAnimation The default animation that will run if there is nothing to cross fade from when a new
* {@link android.graphics.drawable.Drawable} is set.
* @param duration The duration that the cross fade animation should run if there is something to cross fade from
* when a new {@link android.graphics.drawable.Drawable} is set.
*/
public DrawableCrossFadeViewAnimation(Animation defaultAnimation, int duration) {
public DrawableCrossFadeViewAnimation(GlideAnimation<T> defaultAnimation, int duration) {
this.defaultAnimation = defaultAnimation;
this.duration = duration;
}
Expand Down Expand Up @@ -119,11 +107,18 @@ public boolean animate(T current, ViewAdapter adapter) {
adapter.setDrawable(transitionDrawable);
return true;
} else {
View view = adapter.getView();
if (view != null) {
view.startAnimation(defaultAnimation);
}
defaultAnimation.animate(current, adapter);
return false;
}
}

private static class DefaultAnimationFactory implements ViewAnimation.AnimationFactory {

@Override
public Animation build() {
AlphaAnimation animation = new AlphaAnimation(0f, 1f);
animation.setDuration(DEFAULT_DURATION / 2);
return animation;
}
}
}
Loading

0 comments on commit cd2c3ba

Please sign in to comment.