[Android / Glide] Glide 이미지 로딩 중 다른 scaleType 적용하기

Glide 동작을 테스트하면서 아래와 같은 상황이 발생하였다.

  1. 기존에 사용하던 로딩이미지의 ScaleType은 CENTER를 사용해야 한다.
  2. Glide로 로드한 이미지는 로딩이미지와는 다른 각자의 ScaleType을 가지고 있다.

따라서 loadingImage와 loadedImage의 ScaleType을 외부에서 설정만 해주면 내부에서 자동으로 바꿔서 보여주도록 만들고자 했다.

이 작업을 위해 Glide에서는 이미지 로딩 중 placeholder 노출, 리소스 로드 등의 동작을 확장 구현할 수 있도록 Target을 제공한다는 점을 먼저 말해두겠다. 이 Target은 into()를 통해 전달할 수 있다.

1
2
3
4
5
6
Target<Drawable> target =
Glide.with(fragment)
.load(url)
.into(new Target<Drawable>() {
...
});

이러한 Target를 상속받는 클래스를 만들어서 placeholder는 onLoadStarted, error는 onLoadFailed에 각각 정의하려고 한다. 이때 로딩이미지는 drawable 리소스로 앱에 저장되어있기 때문에 DrawableImageViewTarget을 상속받아 만든 게 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class ScaleLoadingImageViewTarget extends DrawableImageViewTarget {
private ImageView.ScaleType mLoadingScaleType;
private ImageView.ScaleType mReadyScaleType;

 // RequestOptions에서 정의해둔 scale은 fitCenter
public ScaleLoadingImageViewTarget(ImageView view, ImageView.ScaleType scaleType) {
super(view);
// loadingCenter()에서 받아온 scale
mLoadingScaleType = scaleType;
        // xml에서 정의해둔 scale
// (따로 정의되지 않았다면 여기에 RequestOptions scaleType인 fitCenter가 들어옴
mReadyScaleType = view.getScaleType();
}

@Override
public void onLoadStarted(@Nullable Drawable placeholder) {
ImageView imageView = getView();
imageView.setScaleType(mLoadingScaleType);
super.onLoadStarted(placeholder);
}

@Override
public void onLoadFailed(@Nullable Drawable errorDrawable) {
ImageView imageView = getView();
imageView.setScaleType(mLoadingScaleType);
super.onLoadFailed(errorDrawable);
}

    @Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
ImageView imageView = getView();
imageView.setImageResource(0); // 로딩 이미지가 보여지고 있을 때 scaleType이 바뀌면서 이미지가 덜그럭 거리는 이슈 방어
imageView.setScaleType(mReadyScaleType);
super.onResourceReady(resource, transition);
}

@NonNull
public static ScaleLoadingImageViewTarget loadingCenter(ImageView imageView) {
return new ScaleLoadingImageViewTarget(imageView, ImageView.ScaleType.CENTER);
}
}

loadingCenter 메소드를 통해 위에 새롭게 정의된 Target에 접근할 수 있도록 한다.

1
2
3
4
5
Glide.with(context)
.load(url)
.listener(listener)
.apply(options)
.into(ScaleLoadingImageViewTarget.loadingCenter(imageView));

참고링크

그러나 이 방식을 적용한 ImageView가 담긴 RecyclerView를 구현하게 되면, RecyclerView 각 아이템이 재사용되면서 ScaleLoadingImageViewTarget의 생성자에서 호출하는 view.getScaleType()의 값이 기대한 대로 나오지 않는 경우가 있어 문제가 될 수 있다.

따라서 이를 아래와 같이 view의 ScaleType을 명시적으로 받도록 변경하였다.

1
2
3
4
5
Glide.with(context)
.load(url)
.listener(listener)
.apply(options)
.into(ScaleLoadingImageViewTarget.loadingCenter(imageView, ScaleType.FIT_CENTER));
1
2
3
4
5
6
7
8
9
10
public ScaleLoadingImageViewTarget(ImageView view, ImageView.ScaleType originScaleType, ImageView.ScaleType loadingScaleType) {
super(view);
mLoadingScaleType = loadingScaleType;
mReadyScaleType = originScaleType;
}

@NonNull
public static ScaleLoadingImageViewTarget loadingCenter(ImageView imageView, ImageView.ScaleType originScaleType) {
return new ScaleLoadingImageViewTarget(imageView, originScaleType, ImageView.ScaleType.CENTER);
}

[Android / Glide] Glide 이미지 로딩 중 다른 scaleType 적용하기

https://dl137584.github.io/2022/05/02/024-allow-the-different-scaletype-when-loading-image-in-glide/

Author

LEEJS

Posted on

2022-05-02

Updated on

2022-05-02

Licensed under

댓글