在Android中,ImageView默认是一个矩形。如何使它成为一个圆角矩形(剪辑我的位图的所有4个角为圆角矩形)在ImageView?
请注意,从2021年起,只需使用ShapeableImageView
在Android中,ImageView默认是一个矩形。如何使它成为一个圆角矩形(剪辑我的位图的所有4个角为圆角矩形)在ImageView?
请注意,从2021年起,只需使用ShapeableImageView
当前回答
这不是确切的答案,但它是一个类似的解决方案。它可能会帮助那些和我有同样遭遇的人。
我的图像是一个应用程序logo,它的背景是透明的,我正在应用XML渐变作为图像背景。我在imageView中添加了必要的padding/margin,然后添加了这个作为我的背景:
<?xml version="1.0" encoding="utf-8"?>
<!-- This file defines the gradient used on the background of the main activity. -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<gradient
android:type="linear"
android:startColor="@color/app_color_light_background"
android:endColor="@color/app_color_disabled"
android:angle="90" />
<!-- Round the top corners. -->
<corners
android:topLeftRadius="@dimen/radius_small"
android:topRightRadius="@dimen/radius_small" />
</shape>
</item>
</selector>
其他回答
我知道这个问题已经过时了,但这里有另一种更简单的四舍五入图像的方法:
这是一种编程方法。
创造你的空白……
} public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) { Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output); final int color = 0xff424242;
final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels; paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0); paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint); return output;
加载图像,然后设置圆角
imageview1.setImageResource(R.drawable.yourimage);
Bitmap bm = ((android.graphics.drawable.BitmapDrawable) imageview1.getDrawable()).getBitmap();
imageview1.setImageBitmap(getRoundedCornerBitmap(bm, 30));
以30为半径,你会得到这样的结果:
不管我的图像看起来如何,它只是一个放大的小图标
如果你不希望边框影响图像,使用这个类。不幸的是,我没有找到任何方法来绘制画布上的透明区域来到onDraw()。这里创建了一个新的位图它是画在一个真实的画布上的。
如果您想要创建一个消失的边界,该视图非常有用。如果你将borderWidth设置为0,边框将会消失,图像仍然保持圆角,就像边界一样。也就是说,它看起来就像边界完全由图像边缘绘制。
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.graphics.RectF
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatImageView
class RoundedImageViewWithBorder @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0) : AppCompatImageView(context, attrs, defStyleAttr) {
var borderColor: Int = 0
set(value) {
invalidate()
field = value
}
var borderWidth: Int = 0
set(value) {
invalidate()
field = value
}
var cornerRadius: Float = 0f
set(value) {
invalidate()
field = value
}
private var bitmapForDraw: Bitmap? = null
private var canvasForDraw: Canvas? = null
private val transparentPaint = Paint().apply {
isAntiAlias = true
color = Color.TRANSPARENT
style = Paint.Style.STROKE
xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC)
}
private val borderPaint = Paint().apply {
isAntiAlias = true
style = Paint.Style.STROKE
}
private val transparentAreaRect = RectF()
private val borderRect = RectF()
init {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundedImageViewWithBorder)
try {
borderWidth = typedArray.getDimensionPixelSize(R.styleable.RoundedImageViewWithBorder_border_width, 0)
borderColor = typedArray.getColor(R.styleable.RoundedImageViewWithBorder_border_color, 0)
cornerRadius = typedArray.getDimensionPixelSize(R.styleable.RoundedImageViewWithBorder_corner_radius, 0).toFloat()
} finally {
typedArray.recycle()
}
}
@SuppressLint("CanvasSize", "DrawAllocation")
override fun onDraw(canvas: Canvas) {
if (canvas.height <=0 || canvas.width <=0) {
return
}
if (canvasForDraw?.height != canvas.height || canvasForDraw?.width != canvas.width) {
val newBitmap = Bitmap.createBitmap(canvas.width, canvas.height, Bitmap.Config.ARGB_8888)
bitmapForDraw = newBitmap
canvasForDraw = Canvas(newBitmap)
}
bitmapForDraw?.eraseColor(Color.TRANSPARENT)
// Draw existing content
super.onDraw(canvasForDraw)
if (borderWidth > 0) {
canvasForDraw?.let { drawWithBorder(it) }
} else {
canvasForDraw?.let { drawWithoutBorder(it) }
}
// Draw everything on real canvas
bitmapForDraw?.let { canvas.drawBitmap(it, 0f, 0f, null) }
}
private fun drawWithBorder(canvas: Canvas) {
// Draw transparent area
transparentPaint.strokeWidth = borderWidth.toFloat() * 4
transparentAreaRect.apply {
left = -borderWidth.toFloat() * 1.5f
top = -borderWidth.toFloat() * 1.5f
right = canvas.width.toFloat() + borderWidth.toFloat() * 1.5f
bottom = canvas.height.toFloat() + borderWidth.toFloat() * 1.5f
}
canvasForDraw?.drawRoundRect(transparentAreaRect, borderWidth.toFloat() * 2 + cornerRadius, borderWidth.toFloat() * 2 + cornerRadius, transparentPaint)
// Draw border
borderPaint.color = borderColor
borderPaint.strokeWidth = borderWidth.toFloat()
borderRect.apply {
left = borderWidth.toFloat() / 2
top = borderWidth.toFloat() / 2
right = canvas.width.toFloat() - borderWidth.toFloat() / 2
bottom = canvas.height.toFloat() - borderWidth.toFloat() / 2
}
canvas.drawRoundRect(borderRect, cornerRadius - borderWidth.toFloat() / 2, cornerRadius - borderWidth.toFloat() / 2, borderPaint)
}
private fun drawWithoutBorder(canvas: Canvas) {
// Draw transparent area
transparentPaint.strokeWidth = cornerRadius * 4
transparentAreaRect.apply {
left = -cornerRadius * 2
top = -cornerRadius * 2
right = canvas.width.toFloat() + cornerRadius * 2
bottom = canvas.height.toFloat() + cornerRadius * 2
}
canvasForDraw?.drawRoundRect(transparentAreaRect, cornerRadius * 3, cornerRadius * 3, transparentPaint)
}
}
值:
<declare-styleable name="RoundedImageViewWithBorder">
<attr name="corner_radius" format="dimension|string" />
<attr name="border_width" format="dimension|reference" />
<attr name="border_color" format="color|reference" />
</declare-styleable>
我使用了一个自定义视图,我在其他视图的顶部布局,它只是画了4个小倒角,颜色与背景相同。
优点:
不分配位图。 适用于任何你想要应用圆角的视图。 适用于所有API级别;)
代码:
public class RoundedCornersView extends View {
private float mRadius;
private int mColor = Color.WHITE;
private Paint mPaint;
private Path mPath;
public RoundedCornersView(Context context) {
super(context);
init();
}
public RoundedCornersView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.RoundedCornersView,
0, 0);
try {
setRadius(a.getDimension(R.styleable.RoundedCornersView_radius, 0));
setColor(a.getColor(R.styleable.RoundedCornersView_cornersColor, Color.WHITE));
} finally {
a.recycle();
}
}
private void init() {
setColor(mColor);
setRadius(mRadius);
}
private void setColor(int color) {
mColor = color;
mPaint = new Paint();
mPaint.setColor(mColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
invalidate();
}
private void setRadius(float radius) {
mRadius = radius;
RectF r = new RectF(0, 0, 2 * mRadius, 2 * mRadius);
mPath = new Path();
mPath.moveTo(0,0);
mPath.lineTo(0, mRadius);
mPath.arcTo(r, 180, 90);
mPath.lineTo(0,0);
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
/*This just draws 4 little inverted corners */
int w = getWidth();
int h = getHeight();
canvas.drawPath(mPath, mPaint);
canvas.save();
canvas.translate(w, 0);
canvas.rotate(90);
canvas.drawPath(mPath, mPaint);
canvas.restore();
canvas.save();
canvas.translate(w, h);
canvas.rotate(180);
canvas.drawPath(mPath, mPaint);
canvas.restore();
canvas.translate(0, h);
canvas.rotate(270);
canvas.drawPath(mPath, mPaint);
}
}
下面是一个覆盖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预览:
我使用路径在图像画布上只画角。(我需要没有位图内存分配的解决方案)
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
if (!hasRoundedCorners()) return;
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(0);
Path path = new Path();
path.setFillType(Path.FillType.INVERSE_WINDING);
path.addRoundRect(new RectF(0, 0, getWidth(), getHeight()), mRadius, mRadius, Path.Direction.CCW);
canvas.drawPath(path, mPaint);
}
注意,你不应该在onDraw方法中分配任何新对象。此代码是概念验证,不应该在产品代码中这样使用
看到更多: https://medium.com/@przemek.materna/rounded-image-view-no-bitmap-reallocation-11a8b163484d