0
# Glide Transitions and Animations System
1
2
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.
3
4
## TransitionOptions Base Class
5
6
The foundation for all transition configurations in Glide:
7
8
```java { .api }
9
public abstract class TransitionOptions<CHILD extends TransitionOptions<CHILD, TranscodeType>, TranscodeType> {
10
11
/**
12
* Disables all transitions for this request
13
* @return Updated options instance
14
*/
15
public abstract CHILD dontTransition();
16
17
/**
18
* Creates a clone of these options
19
* @return Cloned options instance
20
*/
21
public abstract CHILD clone();
22
23
/**
24
* Creates empty transition options with no effects
25
*/
26
public static <T> TransitionOptions<?, T> of() {
27
// Implementation provided by Glide
28
return null;
29
}
30
}
31
```
32
33
## DrawableTransitionOptions Class
34
35
Specialized transition options for Drawable resources with built-in cross-fade support:
36
37
```java { .api }
38
public class DrawableTransitionOptions extends TransitionOptions<DrawableTransitionOptions, Drawable> {
39
40
/**
41
* Creates cross-fade transition with default duration (300ms)
42
* @return DrawableTransitionOptions with cross-fade
43
*/
44
public static DrawableTransitionOptions withCrossFade() {
45
// Implementation provided by Glide
46
return null;
47
}
48
49
/**
50
* Creates cross-fade transition with custom duration
51
* @param duration Fade duration in milliseconds
52
* @return DrawableTransitionOptions with timed cross-fade
53
*/
54
public static DrawableTransitionOptions withCrossFade(int duration) {
55
// Implementation provided by Glide
56
return null;
57
}
58
59
/**
60
* Creates cross-fade with custom duration and animation builder
61
* @param duration Fade duration in milliseconds
62
* @param animationId Android animation resource ID
63
* @return DrawableTransitionOptions with custom animation
64
*/
65
public static DrawableTransitionOptions withCrossFade(int duration, int animationId) {
66
// Implementation provided by Glide
67
return null;
68
}
69
70
/**
71
* Creates transition with custom transition factory
72
* @param transitionFactory Factory for creating transitions
73
* @return DrawableTransitionOptions with custom factory
74
*/
75
public static DrawableTransitionOptions with(TransitionFactory<? super Drawable> transitionFactory) {
76
// Implementation provided by Glide
77
return null;
78
}
79
80
/**
81
* Creates transition with no animation effects
82
* @return DrawableTransitionOptions with transitions disabled
83
*/
84
public static DrawableTransitionOptions withNoTransition() {
85
// Implementation provided by Glide
86
return null;
87
}
88
89
@Override
90
public DrawableTransitionOptions clone() {
91
// Implementation provided by Glide
92
return null;
93
}
94
}
95
```
96
97
## BitmapTransitionOptions Class
98
99
Transition options specifically for Bitmap resources:
100
101
```java { .api }
102
public class BitmapTransitionOptions extends TransitionOptions<BitmapTransitionOptions, Bitmap> {
103
104
/**
105
* Creates cross-fade transition for bitmaps (default 300ms)
106
* @return BitmapTransitionOptions with cross-fade
107
*/
108
public static BitmapTransitionOptions withCrossFade() {
109
// Implementation provided by Glide
110
return null;
111
}
112
113
/**
114
* Creates cross-fade transition with custom duration
115
* @param duration Fade duration in milliseconds
116
* @return BitmapTransitionOptions with timed cross-fade
117
*/
118
public static BitmapTransitionOptions withCrossFade(int duration) {
119
// Implementation provided by Glide
120
return null;
121
}
122
123
/**
124
* Creates custom bitmap transition
125
* @param transitionFactory Factory for bitmap transitions
126
* @return BitmapTransitionOptions with custom factory
127
*/
128
public static BitmapTransitionOptions with(TransitionFactory<? super Bitmap> transitionFactory) {
129
// Implementation provided by Glide
130
return null;
131
}
132
133
/**
134
* Creates no-transition options for bitmaps
135
* @return BitmapTransitionOptions with no effects
136
*/
137
public static BitmapTransitionOptions withNoTransition() {
138
// Implementation provided by Glide
139
return null;
140
}
141
142
@Override
143
public BitmapTransitionOptions clone() {
144
// Implementation provided by Glide
145
return null;
146
}
147
}
148
```
149
150
## Transition Interface
151
152
Core interface for implementing custom transitions:
153
154
```java { .api }
155
public interface Transition<R> {
156
/**
157
* Executes the transition animation
158
* @param current Current resource (may be placeholder)
159
* @param adapter Adapter for applying the transition
160
* @return True if transition was applied, false otherwise
161
*/
162
boolean transition(R current, ViewAdapter adapter);
163
164
/**
165
* Adapter interface for applying transitions to views
166
*/
167
interface ViewAdapter {
168
/**
169
* Gets the current drawable from the view
170
* @return Current drawable or null
171
*/
172
Drawable getCurrentDrawable();
173
174
/**
175
* Sets the drawable on the view
176
* @param drawable Drawable to set
177
*/
178
void setDrawable(Drawable drawable);
179
180
/**
181
* Gets the underlying view
182
* @return View being transitioned
183
*/
184
View getView();
185
}
186
}
187
```
188
189
## ViewTransition Interface
190
191
Specialized transition interface for view-based animations:
192
193
```java { .api }
194
public interface ViewTransition {
195
/**
196
* Executes transition on a specific view
197
* @param view Target view for the transition
198
* @param adapter Adapter for view operations
199
* @return True if transition was handled
200
*/
201
boolean transition(View view, Transition.ViewAdapter adapter);
202
203
/**
204
* Creates a view transition from an animation resource
205
* @param animationId Android animation resource ID
206
* @return ViewTransition using the animation
207
*/
208
static ViewTransition withAnimation(int animationId) {
209
// Implementation provided by Glide
210
return null;
211
}
212
213
/**
214
* Creates a view transition with no animation
215
* @return ViewTransition that immediately sets the drawable
216
*/
217
static ViewTransition withNoTransition() {
218
// Implementation provided by Glide
219
return null;
220
}
221
}
222
```
223
224
## TransitionFactory Interface
225
226
Factory interface for creating transition instances:
227
228
```java { .api }
229
public interface TransitionFactory<R> {
230
/**
231
* Creates a transition for the given data source
232
* @param dataSource Source of the image data
233
* @param isFirstResource Whether this is the first resource loaded
234
* @return Transition instance or null for no transition
235
*/
236
Transition<R> build(DataSource dataSource, boolean isFirstResource);
237
}
238
```
239
240
## Basic Transition Usage
241
242
### Simple Cross-Fade Transitions
243
244
Apply basic cross-fade effects to image loading:
245
246
```java
247
public class BasicTransitionsActivity extends AppCompatActivity {
248
249
public void basicCrossFade() {
250
// Default cross-fade (300ms)
251
Glide.with(this)
252
.load(imageUrl)
253
.transition(DrawableTransitionOptions.withCrossFade())
254
.into(imageView);
255
256
// Custom duration cross-fade
257
Glide.with(this)
258
.load(imageUrl)
259
.transition(DrawableTransitionOptions.withCrossFade(500))
260
.into(imageView);
261
262
// Bitmap-specific cross-fade
263
Glide.with(this)
264
.asBitmap()
265
.load(imageUrl)
266
.transition(BitmapTransitionOptions.withCrossFade(400))
267
.into(imageView);
268
}
269
270
public void noTransition() {
271
// Disable transitions completely
272
Glide.with(this)
273
.load(imageUrl)
274
.transition(DrawableTransitionOptions.withNoTransition())
275
.into(imageView);
276
277
// Alternative syntax
278
Glide.with(this)
279
.load(imageUrl)
280
.dontAnimate()
281
.into(imageView);
282
}
283
}
284
```
285
286
### Android Animation Resources
287
288
Use Android animation XML resources for transitions:
289
290
```java
291
public class AnimationResourceActivity extends AppCompatActivity {
292
293
public void useAnimationResources() {
294
// Create animation XML file: res/anim/fade_in.xml
295
/*
296
<?xml version="1.0" encoding="utf-8"?>
297
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
298
android:fromAlpha="0.0"
299
android:toAlpha="1.0"
300
android:duration="600" />
301
*/
302
303
// Apply animation resource
304
Glide.with(this)
305
.load(imageUrl)
306
.transition(DrawableTransitionOptions.withCrossFade(600, R.anim.fade_in))
307
.into(imageView);
308
309
// Scale animation: res/anim/scale_up.xml
310
/*
311
<?xml version="1.0" encoding="utf-8"?>
312
<scale xmlns:android="http://schemas.android.com/apk/res/android"
313
android:fromXScale="0.8"
314
android:fromYScale="0.8"
315
android:toXScale="1.0"
316
android:toYScale="1.0"
317
android:pivotX="50%"
318
android:pivotY="50%"
319
android:duration="400"
320
android:interpolator="@android:anim/decelerate_interpolator" />
321
*/
322
323
ViewTransition scaleTransition = ViewTransition.withAnimation(R.anim.scale_up);
324
Glide.with(this)
325
.load(imageUrl)
326
.transition(DrawableTransitionOptions.with(
327
new TransitionFactory<Drawable>() {
328
@Override
329
public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) {
330
return scaleTransition;
331
}
332
}
333
))
334
.into(imageView);
335
}
336
}
337
```
338
339
## Custom Transitions
340
341
### Simple Custom Transition
342
343
Create custom transition effects by implementing the Transition interface:
344
345
```java
346
public class FadeInTransition implements Transition<Drawable> {
347
348
@Override
349
public boolean transition(Drawable current, Transition.ViewAdapter adapter) {
350
View view = adapter.getView();
351
352
// Set initial alpha and drawable
353
view.setAlpha(0f);
354
adapter.setDrawable(current);
355
356
// Animate fade in
357
view.animate()
358
.alpha(1f)
359
.setDuration(500)
360
.setInterpolator(new DecelerateInterpolator())
361
.start();
362
363
return true;
364
}
365
}
366
367
public class CustomTransitionActivity extends AppCompatActivity {
368
369
public void useCustomTransition() {
370
TransitionFactory<Drawable> fadeInFactory = new TransitionFactory<Drawable>() {
371
@Override
372
public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) {
373
return new FadeInTransition();
374
}
375
};
376
377
Glide.with(this)
378
.load(imageUrl)
379
.transition(DrawableTransitionOptions.with(fadeInFactory))
380
.into(imageView);
381
}
382
}
383
```
384
385
### Advanced Custom Transitions
386
387
Create complex animations with multiple effects:
388
389
```java
390
public class SlideUpFadeTransition implements Transition<Drawable> {
391
392
@Override
393
public boolean transition(Drawable current, Transition.ViewAdapter adapter) {
394
View view = adapter.getView();
395
float originalY = view.getTranslationY();
396
397
// Set initial state
398
view.setAlpha(0f);
399
view.setTranslationY(view.getHeight() * 0.3f);
400
adapter.setDrawable(current);
401
402
// Create animator set for combined effects
403
ObjectAnimator fadeAnimator = ObjectAnimator.ofFloat(view, "alpha", 0f, 1f);
404
ObjectAnimator slideAnimator = ObjectAnimator.ofFloat(view, "translationY", view.getTranslationY(), originalY);
405
406
AnimatorSet animatorSet = new AnimatorSet();
407
animatorSet.playTogether(fadeAnimator, slideAnimator);
408
animatorSet.setDuration(600);
409
animatorSet.setInterpolator(new DecelerateInterpolator());
410
animatorSet.start();
411
412
return true;
413
}
414
}
415
416
public class CrossFadeTransition implements Transition<Drawable> {
417
private final int duration;
418
419
public CrossFadeTransition() {
420
this.duration = 300;
421
}
422
423
public CrossFadeTransition(int duration) {
424
this.duration = duration;
425
}
426
427
@Override
428
public boolean transition(Drawable current, Transition.ViewAdapter adapter) {
429
Drawable previous = adapter.getCurrentDrawable();
430
431
if (previous == null) {
432
adapter.setDrawable(current);
433
return false;
434
}
435
436
// Create cross-fade effect
437
TransitionDrawable crossFadeDrawable = new TransitionDrawable(new Drawable[]{previous, current});
438
adapter.setDrawable(crossFadeDrawable);
439
crossFadeDrawable.startTransition(duration);
440
441
return true;
442
}
443
}
444
```
445
446
### Conditional Transitions
447
448
Apply different transitions based on data source or conditions:
449
450
```java
451
public class ConditionalTransitionFactory implements TransitionFactory<Drawable> {
452
453
@Override
454
public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) {
455
// No transition for cached images (already fast)
456
if (dataSource == DataSource.MEMORY_CACHE) {
457
return null;
458
}
459
460
// Slow fade for remote images (user expects loading time)
461
if (dataSource == DataSource.REMOTE) {
462
return new CrossFadeTransition(500);
463
}
464
465
// Quick fade for local images
466
if (dataSource == DataSource.LOCAL) {
467
return new CrossFadeTransition(200);
468
}
469
470
// Custom transition for first load
471
if (isFirstResource) {
472
return new SlideUpFadeTransition();
473
}
474
475
// Default cross-fade
476
return new CrossFadeTransition();
477
}
478
}
479
480
public class ConditionalTransitionsActivity extends AppCompatActivity {
481
482
public void useConditionalTransitions() {
483
Glide.with(this)
484
.load(imageUrl)
485
.transition(DrawableTransitionOptions.with(new ConditionalTransitionFactory()))
486
.into(imageView);
487
}
488
}
489
```
490
491
## Animation Timing and Customization
492
493
### Transition Timing Control
494
495
Control animation duration and timing:
496
497
```java
498
public class TimingControlActivity extends AppCompatActivity {
499
500
public void variableTimingTransitions() {
501
// Fast transition for thumbnails
502
RequestOptions thumbnailOptions = new RequestOptions()
503
.override(100, 100)
504
.centerCrop();
505
506
Glide.with(this)
507
.load(thumbnailUrl)
508
.apply(thumbnailOptions)
509
.transition(DrawableTransitionOptions.withCrossFade(150))
510
.into(thumbnailView);
511
512
// Slow transition for hero images
513
Glide.with(this)
514
.load(heroImageUrl)
515
.transition(DrawableTransitionOptions.withCrossFade(800))
516
.into(heroImageView);
517
518
// No transition for rapid scrolling
519
if (isRapidScrolling) {
520
Glide.with(this)
521
.load(imageUrl)
522
.dontAnimate()
523
.into(imageView);
524
}
525
}
526
}
527
```
528
529
### Interpolator Customization
530
531
Use different interpolators for varied animation feels:
532
533
```java
534
public class InterpolatorTransition implements Transition<Drawable> {
535
private final long duration;
536
private final Interpolator interpolator;
537
538
public InterpolatorTransition() {
539
this.duration = 300;
540
this.interpolator = new AccelerateDecelerateInterpolator();
541
}
542
543
public InterpolatorTransition(long duration, Interpolator interpolator) {
544
this.duration = duration;
545
this.interpolator = interpolator;
546
}
547
548
@Override
549
public boolean transition(Drawable current, Transition.ViewAdapter adapter) {
550
View view = adapter.getView();
551
552
view.setAlpha(0f);
553
adapter.setDrawable(current);
554
555
view.animate()
556
.alpha(1f)
557
.setDuration(duration)
558
.setInterpolator(interpolator)
559
.start();
560
561
return true;
562
}
563
}
564
565
public class InterpolatorActivity extends AppCompatActivity {
566
567
public void useInterpolators() {
568
// Bouncy animation
569
TransitionFactory<Drawable> bounceFactory = new TransitionFactory<Drawable>() {
570
@Override
571
public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) {
572
return new InterpolatorTransition(600, new BounceInterpolator());
573
}
574
};
575
576
// Overshoot animation
577
TransitionFactory<Drawable> overshootFactory = new TransitionFactory<Drawable>() {
578
@Override
579
public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) {
580
return new InterpolatorTransition(500, new OvershootInterpolator());
581
}
582
};
583
584
Glide.with(this)
585
.load(imageUrl)
586
.transition(DrawableTransitionOptions.with(bounceFactory))
587
.into(imageView);
588
}
589
}
590
```
591
592
## Global Transition Configuration
593
594
### Default Transitions
595
596
Set default transitions through GlideModule:
597
598
```java
599
public class GlobalTransitionModule extends AppGlideModule {
600
601
@Override
602
public void applyOptions(Context context, GlideBuilder builder) {
603
// Set default drawable transitions
604
builder.setDefaultTransitionOptions(
605
Drawable.class,
606
DrawableTransitionOptions.withCrossFade(400)
607
);
608
609
// Set default bitmap transitions
610
builder.setDefaultTransitionOptions(
611
Bitmap.class,
612
BitmapTransitionOptions.withCrossFade(300)
613
);
614
}
615
}
616
```
617
618
### RequestOptions with Transitions
619
620
Create reusable transition configurations:
621
622
```java
623
public class TransitionPresets {
624
625
public static final RequestOptions INSTANT = new RequestOptions()
626
.dontAnimate();
627
628
public static final RequestOptions FAST_FADE = new RequestOptions()
629
.transition(DrawableTransitionOptions.withCrossFade(200));
630
631
public static final RequestOptions SLOW_FADE = new RequestOptions()
632
.transition(DrawableTransitionOptions.withCrossFade(600));
633
634
public static final RequestOptions CUSTOM_SLIDE = new RequestOptions()
635
.transition(DrawableTransitionOptions.with(
636
new TransitionFactory<Drawable>() {
637
@Override
638
public Transition<Drawable> build(DataSource dataSource, boolean isFirstResource) {
639
return new SlideUpFadeTransition();
640
}
641
}
642
));
643
}
644
645
public class TransitionPresetsActivity extends AppCompatActivity {
646
647
public void usePresets() {
648
// Gallery thumbnails - fast
649
Glide.with(this)
650
.load(thumbnailUrl)
651
.apply(TransitionPresets.FAST_FADE)
652
.into(thumbnailView);
653
654
// Featured image - slow elegant fade
655
Glide.with(this)
656
.load(featuredUrl)
657
.apply(TransitionPresets.SLOW_FADE)
658
.into(featuredView);
659
660
// Profile image - custom slide effect
661
Glide.with(this)
662
.load(profileUrl)
663
.apply(TransitionPresets.CUSTOM_SLIDE)
664
.into(profileView);
665
}
666
}
667
```
668
669
## Performance Considerations
670
671
### Optimized Transitions
672
673
Balance visual appeal with performance:
674
675
```java
676
public class PerformanceOptimizedTransitions extends AppCompatActivity {
677
678
public void optimizeForPerformance() {
679
// Disable transitions during fast scrolling
680
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
681
@Override
682
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
683
boolean useTransitions = newState != RecyclerView.SCROLL_STATE_SETTLING;
684
685
if (useTransitions) {
686
// Normal transitions when not scrolling
687
Glide.with(PerformanceOptimizedTransitions.this)
688
.setDefaultRequestOptions(TransitionPresets.FAST_FADE);
689
} else {
690
// No transitions during scroll
691
Glide.with(PerformanceOptimizedTransitions.this)
692
.setDefaultRequestOptions(TransitionPresets.INSTANT);
693
}
694
}
695
});
696
}
697
698
public void adaptiveTransitions() {
699
// Adjust transitions based on device performance
700
boolean isLowEndDevice = !ActivityManager.isHighPerformanceDevice();
701
702
DrawableTransitionOptions transitionOptions;
703
if (isLowEndDevice) {
704
// Minimal transitions on low-end devices
705
transitionOptions = DrawableTransitionOptions.withCrossFade(150);
706
} else {
707
// Rich transitions on capable devices
708
transitionOptions = DrawableTransitionOptions.withCrossFade(400);
709
}
710
711
Glide.with(this)
712
.load(imageUrl)
713
.transition(transitionOptions)
714
.into(imageView);
715
}
716
}
717
```
718
719
## Best Practices
720
721
### Transition Guidelines
722
723
1. **Performance**: Disable transitions during rapid scrolling for smooth performance
724
2. **Consistency**: Use consistent transition timing across similar UI elements
725
3. **Context Awareness**: Adapt transition duration based on image source and size
726
4. **Device Capability**: Consider device performance when choosing transition complexity
727
5. **User Experience**: Match transitions to user expectations and app personality
728
729
### Common Patterns
730
731
```java
732
public class TransitionBestPractices {
733
734
// Context-aware transition selection
735
public static DrawableTransitionOptions getOptimalTransition(Context context, ImageSize imageSize) {
736
switch (imageSize) {
737
case THUMBNAIL:
738
return DrawableTransitionOptions.withCrossFade(150);
739
case MEDIUM:
740
return DrawableTransitionOptions.withCrossFade(300);
741
case LARGE:
742
return DrawableTransitionOptions.withCrossFade(500);
743
case HERO:
744
return DrawableTransitionOptions.withCrossFade(800);
745
default:
746
return DrawableTransitionOptions.withCrossFade(300);
747
}
748
}
749
750
// Scroll-state aware transitions
751
public static DrawableTransitionOptions getScrollAwareTransition(boolean isScrolling) {
752
if (isScrolling) {
753
return DrawableTransitionOptions.withNoTransition();
754
} else {
755
return DrawableTransitionOptions.withCrossFade(250);
756
}
757
}
758
}
759
```
760
761
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.