在Android中,ImageView默认是一个矩形。如何使它成为一个圆角矩形(剪辑我的位图的所有4个角为圆角矩形)在ImageView?


请注意,从2021年起,只需使用ShapeableImageView


当前回答

最近,还有另一种方法——使用Glide的生成API。它需要一些初始的工作,但它给了你Glide所有的力量,以及做任何事情的灵活性,因为你重写了实际的代码,所以我认为从长远来看,这是一个很好的解决方案。另外,使用非常简单和整洁。

首先,设置Glide版本4+:

implementation 'com.github.bumptech.glide:glide:4.6.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1'

然后创建Glid的app模块类来触发注释处理:

@GlideModule
public final class MyAppGlideModule extends AppGlideModule {}

然后创建实际工作的Glide扩展。你可以自定义它来做任何你想做的事情:

@GlideExtension
public class MyGlideExtension {

    private MyGlideExtension() {}

    @NonNull
    @GlideOption
    public static RequestOptions roundedCorners(RequestOptions options, @NonNull Context context, int cornerRadius) {
        int px = Math.round(cornerRadius * (context.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
        return options.transforms(new RoundedCorners(px));
    }
}

添加这些文件之后,构建您的项目。

然后像这样在你的代码中使用它:

GlideApp.with(this)
        .load(imageUrl)
        .roundedCorners(getApplicationContext(), 5)
        .into(imageView);

其他回答

试试这个

Bitmap finalBitmap;
        if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
            finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
                    false);
        else
            finalBitmap = bitmap;
        Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
                finalBitmap.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
                finalBitmap.getHeight());

        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(Color.parseColor("#BAB399"));
        canvas.drawCircle(finalBitmap.getWidth() / 2 + 0.7f,
                finalBitmap.getHeight() / 2 + 0.7f,
                finalBitmap.getWidth() / 2 + 0.1f, paint);
        paint.setXfermode(new PorterDuffXfermode(
                android.graphics.PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(finalBitmap, rect, rect, paint);

        return output;

我认为最简单的解决方法是这样的:-

步骤1 -创建一个形状绘图文件如下所示

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <solid android:color="@color/white" />

    <corners android:radius="@dimen/dimen_10dp" />

    <stroke
        android:width="1dp"
        android:color="@color/white" />
</shape>

步骤2 -在代码中使用上述绘图。

Drawable drawable = ContextCompat.getDrawable(mActivity, R.drawable.photos_round_shape);
            drawable.mutate().setColorFilter(randomColor, PorterDuff.Mode.SRC_ATOP);
            imageView.setBackground(drawable);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
               imageView.setClipToOutline(true);
            }

Glide.with(mContext)
                .setDefaultRequestOptions(getNoAnimationOptions())
                .load(url)
                .into(imageView);

希望这能有所帮助。

如果你们中有人面临这个问题

大多数情况下,你使用的是Android Studio。由于图像大小的调整和所有在Android工作室,你可能会遇到这个问题。解决这个问题的一个简单方法是减小drawCircle()中的圆的半径。在我的情况下,我使用这个修复

使用画布。drawCircle(100,100,90, paint);而不是帆布。drawCircle(100,100,100, paint);这绝对能解决你的问题。

下面是最终编辑的代码:-

  public class Profile extends ActionBarActivity {


    TextView username;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.profile);


        username= (TextView) findViewById(R.id.txt);

        String recievedusername=getIntent().getExtras().getString("toname");
        username.setText(recievedusername);


        Bitmap bm = BitmapFactory.decodeResource(getResources(),
                R.mipmap.gomez);

        Bitmap resizedBitmap = Bitmap.createScaledBitmap(bm, 200,200, false);
        Bitmap conv_bm=getCircleBitmap(resizedBitmap,100);
        // set circle bitmap
        ImageView mImage = (ImageView) findViewById(R.id.profile_image);
        mImage.setImageBitmap(conv_bm);
        // TODO Auto-generated method stub
    }
    private Bitmap getCircleBitmap(Bitmap bitmap , int pixels) {
        final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        final 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);
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawCircle(100,100, 90, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        bitmap.recycle();
        return output;
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_apploud, menu);
        return super.onCreateOptionsMenu(menu);
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        //noinspection SimplifiableIfStatement
        if (id == R.id.action_addnew) {
            Intent i;
            i=new Intent(Profile.this,ApplaudSomeone.class);
            startActivity(i);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

芬兰湾的科特林版:

@GlideExtension
object GamersGeekGlideExtension {

    @NonNull
    @JvmStatic
    @GlideOption
    fun roundedCorners(options: BaseRequestOptions<*>, context: Context, cornerRadius: Int): BaseRequestOptions<*> {
        val px =
            (cornerRadius * (context.resources.displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT)).roundToInt()
        return options.transforms(RoundedCorners(px))
    }
}

注意:Glide扩展现在需要BaseRequestOptions而不是RequestOptions。此外,它与@Sir Codesalot答案在kotlin中转换的函数相同。

我使用路径在图像画布上只画角。(我需要没有位图内存分配的解决方案)

@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