(부제 : 아니 CenterCrop을 하고 Radius 적용해 달라고!!!!!)
슬픈 서론...
나 : 글라이드 최고최고! 옵션만 주면 알아서 모서리 깎아줌 ㅋ
QA : 결함 - 어떤 이미지 뷰는 라운드 처리 되었으나 또 어떤 이미지 뷰는 라운드 처리 되지 않음.
나 : 아니, 절대 그럴 리가 없어.
QA : (사진 첨부)
나 : 사람은 누구나 실수를 하지. 🙂
며칠 전 QA 결과를 보고 이런 자잘한 실수를 했을 리가 없다고 현실 부정을 했지만 캡쳐본에는... 어떤 것은 덜 깎여있고, 어떤 것은 안 깎여있는 그런 이미지가 바인딩 되어 있었다.
ImageView의 scaleType을 정확하게 줬다고!!!!! 진짜로!!!!!😫 라고 하지 말고 제대로 살펴보자.
재현 되었던 환경
나는 해당 ImageView scaleType을 centerCrop으로 설정했다.
서버에서 보내주는 이미지의 크기가 일정하지 않기 때문에 내 이미지 뷰에 꽉 차길 바랐고, fitXY 사용 시 ImageView의 비율이 조정되기 때문에 (찌그러진다) ImageView에 공백 없이 들어찬 후 crop 되길 바랐다.
그 다음 Glide의 transform을 이용하여 radius를 적용했으나, 위에 언급한 결함이 발생하였다.
이러한 결함이 재현 되는 이유?
정확한 자료를 찾을 수는 없었지만 (링크 제보 받아요🙌) 현상이 나타난 이미지의 형태들로 추측해 봤다.
- 이미지 url을 전달 받음
- RequestOptions으로 받은 옵션들을 apply함.
- into() 메서드에서 받은 타겟으로 ImageView에 바인드 함
위 과정에서 3번에 ImageView의 scaleType이 bind 될 때에서야 적용되는 것이므로 이미 2번에서 가공이 완료된 사진을 넣을 때 다시 한 번 ImageView의 scaleType 값에 의해서 가공이 되는 것이라는 생각이 들었다. width와 height가 다양한 이미지가 내가 옵션을 준 대로 radius 가공이 되고, 그 후에 ImageView의 제한된 크기에 맞춰지면서 한 번 더 가공이 되어 radius 가공된 부분이 잘려져 나간 것으로 생각됐다. 그래서 ImageView의 scaleType 값을 사용하지 않고 Glide 라이브러리의 transform을 이용하여 centerCrop과 radius를 둘 다 transform을 할 수 있도록 만들었다.
Glide.with(context)
.load(url)
.apply(new RequestOptions().transforms(new CenterCrop(),
new RoundedCorners(20)))
.into(imageView);
위와 같은 소스로 변경을 하였으나 문제가 되는 현상은 여전했고 순서대로 가공할 수 있는 방법을 찾았다.
해결 방법 - MultiTransformation
MultiTransformation
은 여러 개의 Transformation
을 파라미터로 받아 순서대로 transform 해준다.
아래는 Glide의 github 페이지에서 가져온 MultiTransformation 코드의 한 부분이다.
library/src/main/java/com/bumptech/glide/load/MultiTransformation.java
/**
* A transformation that applies one or more transformations in iteration order to a resource.
*
* @param <T> The type of {@link com.bumptech.glide.load.engine.Resource} that will be transformed.
*/
public class MultiTransformation<T> implements Transformation<T> {
private final Collection<? extends Transformation<T>> transformations;
@SafeVarargs
@SuppressWarnings("varargs")
public MultiTransformation(@NonNull Transformation<T>... transformations) {
if (transformations.length == 0) {
throw new IllegalArgumentException(
"MultiTransformation must contain at least one Transformation");
}
this.transformations = Arrays.asList(transformations);
}
@NonNull
@Override
public Resource<T> transform(
@NonNull Context context, @NonNull Resource<T> resource, int outWidth, int outHeight) {
Resource<T> previous = resource;
for (Transformation<T> transformation : transformations) {
Resource<T> transformed = transformation.transform(context, previous, outWidth, outHeight);
if (previous != null && !previous.equals(resource) && !previous.equals(transformed)) {
previous.recycle();
}
previous = transformed;
}
return previous;
}
MultiTransformation
은 파라미터로 넘어온 Option들을 ArrayList에 저장해 반환한다.
이 ArrayList는 for문을 돌면서 차례대로 transform이 되고 변환이 완료된 사진을 반환한다.
따라서 아래와 같은 소스로 내가 원하는 선crop 후radius를 구현할 수 있었다.
MultiTransformation multiOption = new MultiTransformation(
new CenterCrop(),
new RoundedCorners(20)
);
Glide.with(mContext)
.load(star.getProfileImage())
.apply(RequestOptions.bitmapTransform(multiOption))
.into(imageView);