首先致謝:https://blog.csdn.net/flyinbed_/article/details/75506062
咱們不是代碼的生產者,只是代碼的搬運工。
最近有個工作中有個需求就是展示的圖片必須圓角、正方形,當時一想這太尼瑪簡單了,無非就是設置一個圖片參數的大小,然后在設置一個centerCrop的屬性,在自定義一個類去繼承BitmapTransformation重畫一下。
結果寫的時候發現,在glide4.0上面 centerCrop和圓角圖片有沖突只能顯示一個,結果就度娘問了一邊,大部分都是下面這行代碼,發現這個在glide4.0上面直接報錯 無法使用,最后沒辦法了只能自己擼一遍源碼看看了。
transform(new CenterCrop(getActivity()),new GlideRoundImage(getActivity()))
點開centerCrop的源碼
/** * Applies {@link CenterCrop} to all default types and * throws an exception if asked to transform an unknown type. * * <p>this will override previous calls to {@link #dontTransform()} ()}. * * @see #transform(Class, Transformation) * @see #optionalCenterCrop() */ public RequestOptions centerCrop() { return transform(DownsampleStrategy.CENTER_OUTSIDE, new CenterCrop()); }
原來這犢子也是調用的 transform的方法,在點開 new Centercrop()這個方法看看里面的實現
/** * Scale the image so that either the width of the image matches the given width and the height of * the image is greater than the given height or vice versa, and then crop the larger dimension to * match the given dimension. * * Does not maintain the image's aspect ratio */ 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); public CenterCrop() { // Intentionally empty. } @Deprecated public CenterCrop(@SuppressWarnings("unused") Context context) { this(); } @Deprecated public CenterCrop(@SuppressWarnings("unused") BitmapPool bitmapPool) { this(); } // Bitmap doesn't implement equals, so == and .equals are equivalent here. @SuppressWarnings("PMD.CompareObjectsWithEquals") @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(MessageDigest messageDigest) { messageDigest.update(ID_BYTES); } }
不出所料 這里面也是繼承了BitmapTransformation這個類然后重畫了一邊,后面我們自己有調用了transform()這個方法等於把系統的Centercrop這個方法給覆蓋了,所以說這兩個屬性誰在后面就用哪種效果,但是現在的問題是我想兩個都要用咋整,那么問題來了,這下只能在自己自定義的BitmapTransformation將兩個效果一起畫出來了;
先是我的布局文件:很簡單就一個線性布局+3個ImageView
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.flyinbed.myapplication.MainActivity"> <ImageView android:id="@+id/icon1" android:layout_width="150dp" android:layout_height="150dp" /> <ImageView android:id="@+id/icon2" android:layout_marginTop="10dp" android:layout_width="150dp" android:layout_height="150dp" /> <ImageView android:id="@+id/icon3" android:layout_marginTop="10dp" android:layout_width="150dp" android:layout_height="150dp" /> </LinearLayout>
Activity代碼:3個Imageview加載3張本地圖片
public class MainActivity extends AppCompatActivity { private ImageView icon1,icon2,icon3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); icon1 = (ImageView) findViewById(R.id.icon1); icon2 = (ImageView) findViewById(R.id.icon2); icon3 = (ImageView) findViewById(R.id.icon3); Glide.with(this).load(R.drawable.item1).into(icon1); Glide.with(this).load(R.drawable.image2).into(icon2); Glide.with(this).load(R.drawable.image3).into(icon3); } }
效果:
先設置一下Centercrop的屬性:
題外話:glide4.0想設置圖片的屬性現在都是通過RequestOptions()這個類來實現的,然后在glide加載的時候通過
.apply()把那個類給塞進去就好了;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); icon1 = (ImageView) findViewById(R.id.icon1); icon2 = (ImageView) findViewById(R.id.icon2); icon3 = (ImageView) findViewById(R.id.icon3); RequestOptions myOptions = new RequestOptions() .centerCrop(); Glide.with(this) .load(R.drawable.item1) .apply(myOptions) .into(icon1); Glide.with(this) .load(R.drawable.image2) .apply(myOptions) .into(icon2); Glide.with(this) .load(R.drawable.image3) .apply(myOptions) .into(icon3); }
現在設置transform圓角屬性
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); icon1 = (ImageView) findViewById(R.id.icon1); icon2 = (ImageView) findViewById(R.id.icon2); icon3 = (ImageView) findViewById(R.id.icon3); RequestOptions myOptions = new RequestOptions() .centerCrop() .transform(new GlideRoundTransform(this,30)); Glide.with(this) .load(R.drawable.item1) .apply(myOptions) .into(icon1); Glide.with(this) .load(R.drawable.image2) .apply(myOptions) .into(icon2); Glide.with(this) .load(R.drawable.image3) .apply(myOptions) .into(icon3); }
很明顯把Centercrop的屬性給覆蓋了;
下面是我自定義類GlideRoundTransform()的代碼:
public class GlideRoundTransform extends BitmapTransformation { private static float radius = 0f; public GlideRoundTransform(Context context) { this(context, 4); } public GlideRoundTransform(Context context, int dp) { super(context); this.radius = Resources.getSystem().getDisplayMetrics().density * dp; } @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { return roundCrop(pool, toTransform); } private static Bitmap roundCrop(BitmapPool pool, Bitmap source) { if (source == null) return null; Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); if (result == null) { result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); } Canvas canvas = new Canvas(result); Paint paint = new Paint(); paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); paint.setAntiAlias(true); RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight()); canvas.drawRoundRect(rectF, radius, radius, paint); return result; } public String getId() { return getClass().getName() + Math.round(radius); } @Override public void updateDiskCacheKey(MessageDigest messageDigest) { } }
接下來就開始解決這個問題了,在這個自定義類當中,我們要先獲取到Centercrop()這個屬性后得到到圖片,然后在根據這個圖片在進行圓角加工然后在返回。
其實屢清楚了思路很簡單 也就是一樣代碼的事,下面是我更改以后的代碼:
public class GlideRoundTransform extends BitmapTransformation {
private static float radius = 0f;
public GlideRoundTransform(Context context) {
this(context, 4);
}
public GlideRoundTransform(Context context, int dp) {
super(context);
this.radius = Resources.getSystem().getDisplayMetrics().density * dp;
}
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
Bitmap bitmap = TransformationUtils.centerCrop(pool, toTransform, outWidth, outHeight);
return roundCrop(pool, bitmap);
}
private static Bitmap roundCrop(BitmapPool pool, Bitmap source) {
if (source == null) return null;
Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
if (result == null) {
result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(result);
Paint paint = new Paint();
paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
paint.setAntiAlias(true);
RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight());
canvas.drawRoundRect(rectF, radius, radius, paint);
return result;
}
public String getId() {
return getClass().getName() + Math.round(radius);
}
@Override
public void updateDiskCacheKey(MessageDigest messageDigest) {
}
}
在看看效果:
很完美,搞定收工,接下來是Activity的完整代碼:
public class MainActivity extends AppCompatActivity { private ImageView icon1,icon2,icon3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); icon1 = (ImageView) findViewById(R.id.icon1); icon2 = (ImageView) findViewById(R.id.icon2); icon3 = (ImageView) findViewById(R.id.icon3); //第一個是上下文,第二個是圓角的弧度 RequestOptions myOptions = new RequestOptions() .transform(new GlideRoundTransform(this,30)); Glide.with(this) .load(R.drawable.item1) .apply(myOptions) .into(icon1); Glide.with(this) .load(R.drawable.image2) .apply(myOptions) .into(icon2); Glide.with(this) .load(R.drawable.image3) .apply(myOptions) .into(icon3); } }
要是設置的效果沒用就清除下緩存,要是還不行就卸載重裝好了!!!!!
總結: 核心代碼

1 public class GlideRoundTransform extends BitmapTransformation { 2 3 private static float radius = 0f; 4 5 public GlideRoundTransform(Context context) { 6 this(context, 4); 7 } 8 9 public GlideRoundTransform(Context context, int dp) { 10 super(context); 11 this.radius = Resources.getSystem().getDisplayMetrics().density * dp; 12 } 13 14 @Override 15 protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { 16 Bitmap bitmap = TransformationUtils.centerCrop(pool, toTransform, outWidth, outHeight); 17 return roundCrop(pool, bitmap); 18 } 19 20 private static Bitmap roundCrop(BitmapPool pool, Bitmap source) { 21 if (source == null) return null; 22 23 Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); 24 if (result == null) { 25 result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888); 26 } 27 28 Canvas canvas = new Canvas(result); 29 Paint paint = new Paint(); 30 paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); 31 paint.setAntiAlias(true); 32 RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight()); 33 canvas.drawRoundRect(rectF, radius, radius, paint); 34 return result; 35 } 36 37 public String getId() { 38 return getClass().getName() + Math.round(radius); 39 } 40 41 @Override 42 public void updateDiskCacheKey(MessageDigest messageDigest) { 43 44 } 45 46 }

1 //第一個是上下文,第二個是圓角的弧度 2 RequestOptions myOptions = new RequestOptions() 3 .transform(new GlideRoundTransform(this,30)); 4 5 Glide.with(this) 6 .load(path) 7 .apply(myOptions) 8 .into(img);