CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-github-bumptech-glide--glide

A fast and efficient open source media management and image loading framework for Android that wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface.

Pending
Overview
Eval results
Files

transitions-animations.mddocs/

Glide Transitions and Animations System

Glide's transition and animation system provides smooth visual effects during image loading through a flexible architecture built around the TransitionOptions base class and specialized implementations like DrawableTransitionOptions. The system supports built-in cross-fade effects, custom transitions, and comprehensive animation timing controls for enhanced user experience.

TransitionOptions Base Class

The foundation for all transition configurations in Glide:

public abstract class TransitionOptions<CHILD extends TransitionOptions<CHILD, TranscodeType>, TranscodeType> {
    
    /**
     * Disables all transitions for this request
     * @return Updated options instance
     */
    public abstract CHILD dontTransition();
    
    /**
     * Creates a clone of these options
     * @return Cloned options instance
     */
    public abstract CHILD clone();
    
    /**
     * Creates empty transition options with no effects
     */
    public static <T> TransitionOptions<?, T> of() {
        // Implementation provided by Glide
        return null;
    }
}

DrawableTransitionOptions Class

Specialized transition options for Drawable resources with built-in cross-fade support:

public class DrawableTransitionOptions extends TransitionOptions<DrawableTransitionOptions, Drawable> {
    
    /**
     * Creates cross-fade transition with default duration (300ms)
     * @return DrawableTransitionOptions with cross-fade
     */
    public static DrawableTransitionOptions withCrossFade() {
        // Implementation provided by Glide
        return null;
    }
    
    /**
     * Creates cross-fade transition with custom duration
     * @param duration Fade duration in milliseconds
     * @return DrawableTransitionOptions with timed cross-fade
     */
    public static DrawableTransitionOptions withCrossFade(int duration) {
        // Implementation provided by Glide
        return null;
    }
    
    /**
     * Creates cross-fade with custom duration and animation builder
     * @param duration Fade duration in milliseconds  
     * @param animationId Android animation resource ID
     * @return DrawableTransitionOptions with custom animation
     */
    public static DrawableTransitionOptions withCrossFade(int duration, int animationId) {
        // Implementation provided by Glide
        return null;
    }
    
    /**
     * Creates transition with custom transition factory
     * @param transitionFactory Factory for creating transitions
     * @return DrawableTransitionOptions with custom factory
     */
    public static DrawableTransitionOptions with(TransitionFactory<? super Drawable> transitionFactory) {
        // Implementation provided by Glide
        return null;
    }
    
    /**
     * Creates transition with no animation effects
     * @return DrawableTransitionOptions with transitions disabled
     */
    public static DrawableTransitionOptions withNoTransition() {
        // Implementation provided by Glide
        return null;
    }
    
    @Override
    public DrawableTransitionOptions clone() {
        // Implementation provided by Glide
        return null;
    }
}

BitmapTransitionOptions Class

Transition options specifically for Bitmap resources:

public class BitmapTransitionOptions extends TransitionOptions<BitmapTransitionOptions, Bitmap> {
    
    /**
     * Creates cross-fade transition for bitmaps (default 300ms)
     * @return BitmapTransitionOptions with cross-fade
     */
    public static BitmapTransitionOptions withCrossFade() {
        // Implementation provided by Glide
        return null;
    }
    
    /**
     * Creates cross-fade transition with custom duration
     * @param duration Fade duration in milliseconds
     * @return BitmapTransitionOptions with timed cross-fade  
     */
    public static BitmapTransitionOptions withCrossFade(int duration) {
        // Implementation provided by Glide
        return null;
    }
    
    /**
     * Creates custom bitmap transition
     * @param transitionFactory Factory for bitmap transitions
     * @return BitmapTransitionOptions with custom factory
     */
    public static BitmapTransitionOptions with(TransitionFactory<? super Bitmap> transitionFactory) {
        // Implementation provided by Glide
        return null;
    }
    
    /**
     * Creates no-transition options for bitmaps
     * @return BitmapTransitionOptions with no effects
     */
    public static BitmapTransitionOptions withNoTransition() {
        // Implementation provided by Glide
        return null;
    }
    
    @Override
    public BitmapTransitionOptions clone() {
        // Implementation provided by Glide
        return null;
    }
}

Transition Interface

Core interface for implementing custom transitions:

public interface Transition<R> {
    /**
     * Executes the transition animation
     * @param current Current resource (may be placeholder)
     * @param adapter Adapter for applying the transition
     * @return True if transition was applied, false otherwise
     */
    boolean transition(R current, ViewAdapter adapter);
    
    /**
     * Adapter interface for applying transitions to views
     */
    interface ViewAdapter {
        /**
         * Gets the current drawable from the view
         * @return Current drawable or null
         */
        Drawable getCurrentDrawable();
        
        /**
         * Sets the drawable on the view
         * @param drawable Drawable to set
         */
        void setDrawable(Drawable drawable);
        
        /**
         * Gets the underlying view
         * @return View being transitioned
         */
        View getView();
    }
}

ViewTransition Interface

Specialized transition interface for view-based animations:

public interface ViewTransition {
    /**
     * Executes transition on a specific view
     * @param view Target view for the transition
     * @param adapter Adapter for view operations
     * @return True if transition was handled
     */
    boolean transition(View view, Transition.ViewAdapter adapter);
    
    /**
     * Creates a view transition from an animation resource
     * @param animationId Android animation resource ID
     * @return ViewTransition using the animation
     */
    static ViewTransition withAnimation(int animationId) {
        // Implementation provided by Glide
        return null;
    }
    
    /**
     * Creates a view transition with no animation
     * @return ViewTransition that immediately sets the drawable
     */
    static ViewTransition withNoTransition() {
        // Implementation provided by Glide
        return null;
    }
}

TransitionFactory Interface

Factory interface for creating transition instances:

public interface TransitionFactory<R> {
    /**
     * Creates a transition for the given data source
     * @param dataSource Source of the image data
     * @param isFirstResource Whether this is the first resource loaded
     * @return Transition instance or null for no transition
     */
    Transition<R> build(DataSource dataSource, boolean isFirstResource);
}

Basic Transition Usage

Simple Cross-Fade Transitions

Apply basic cross-fade effects to image loading:

public class BasicTransitionsActivity extends AppCompatActivity {
    
    public void basicCrossFade() {
        // Default cross-fade (300ms)
        Glide.with(this)
            .load(imageUrl)
            .transition(DrawableTransitionOptions.withCrossFade())
            .into(imageView);
        
        // Custom duration cross-fade
        Glide.with(this)
            .load(imageUrl)
            .transition(DrawableTransitionOptions.withCrossFade(500))
            .into(imageView);
        
        // Bitmap-specific cross-fade
        Glide.with(this)
            .asBitmap()
            .load(imageUrl)
            .transition(BitmapTransitionOptions.withCrossFade(400))
            .into(imageView);
    }
    
    public void noTransition() {
        // Disable transitions completely
        Glide.with(this)
            .load(imageUrl)
            .transition(DrawableTransitionOptions.withNoTransition())
            .into(imageView);
        
        // Alternative syntax
        Glide.with(this)
            .load(imageUrl)
            .dontAnimate()
            .into(imageView);
    }
}

Android Animation Resources

Use Android animation XML resources for transitions:

public class AnimationResourceActivity extends AppCompatActivity {
    
    public void useAnimationResources() {
        // Create animation XML file: res/anim/fade_in.xml
        /*
        <?xml version="1.0" encoding="utf-8"?>
        <alpha xmlns:android="http://schemas.android.com/apk/res/android"
            android:fromAlpha="0.0"
            android:toAlpha="1.0"
            android:duration="600" />
        */
        
        // Apply animation resource
        Glide.with(this)
            .load(imageUrl)
            .transition(DrawableTransitionOptions.withCrossFade(600, R.anim.fade_in))
            .into(imageView);
        
        // Scale animation: res/anim/scale_up.xml
        /*
        <?xml version="1.0" encoding="utf-8"?>
        <scale xmlns:android="http://schemas.android.com/apk/res/android"
            android:fromXScale="0.8"
            android:fromYScale="0.8"
            android:toXScale="1.0"
            android:toYScale="1.0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:duration="400"
            android:interpolator="@android:anim/decelerate_interpolator" />
        */
        
        ViewTransition scaleTransition = ViewTransition.withAnimation(R.anim.scale_up);
        Glide.with(this)
            .load(imageUrl)
            .transition(DrawableTransitionOptions.with(
                new TransitionFactory<Drawable>() {
                    @Override
                    public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) {
                        return scaleTransition;
                    }
                }
            ))
            .into(imageView);
    }
}

Custom Transitions

Simple Custom Transition

Create custom transition effects by implementing the Transition interface:

public class FadeInTransition implements Transition<Drawable> {
    
    @Override
    public boolean transition(Drawable current, Transition.ViewAdapter adapter) {
        View view = adapter.getView();
        
        // Set initial alpha and drawable
        view.setAlpha(0f);
        adapter.setDrawable(current);
        
        // Animate fade in
        view.animate()
            .alpha(1f)
            .setDuration(500)
            .setInterpolator(new DecelerateInterpolator())
            .start();
        
        return true;
    }
}

public class CustomTransitionActivity extends AppCompatActivity {
    
    public void useCustomTransition() {
        TransitionFactory<Drawable> fadeInFactory = new TransitionFactory<Drawable>() {
            @Override
            public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) {
                return new FadeInTransition();
            }
        };
        
        Glide.with(this)
            .load(imageUrl)
            .transition(DrawableTransitionOptions.with(fadeInFactory))
            .into(imageView);
    }
}

Advanced Custom Transitions

Create complex animations with multiple effects:

public class SlideUpFadeTransition implements Transition<Drawable> {
    
    @Override
    public boolean transition(Drawable current, Transition.ViewAdapter adapter) {
        View view = adapter.getView();
        float originalY = view.getTranslationY();
        
        // Set initial state
        view.setAlpha(0f);
        view.setTranslationY(view.getHeight() * 0.3f);
        adapter.setDrawable(current);
        
        // Create animator set for combined effects
        ObjectAnimator fadeAnimator = ObjectAnimator.ofFloat(view, "alpha", 0f, 1f);
        ObjectAnimator slideAnimator = ObjectAnimator.ofFloat(view, "translationY", view.getTranslationY(), originalY);
        
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(fadeAnimator, slideAnimator);
        animatorSet.setDuration(600);
        animatorSet.setInterpolator(new DecelerateInterpolator());
        animatorSet.start();
        
        return true;
    }
}

public class CrossFadeTransition implements Transition<Drawable> {
    private final int duration;
    
    public CrossFadeTransition() {
        this.duration = 300;
    }
    
    public CrossFadeTransition(int duration) {
        this.duration = duration;
    }
    
    @Override
    public boolean transition(Drawable current, Transition.ViewAdapter adapter) {
        Drawable previous = adapter.getCurrentDrawable();
        
        if (previous == null) {
            adapter.setDrawable(current);
            return false;
        }
        
        // Create cross-fade effect
        TransitionDrawable crossFadeDrawable = new TransitionDrawable(new Drawable[]{previous, current});
        adapter.setDrawable(crossFadeDrawable);
        crossFadeDrawable.startTransition(duration);
        
        return true;
    }
}

Conditional Transitions

Apply different transitions based on data source or conditions:

public class ConditionalTransitionFactory implements TransitionFactory<Drawable> {
    
    @Override
    public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) {
        // No transition for cached images (already fast)
        if (dataSource == DataSource.MEMORY_CACHE) {
            return null;
        }
        
        // Slow fade for remote images (user expects loading time)
        if (dataSource == DataSource.REMOTE) {
            return new CrossFadeTransition(500);
        }
        
        // Quick fade for local images
        if (dataSource == DataSource.LOCAL) {
            return new CrossFadeTransition(200);
        }
        
        // Custom transition for first load
        if (isFirstResource) {
            return new SlideUpFadeTransition();
        }
        
        // Default cross-fade
        return new CrossFadeTransition();
    }
}

public class ConditionalTransitionsActivity extends AppCompatActivity {
    
    public void useConditionalTransitions() {
        Glide.with(this)
            .load(imageUrl)
            .transition(DrawableTransitionOptions.with(new ConditionalTransitionFactory()))
            .into(imageView);
    }
}

Animation Timing and Customization

Transition Timing Control

Control animation duration and timing:

public class TimingControlActivity extends AppCompatActivity {
    
    public void variableTimingTransitions() {
        // Fast transition for thumbnails
        RequestOptions thumbnailOptions = new RequestOptions()
            .override(100, 100)
            .centerCrop();
        
        Glide.with(this)
            .load(thumbnailUrl)
            .apply(thumbnailOptions)
            .transition(DrawableTransitionOptions.withCrossFade(150))
            .into(thumbnailView);
        
        // Slow transition for hero images
        Glide.with(this)
            .load(heroImageUrl)
            .transition(DrawableTransitionOptions.withCrossFade(800))
            .into(heroImageView);
        
        // No transition for rapid scrolling
        if (isRapidScrolling) {
            Glide.with(this)
                .load(imageUrl)
                .dontAnimate()
                .into(imageView);
        }
    }
}

Interpolator Customization

Use different interpolators for varied animation feels:

public class InterpolatorTransition implements Transition<Drawable> {
    private final long duration;
    private final Interpolator interpolator;
    
    public InterpolatorTransition() {
        this.duration = 300;
        this.interpolator = new AccelerateDecelerateInterpolator();
    }
    
    public InterpolatorTransition(long duration, Interpolator interpolator) {
        this.duration = duration;
        this.interpolator = interpolator;
    }
    
    @Override
    public boolean transition(Drawable current, Transition.ViewAdapter adapter) {
        View view = adapter.getView();
        
        view.setAlpha(0f);
        adapter.setDrawable(current);
        
        view.animate()
            .alpha(1f)
            .setDuration(duration)
            .setInterpolator(interpolator)
            .start();
        
        return true;
    }
}

public class InterpolatorActivity extends AppCompatActivity {
    
    public void useInterpolators() {
        // Bouncy animation
        TransitionFactory<Drawable> bounceFactory = new TransitionFactory<Drawable>() {
            @Override
            public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) {
                return new InterpolatorTransition(600, new BounceInterpolator());
            }
        };
        
        // Overshoot animation  
        TransitionFactory<Drawable> overshootFactory = new TransitionFactory<Drawable>() {
            @Override
            public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) {
                return new InterpolatorTransition(500, new OvershootInterpolator());
            }
        };
        
        Glide.with(this)
            .load(imageUrl)
            .transition(DrawableTransitionOptions.with(bounceFactory))
            .into(imageView);
    }
}

Global Transition Configuration

Default Transitions

Set default transitions through GlideModule:

public class GlobalTransitionModule extends AppGlideModule {
    
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
        // Set default drawable transitions
        builder.setDefaultTransitionOptions(
            Drawable.class,
            DrawableTransitionOptions.withCrossFade(400)
        );
        
        // Set default bitmap transitions  
        builder.setDefaultTransitionOptions(
            Bitmap.class,
            BitmapTransitionOptions.withCrossFade(300)
        );
    }
}

RequestOptions with Transitions

Create reusable transition configurations:

public class TransitionPresets {
    
    public static final RequestOptions INSTANT = new RequestOptions()
        .dontAnimate();
    
    public static final RequestOptions FAST_FADE = new RequestOptions()
        .transition(DrawableTransitionOptions.withCrossFade(200));
    
    public static final RequestOptions SLOW_FADE = new RequestOptions()
        .transition(DrawableTransitionOptions.withCrossFade(600));
    
    public static final RequestOptions CUSTOM_SLIDE = new RequestOptions()
        .transition(DrawableTransitionOptions.with(
            new TransitionFactory<Drawable>() {
                @Override
                public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) {
                    return new SlideUpFadeTransition();
                }
            }
        ));
}

public class TransitionPresetsActivity extends AppCompatActivity {
    
    public void usePresets() {
        // Gallery thumbnails - fast
        Glide.with(this)
            .load(thumbnailUrl)
            .apply(TransitionPresets.FAST_FADE)
            .into(thumbnailView);
        
        // Featured image - slow elegant fade
        Glide.with(this)
            .load(featuredUrl)
            .apply(TransitionPresets.SLOW_FADE)
            .into(featuredView);
        
        // Profile image - custom slide effect
        Glide.with(this)
            .load(profileUrl)
            .apply(TransitionPresets.CUSTOM_SLIDE)
            .into(profileView);
    }
}

Performance Considerations

Optimized Transitions

Balance visual appeal with performance:

public class PerformanceOptimizedTransitions extends AppCompatActivity {
    
    public void optimizeForPerformance() {
        // Disable transitions during fast scrolling
        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                boolean useTransitions = newState != RecyclerView.SCROLL_STATE_SETTLING;
                
                if (useTransitions) {
                    // Normal transitions when not scrolling
                    Glide.with(PerformanceOptimizedTransitions.this)
                        .setDefaultRequestOptions(TransitionPresets.FAST_FADE);
                } else {
                    // No transitions during scroll
                    Glide.with(PerformanceOptimizedTransitions.this)
                        .setDefaultRequestOptions(TransitionPresets.INSTANT);
                }
            }
        });
    }
    
    public void adaptiveTransitions() {
        // Adjust transitions based on device performance
        boolean isLowEndDevice = !ActivityManager.isHighPerformanceDevice();
        
        DrawableTransitionOptions transitionOptions;
        if (isLowEndDevice) {
            // Minimal transitions on low-end devices
            transitionOptions = DrawableTransitionOptions.withCrossFade(150);
        } else {
            // Rich transitions on capable devices
            transitionOptions = DrawableTransitionOptions.withCrossFade(400);
        }
        
        Glide.with(this)
            .load(imageUrl)
            .transition(transitionOptions)
            .into(imageView);
    }
}

Best Practices

Transition Guidelines

  1. Performance: Disable transitions during rapid scrolling for smooth performance
  2. Consistency: Use consistent transition timing across similar UI elements
  3. Context Awareness: Adapt transition duration based on image source and size
  4. Device Capability: Consider device performance when choosing transition complexity
  5. User Experience: Match transitions to user expectations and app personality

Common Patterns

public class TransitionBestPractices {
    
    // Context-aware transition selection
    public static DrawableTransitionOptions getOptimalTransition(Context context, ImageSize imageSize) {
        switch (imageSize) {
            case THUMBNAIL:
                return DrawableTransitionOptions.withCrossFade(150);
            case MEDIUM:
                return DrawableTransitionOptions.withCrossFade(300);
            case LARGE:
                return DrawableTransitionOptions.withCrossFade(500);
            case HERO:
                return DrawableTransitionOptions.withCrossFade(800);
            default:
                return DrawableTransitionOptions.withCrossFade(300);
        }
    }
    
    // Scroll-state aware transitions
    public static DrawableTransitionOptions getScrollAwareTransition(boolean isScrolling) {
        if (isScrolling) {
            return DrawableTransitionOptions.withNoTransition();
        } else {
            return DrawableTransitionOptions.withCrossFade(250);
        }
    }
}

This comprehensive transition system provides the tools needed to create smooth, visually appealing image loading experiences while maintaining optimal performance across different device capabilities and usage patterns.

Install with Tessl CLI

npx tessl i tessl/maven-com-github-bumptech-glide--glide

docs

caching-strategies.md

error-handling-debugging.md

index.md

modules-configuration.md

request-configuration.md

request-management.md

targets-loading.md

transformations.md

transitions-animations.md

tile.json