Glide中的 Transformation,多次设置,后面的会覆盖前面的。
如果 ImageView的 scaleType = “centerCrop”,会在 into()方法前自动加上 centerCrop(),即会调用 CenterCrop#transform()
。
public class CenterCrop extends BitmapTransformation {
private static final String ID = "com.bumptech.glide.load.resource.bitmap.CenterCrop";
private static final byte[] ID_BYTES = ID.getBytes(CHARSET);
@Override
protected Bitmap transform(
@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
return TransformationUtils.centerCrop(pool, toTransform, outWidth, outHeight);
}
@Override
public boolean equals(Object o) {
return o instanceof CenterCrop;
}
@Override
public int hashCode() {
return ID.hashCode();
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
messageDigest.update(ID_BYTES);
}
}
要同时有centerCrop效果与圆角效果,就基于这个类修改就行,即基于 TransformationUtils.centerCrop(pool, toTransform, outWidth, outHeight);
这段代码返回的Bitmap对象作处理。
支持dp单位,float精度
/**
* Copyright (C) 2018 Wasabeef
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.RectF;
import android.graphics.Shader;
import android.support.annotation.NonNull;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.TransformationUtils;
import java.security.MessageDigest;
import jp.wasabeef.glide.transformations.BitmapTransformation;
/**
* desc :
* author : stone
* email : [email protected]
* time : 2019/6/12 9:42
*/
public class RoundedCornersTransformation2 extends BitmapTransformation {
private static final int VERSION = 1;
private static final String ID = "jp.wasabeef.glide.transformations.RoundedCornersTransformation." + VERSION;
public enum CornerType {
ALL,
TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT,
TOP, BOTTOM, LEFT, RIGHT,
OTHER_TOP_LEFT, OTHER_TOP_RIGHT, OTHER_BOTTOM_LEFT, OTHER_BOTTOM_RIGHT,
DIAGONAL_FROM_TOP_LEFT, DIAGONAL_FROM_TOP_RIGHT
}
public enum ScaleType {
FIT_CENTER, CENTER_CROP, CENTER_INSIDE
}
private float radius;
private float diameter;
private float margin;
private CornerType cornerType;
private ScaleType scaleType;
public RoundedCornersTransformation2(int dpRadius, int marginDp) {
this(dpRadius, marginDp, CornerType.ALL, ScaleType.FIT_CENTER);
}
public RoundedCornersTransformation2(int dpRadius, int marginDp, CornerType cornerType, ScaleType scaleType) {
this.radius = Resources.getSystem().getDisplayMetrics().density * dpRadius;
this.diameter = this.radius * 2;
this.margin = Resources.getSystem().getDisplayMetrics().density * marginDp;
this.cornerType = cornerType;
this.scaleType = scaleType;
}
@Override
protected Bitmap transform(@NonNull Context context, @NonNull BitmapPool pool,
@NonNull Bitmap toTransform, int outWidth, int outHeight) {
Bitmap bitmap;
switch (scaleType) {
case CENTER_CROP:
bitmap = TransformationUtils.centerCrop(pool, toTransform, outWidth, outHeight);
break;
case CENTER_INSIDE:
bitmap = TransformationUtils.centerInside(pool, toTransform, outWidth, outHeight);
break;
case FIT_CENTER:
default:
bitmap = TransformationUtils.fitCenter(pool, toTransform, outWidth, outHeight);
break;
}
return roundCrop(pool, bitmap);
}
private Bitmap roundCrop(BitmapPool pool, Bitmap source) {
if (source == null) return null;
Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
result.setHasAlpha(true);
Canvas canvas = new Canvas(result);
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
drawRoundRect(canvas, paint, source.getWidth(), source.getHeight());
return result;
}
private void drawRoundRect(Canvas canvas, Paint paint, float width, float height) {
float right = width - margin;
float bottom = height - margin;
switch (cornerType) {
case ALL:
canvas.drawRoundRect(new RectF(margin, margin, right, bottom), radius, radius, paint);
break;
case TOP_LEFT:
drawTopLeftRoundRect(canvas, paint, right, bottom);
break;
case TOP_RIGHT:
drawTopRightRoundRect(canvas, paint, right, bottom);
break;
case BOTTOM_LEFT:
drawBottomLeftRoundRect(canvas, paint, right, bottom);
break;
case BOTTOM_RIGHT:
drawBottomRightRoundRect(canvas, paint, right, bottom);
break;
case TOP:
drawTopRoundRect(canvas, paint, right, bottom);
break;
case BOTTOM:
drawBottomRoundRect(canvas, paint, right, bottom);
break;
case LEFT:
drawLeftRoundRect(canvas, paint, right, bottom);
break;
case RIGHT:
drawRightRoundRect(canvas, paint, right, bottom);
break;
case OTHER_TOP_LEFT:
drawOtherTopLeftRoundRect(canvas, paint, right, bottom);
break;
case OTHER_TOP_RIGHT:
drawOtherTopRightRoundRect(canvas, paint, right, bottom);
break;
case OTHER_BOTTOM_LEFT:
drawOtherBottomLeftRoundRect(canvas, paint, right, bottom);
break;
case OTHER_BOTTOM_RIGHT:
drawOtherBottomRightRoundRect(canvas, paint, right, bottom);
break;
case DIAGONAL_FROM_TOP_LEFT:
drawDiagonalFromTopLeftRoundRect(canvas, paint, right, bottom);
break;
case DIAGONAL_FROM_TOP_RIGHT:
drawDiagonalFromTopRightRoundRect(canvas, paint, right, bottom);
break;
default:
canvas.drawRoundRect(new RectF(margin, margin, right, bottom), radius, radius, paint);
break;
}
}
private void drawTopLeftRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
canvas.drawRoundRect(new RectF(margin, margin, margin + diameter, margin + diameter), radius,
radius, paint);
canvas.drawRect(new RectF(margin, margin + radius, margin + radius, bottom), paint);
canvas.drawRect(new RectF(margin + radius, margin, right, bottom), paint);
}
private void drawTopRightRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
canvas.drawRoundRect(new RectF(right - diameter, margin, right, margin + diameter), radius,
radius, paint);
canvas.drawRect(new RectF(margin, margin, right - radius, bottom), paint);
canvas.drawRect(new RectF(right - radius, margin + radius, right, bottom), paint);
}
private void drawBottomLeftRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
canvas.drawRoundRect(new RectF(margin, bottom - diameter, margin + diameter, bottom), radius,
radius, paint);
canvas.drawRect(new RectF(margin, margin, margin + diameter, bottom - radius), paint);
canvas.drawRect(new RectF(margin + radius, margin, right, bottom), paint);
}
private void drawBottomRightRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
canvas.drawRoundRect(new RectF(right - diameter, bottom - diameter, right, bottom), radius,
radius, paint);
canvas.drawRect(new RectF(margin, margin, right - radius, bottom), paint);
canvas.drawRect(new RectF(right - radius, margin, right, bottom - radius), paint);
}
private void drawTopRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
canvas.drawRoundRect(new RectF(margin, margin, right, margin + diameter), radius, radius,
paint);
canvas.drawRect(new RectF(margin, margin + radius, right, bottom), paint);
}
private void drawBottomRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
canvas.drawRoundRect(new RectF(margin, bottom - diameter, right, bottom), radius, radius,
paint);
canvas.drawRect(new RectF(margin, margin, right, bottom - radius), paint);
}
private void drawLeftRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
canvas.drawRoundRect(new RectF(margin, margin, margin + diameter, bottom), radius, radius,
paint);
canvas.drawRect(new RectF(margin + radius, margin, right, bottom), paint);
}
private void drawRightRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
canvas.drawRoundRect(new RectF(right - diameter, margin, right, bottom), radius, radius, paint);
canvas.drawRect(new RectF(margin, margin, right - radius, bottom), paint);
}
private void drawOtherTopLeftRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
canvas.drawRoundRect(new RectF(margin, bottom - diameter, right, bottom), radius, radius,
paint);
canvas.drawRoundRect(new RectF(right - diameter, margin, right, bottom), radius, radius, paint);
canvas.drawRect(new RectF(margin, margin, right - radius, bottom - radius), paint);
}
private void drawOtherTopRightRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
canvas.drawRoundRect(new RectF(margin, margin, margin + diameter, bottom), radius, radius,
paint);
canvas.drawRoundRect(new RectF(margin, bottom - diameter, right, bottom), radius, radius,
paint);
canvas.drawRect(new RectF(margin + radius, margin, right, bottom - radius), paint);
}
private void drawOtherBottomLeftRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
canvas.drawRoundRect(new RectF(margin, margin, right, margin + diameter), radius, radius,
paint);
canvas.drawRoundRect(new RectF(right - diameter, margin, right, bottom), radius, radius, paint);
canvas.drawRect(new RectF(margin, margin + radius, right - radius, bottom), paint);
}
private void drawOtherBottomRightRoundRect(Canvas canvas, Paint paint, float right,
float bottom) {
canvas.drawRoundRect(new RectF(margin, margin, right, margin + diameter), radius, radius,
paint);
canvas.drawRoundRect(new RectF(margin, margin, margin + diameter, bottom), radius, radius,
paint);
canvas.drawRect(new RectF(margin + radius, margin + radius, right, bottom), paint);
}
private void drawDiagonalFromTopLeftRoundRect(Canvas canvas, Paint paint, float right,
float bottom) {
canvas.drawRoundRect(new RectF(margin, margin, margin + diameter, margin + diameter), radius,
radius, paint);
canvas.drawRoundRect(new RectF(right - diameter, bottom - diameter, right, bottom), radius,
radius, paint);
canvas.drawRect(new RectF(margin, margin + radius, right - diameter, bottom), paint);
canvas.drawRect(new RectF(margin + diameter, margin, right, bottom - radius), paint);
}
private void drawDiagonalFromTopRightRoundRect(Canvas canvas, Paint paint, float right,
float bottom) {
canvas.drawRoundRect(new RectF(right - diameter, margin, right, margin + diameter), radius,
radius, paint);
canvas.drawRoundRect(new RectF(margin, bottom - diameter, margin + diameter, bottom), radius,
radius, paint);
canvas.drawRect(new RectF(margin, margin, right - radius, bottom - radius), paint);
canvas.drawRect(new RectF(margin + radius, margin + radius, right, bottom), paint);
}
@NonNull
@Override
public String toString() {
return "RoundedTransformation(radius=" + radius + ", margin=" + margin + ", diameter="
+ diameter + ", cornerType=" + cornerType.name() + ")";
}
@Override
public boolean equals(Object o) {
return o instanceof RoundedCornersTransformation2 &&
((RoundedCornersTransformation2) o).radius == radius &&
((RoundedCornersTransformation2) o).diameter == diameter &&
((RoundedCornersTransformation2) o).margin == margin &&
((RoundedCornersTransformation2) o).cornerType == cornerType;
}
@Override
public int hashCode() {
return (int) (ID.hashCode() + radius * 10000 + diameter * 1000 + margin * 100 + cornerType.ordinal() * 10);
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
messageDigest.update((ID + radius + diameter + margin + cornerType).getBytes(CHARSET));
}
}
调用方式
Glide
.with(...)
...
.transform(new RoundedCornersTransformation2(dpRadius, margin, cornerType, scaleType))
.into(...);
这里继承的是 glide-transformations项目中的 BitmapTransformation,而不是glide中的。继承glide中的也是可以的。
上面绘制圆角时,分了很多type,不同type分别绘制。代码量很长。
参考了一个文章,改成如下:
public class RoundedCornersTransformation extends BitmapTransformation {
private static final int VERSION = 1;
//这个ID值 随意
private static final String ID = "jp.wasabeef.glide.transformations.RoundedCornersTransformation." + VERSION;
public static final int CORNER_NONE = 0;
public static final int CORNER_TOP_LEFT = 1;
public static final int CORNER_TOP_RIGHT = 1 << 1;
public static final int CORNER_BOTTOM_LEFT = 1 << 2;
public static final int CORNER_BOTTOM_RIGHT = 1 << 3;
public static final int CORNER_ALL = CORNER_TOP_LEFT | CORNER_TOP_RIGHT | CORNER_BOTTOM_LEFT | CORNER_BOTTOM_RIGHT;
public static final int CORNER_TOP = CORNER_TOP_LEFT | CORNER_TOP_RIGHT;
public static final int CORNER_BOTTOM = CORNER_BOTTOM_LEFT | CORNER_BOTTOM_RIGHT;
public static final int CORNER_LEFT = CORNER_TOP_LEFT | CORNER_BOTTOM_LEFT;
public static final int CORNER_RIGHT = CORNER_TOP_RIGHT | CORNER_BOTTOM_RIGHT;
public static final int FIT_CENTER = 1;
public static final int CENTER_CROP = 2;
public static final int CENTER_INSIDE = 3;
@IntDef({FIT_CENTER, CENTER_CROP, CENTER_INSIDE})
public @interface ScaleType {}
private float radius;
private float diameter;
private float margin;
private int cornerType;
private @ScaleType int scaleType;
public RoundedCornersTransformation(int dpRadius, int marginDp) {
this(dpRadius, marginDp, CORNER_ALL, FIT_CENTER);
}
public RoundedCornersTransformation(int dpRadius, int marginDp, int cornerType, @ScaleType int scaleType) {
this.radius = Resources.getSystem().getDisplayMetrics().density * dpRadius;
this.diameter = this.radius * 2;
this.margin = Resources.getSystem().getDisplayMetrics().density * marginDp;
this.cornerType = cornerType;
this.scaleType = scaleType;
}
@Override
protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
Bitmap bitmap;
switch (scaleType) {
case CENTER_CROP:
bitmap = TransformationUtils.centerCrop(pool, toTransform, outWidth, outHeight);
break;
case CENTER_INSIDE:
bitmap = TransformationUtils.centerInside(pool, toTransform, outWidth, outHeight);
break;
case FIT_CENTER:
default:
bitmap = TransformationUtils.fitCenter(pool, toTransform, outWidth, outHeight);
break;
}
return roundCrop(pool, bitmap);
}
private Bitmap roundCrop(BitmapPool pool, Bitmap source) {
if (source == null) return null;
Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
result.setHasAlpha(true);
Canvas canvas = new Canvas(result);
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
drawRoundRect(canvas, paint, source.getWidth(), source.getHeight());
return result;
}
private void drawRoundRect(Canvas canvas, Paint paint, float width, float height) {
float right = width - margin;
float bottom = height - margin;
canvas.drawRoundRect(new RectF(margin, margin, right, bottom), radius, radius, paint);
//把不需要的圆角去掉
int notRoundedCorners = cornerType ^ CORNER_ALL;
if ((notRoundedCorners & CORNER_TOP_LEFT) != 0) {
clipTopLeft(canvas, paint, radius);
}
if ((notRoundedCorners & CORNER_TOP_RIGHT) != 0) {
clipTopRight(canvas, paint, radius, right);
}
if ((notRoundedCorners & CORNER_BOTTOM_LEFT) != 0) {
clipBottomLeft(canvas, paint, radius, bottom);
}
if ((notRoundedCorners & CORNER_BOTTOM_RIGHT) != 0) {
clipBottomRight(canvas, paint, radius, right, bottom);
}
}
private static void clipTopLeft(final Canvas canvas, final Paint paint, float offset) {
final RectF block = new RectF(0, 0, offset, offset);
canvas.drawRect(block, paint);
}
private static void clipTopRight(final Canvas canvas, final Paint paint, float offset, float width) {
final RectF block = new RectF(width - offset, 0, width, offset);
canvas.drawRect(block, paint);
}
private static void clipBottomLeft(final Canvas canvas, final Paint paint, float offset, float height) {
final RectF block = new RectF(0, height - offset, offset, height);
canvas.drawRect(block, paint);
}
private static void clipBottomRight(final Canvas canvas, final Paint paint, float offset, float width, float height) {
final RectF block = new RectF(width - offset, height - offset, width, height);
canvas.drawRect(block, paint);
}
@NonNull
@Override
public String toString() {
return "RoundedTransformation(radius=" + radius + ", margin=" + margin + ", diameter="
+ diameter + ", cornerType=" + cornerType + ")";
}
@Override
public boolean equals(Object o) {
return o instanceof RoundedCornersTransformation &&
((RoundedCornersTransformation) o).radius == radius &&
((RoundedCornersTransformation) o).diameter == diameter &&
((RoundedCornersTransformation) o).margin == margin &&
((RoundedCornersTransformation) o).cornerType == cornerType;
}
@Override
public int hashCode() {
return (int) (ID.hashCode() + radius * 10000 + diameter * 1000 + margin * 100 + cornerType * 10);
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
messageDigest.update((ID + radius + diameter + margin + cornerType).getBytes(CHARSET));
}
}
先绘一个全圆角,再根据条件绘制 某几的个角小矩形,以覆盖圆角效果
由于transform变换操作,会影响glide的图片缓存。glide文档中是要求重写 equals、hashCode、updateDiskCacheKey这三个方法的。
在调试时,若对同一图片,一会设置左圆角,一会设置右圆角,类似这样,可能就会造成后设置的看不到效果,看到还是之前的设置的效果。这是由于 glide缓存造成的。这时重装项目就可以了。
android中对Bitmap图片设置任意角为圆角
glide-transformations