Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Non-stretching Glide placeholder
import com.bumptech.glide.request.transition.Transition
class PaddingTransition<T : Drawable>(private val realTransition: Transition<in T>) : Transition<T> {
override fun transition(current: T, adapter: Transition.ViewAdapter): Boolean {
val width = current.intrinsicWidth
val height = current.intrinsicHeight
return realTransition.transition(current, PaddingViewAdapter(adapter, width, height))
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.request.transition.DrawableCrossFadeFactory
import com.bumptech.glide.request.transition.Transition
import com.bumptech.glide.request.transition.TransitionFactory
class PaddingTransitionFactory<T : Drawable>(
private val realFactory: DrawableCrossFadeFactory
) : TransitionFactory<T> {
override fun build(dataSource: DataSource, b: Boolean): Transition<T> {
return PaddingTransition(, b))
import android.os.Build
import android.view.View
class PaddingViewAdapter(
private val realAdapter: Transition.ViewAdapter,
private val targetWidth: Int,
private val targetHeight: Int) : Transition.ViewAdapter {
override fun getView(): View = realAdapter.view
override fun getCurrentDrawable(): Drawable? {
var drawable = realAdapter.currentDrawable
if (drawable != null) {
val padX = Math.max(0, targetWidth - drawable.intrinsicWidth) / 2
val padY = Math.max(0, targetHeight - drawable.intrinsicHeight) / 2
if (padX > 0 || padY > 0) {
drawable = InsetDrawable(drawable, padX, padY, padX, padY)
return drawable
override fun setDrawable(drawable: Drawable) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && drawable is TransitionDrawable) {
// For some reason padding is taken into account differently on M than before in LayerDrawable
// PaddingMode was introduced in 21 and gravity in 23, I think NO_GRAVITY default may play
// a role in this, but didn't have time to dig deeper than this.
drawable.paddingMode = TransitionDrawable.PADDING_MODE_STACK
val transitionFactory = DrawableCrossFadeFactory.Builder()
val placeholder = R.drawable.ic_placeholder_white_24dp
// The default Glide behavior is to stretch the placeholder to fit the ImageView
// This makes the placeholder be exactly its intrinsic size - 24dp in this example.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment