在Android中,ImageView默认是一个矩形。如何使它成为一个圆角矩形(剪辑我的位图的所有4个角为圆角矩形)在ImageView?
请注意,从2021年起,只需使用ShapeableImageView
在Android中,ImageView默认是一个矩形。如何使它成为一个圆角矩形(剪辑我的位图的所有4个角为圆角矩形)在ImageView?
请注意,从2021年起,只需使用ShapeableImageView
当前回答
我建议在这种情况下使用Coil库
Coil是Kotlin-first,使用现代库,包括Coroutines, OkHttp, Okio和AndroidX Lifecycles。
github链接
其他回答
对于上面提到的乔治·沃尔特斯二世,我只是把他的答案扩展了一下,以支持不同的圆角。这可以进一步优化(一些目标矩形重叠),但不是很多。
我知道这个线程有点老了,但它是谷歌上关于如何在Android上圆角ImageViews的查询的顶级结果之一。
/**
* Use this method to scale a bitmap and give it specific rounded corners.
* @param context Context object used to ascertain display density.
* @param bitmap The original bitmap that will be scaled and have rounded corners applied to it.
* @param upperLeft Corner radius for upper left.
* @param upperRight Corner radius for upper right.
* @param lowerRight Corner radius for lower right.
* @param lowerLeft Corner radius for lower left.
* @param endWidth Width to which to scale original bitmap.
* @param endHeight Height to which to scale original bitmap.
* @return Scaled bitmap with rounded corners.
*/
public static Bitmap getRoundedCornerBitmap(Context context, Bitmap bitmap, float upperLeft,
float upperRight, float lowerRight, float lowerLeft, int endWidth,
int endHeight) {
float densityMultiplier = context.getResources().getDisplayMetrics().density;
// scale incoming bitmap to appropriate px size given arguments and display dpi
bitmap = Bitmap.createScaledBitmap(bitmap,
Math.round(endWidth * densityMultiplier),
Math.round(endHeight * densityMultiplier), true);
// create empty bitmap for drawing
Bitmap output = Bitmap.createBitmap(
Math.round(endWidth * densityMultiplier),
Math.round(endHeight * densityMultiplier), Config.ARGB_8888);
// get canvas for empty bitmap
Canvas canvas = new Canvas(output);
int width = canvas.getWidth();
int height = canvas.getHeight();
// scale the rounded corners appropriately given dpi
upperLeft *= densityMultiplier;
upperRight *= densityMultiplier;
lowerRight *= densityMultiplier;
lowerLeft *= densityMultiplier;
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
// fill the canvas with transparency
canvas.drawARGB(0, 0, 0, 0);
// draw the rounded corners around the image rect. clockwise, starting in upper left.
canvas.drawCircle(upperLeft, upperLeft, upperLeft, paint);
canvas.drawCircle(width - upperRight, upperRight, upperRight, paint);
canvas.drawCircle(width - lowerRight, height - lowerRight, lowerRight, paint);
canvas.drawCircle(lowerLeft, height - lowerLeft, lowerLeft, paint);
// fill in all the gaps between circles. clockwise, starting at top.
RectF rectT = new RectF(upperLeft, 0, width - upperRight, height / 2);
RectF rectR = new RectF(width / 2, upperRight, width, height - lowerRight);
RectF rectB = new RectF(lowerLeft, height / 2, width - lowerRight, height);
RectF rectL = new RectF(0, upperLeft, width / 2, height - lowerLeft);
canvas.drawRect(rectT, paint);
canvas.drawRect(rectR, paint);
canvas.drawRect(rectB, paint);
canvas.drawRect(rectL, paint);
// set up the rect for the image
Rect imageRect = new Rect(0, 0, width, height);
// set up paint object such that it only paints on Color.WHITE
paint.setXfermode(new AvoidXfermode(Color.WHITE, 255, AvoidXfermode.Mode.TARGET));
// draw resized bitmap onto imageRect in canvas, using paint as configured above
canvas.drawBitmap(bitmap, imageRect, imageRect, paint);
return output;
}
下面是一个覆盖imageView的简单示例,然后你也可以在布局设计器中使用它来预览。
public class RoundedImageView extends ImageView {
public RoundedImageView(Context context) {
super(context);
}
public RoundedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void setImageDrawable(Drawable drawable) {
float radius = 0.1f;
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
RoundedBitmapDrawable rid = RoundedBitmapDrawableFactory.create(getResources(), bitmap);
rid.setCornerRadius(bitmap.getWidth() * radius);
super.setImageDrawable(rid);
}
}
这是为了快速解决问题。半径用于所有角落,并基于位图宽度的百分比。
我只是覆盖了setImageDrawable,并使用支持v4方法绘制圆角位图。
用法:
<com.example.widgets.RoundedImageView
android:layout_width="39dp"
android:layout_height="39dp"
android:src="@drawable/your_drawable" />
使用imageView和自定义imageView预览:
虽然上面的答案是可行的,Romain Guy(核心Android开发人员)在他的博客中展示了一个更好的方法,通过使用着色器而不是创建位图的副本来使用更少的内存。该功能的一般要点如下:
BitmapShader shader;
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
RectF rect = new RectF(0.0f, 0.0f, width, height);
// rect contains the bounds of the shape
// radius is the radius in pixels of the rounded corners
// paint contains the shader that will texture the shape
canvas.drawRoundRect(rect, radius, radius, paint);
与其他方法相比,这种方法的优点是:
不创建一个单独的位图副本,对于大图像使用大量内存[相对于这里的大多数其他答案] 支持反锯齿[vs clipPath方法] 支持alpha [vs xfermode+porterduff方法] 支持硬件加速[vs clipPath方法] 只在画布上绘制一次[相对于xfermode和clippath方法]
我创建了一个基于这段代码的RoundedImageView,它将这个逻辑包装到一个ImageView中,并添加了适当的ScaleType支持和可选的圆角边框。
你可以在你的布局中只使用ImageView,使用滑动,你可以使用这个方法应用圆角。
首先在你的gradle里写上,
compile 'com.github.bumptech.glide:glide:3.7.0'
对于有圆角的图像,
public void loadImageWithCorners(String url, ImageView view) {
Glide.with(context)
.load(url)
.asBitmap()
.centerCrop()
.placeholder(R.color.gray)
.error(R.color.gray)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(new BitmapImageViewTarget(view) {
@Override
protected void setResource(Bitmap resource) {
RoundedBitmapDrawable circularBitmapDrawable =
RoundedBitmapDrawableFactory.create(context.getResources(), resource);
circularBitmapDrawable.setCornerRadius(32.0f); // radius for corners
view.setImageDrawable(circularBitmapDrawable);
}
});
}
调用方法:
loadImageWithCorners("your url","your imageview");
多亏了melanke,你可以使用一个自定义类并创建一个自定义循环ImageView。
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
public class MLRoundedImageView extends android.support.v7.widget.AppCompatImageView {
public MLRoundedImageView(Context context) {
super(context);
}
public MLRoundedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MLRoundedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
int w = getWidth(), h = getHeight();
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
Bitmap sbmp;
if (bmp.getWidth() != radius || bmp.getHeight() != radius) {
float smallest = Math.min(bmp.getWidth(), bmp.getHeight());
float factor = smallest / radius;
sbmp = Bitmap.createScaledBitmap(bmp, (int)(bmp.getWidth() / factor), (int)(bmp.getHeight() / factor), false);
} else {
sbmp = bmp;
}
Bitmap output = Bitmap.createBitmap(radius, radius,
Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xffa19774;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, radius, radius);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(radius / 2 + 0.7f,
radius / 2 + 0.7f, radius / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
}
然后在XML中使用它:
<your.package.name.MLRoundedImageView
..
/>
源