【问题标题】:Bitmap in ImageView with rounded cornersImageView 中带圆角的位图
【发布时间】:2013-08-16 06:22:14
【问题描述】:

我有一个 ImageView,我想用 rounded corners 制作它。

我用这个:

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

    <stroke android:width="1dp"
            android:color="#ff000000"/>


    <corners android:radius="62px"/> 
</shape>

并将此代码设置为我的图像视图的背景。 它可以工作,但是我放在ImageView 上的 src 图像超出了边界,无法适应新的形状。

我该如何解决这个问题?

【问题讨论】:

标签: android bitmap imageview rounded-corners


【解决方案1】:

试试这个:

public class CustomImageView extends ImageView {

    public static float radius = 18.0f;  

    public CustomImageView(Context context) {
        super(context);
    }

    public CustomImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //float radius = 36.0f;  
        Path clipPath = new Path();
        RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight());
        clipPath.addRoundRect(rect, radius, radius, Path.Direction.CW);
        canvas.clipPath(clipPath);
        super.onDraw(canvas);
    }
}

<your.pack.name.CustomImageView
                android:id="@+id/selectIcon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:scaleType="centerCrop" />

CustomImageView  iconImage = (CustomImageView )findViewById(R.id.selectIcon);
iconImage.setImageBitmap(bitmap);

或者,

ImageView iv= new CustomImageView(this);
iv.setImageResource(R.drawable.pic);

【讨论】:

  • 谢谢@Anand 分享这个,但我没有得到圆的锋利边缘,请!指导我图像尺寸的半径是 40X40 dp。
  • 请注意,通常您不应在绘制或布局方法期间进行对象分配。将这些分配移动到视图对象的其他部分相当简单。
  • @Salim,有没有办法只设置左上角?
  • 对我来说最好的解决方案。简单而聪明。
  • 嗯.. 但是你应该知道路径裁剪不支持抗锯齿。请参阅 Romain Guy 在他的帖子上的 cmets。 “路径裁剪不支持抗锯齿,你会得到锯齿状的边缘。” curious-creature.com/2012/12/11/…
【解决方案2】:

奇怪的是这里没有人提到 Android 支持库 v4 中的RoundedBitmapDrawable。对我来说,这是获得无边界圆角的最简单方法。以下是使用示例:

RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(), bitmap);
final float roundPx = (float) bitmap.getWidth() * 0.06f;
roundedBitmapDrawable.setCornerRadius(roundPx);

【讨论】:

  • 我有一个问题...设置角半径会导致更改图像的位置!自己试试:设置RoundedBitmapDrawable 的边界 > 查看结果而不设置角半径。现在设置圆角半径并再次查看结果!
  • 如此简单和完整
  • 值得注意的是,您不能使用此可绘制对象的位图进行进一步处理,因为它不是四舍五入的。
  • 终于!所有其他解决方案都不允许我有一个圆形按钮,它也有一个圆形背景。
【解决方案3】:

使用画布制作一个使位图四舍五入的函数。

public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
    Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
            .getHeight(), 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(Mode.SRC_IN));
    canvas.drawBitmap(bitmap, rect, rect, paint);

    return output;
}

更多信息:> here

【讨论】:

  • 这很好! (如果它似乎不适合您,请务必大大增加像素数)
  • 我正在画布上绘制位图和阴影,为了使阴影变圆,这是我的步骤,mPaint.setShadowLayer(radius, dX, dY, shadowColor);canvas.drawRoundRect(rect, cornerRadius, cornerRadius, mPaint); 并使用您的代码使位图角变圆,但 shadowbitmap 角不同从一个到另一个,我该怎么办?
【解决方案4】:

接受的答案使用路径裁剪,但不支持抗锯齿。请参阅 Romain Guy 在他的帖子上的 cmets。 “路径裁剪不支持抗锯齿,你会得到锯齿状的边缘。”

http://www.curious-creature.com/2012/12/11/android-recipe-1-image-with-rounded-corners/

有一个很好的库(vinc3m1 的 RoundedImageView)支持 ImageView 上的圆角,但它只支持每个角的半径相同。所以我做了一个,你可以在每个角落设置不同的半径。

它不依赖路径裁剪,也不重绘。它只使用canvas.drawPath() 方法绘制一次。所以我终于得到了我想要的结果,如下所示。

见:https://github.com/pungrue26/SelectableRoundedImageView

【讨论】:

    【解决方案5】:

    如果您需要制作具有不同圆角半径的位图,我建议您使用以下代码:

    private static Bitmap createRoundedRectBitmap(@NonNull Bitmap bitmap,
                                    float topLeftCorner, float topRightCorner,
                                    float bottomRightCorner, float bottomLeftCorner) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), 
                                            Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
    
        final int color = Color.WHITE;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);
        Path path = new Path();
        float[] radii = new float[]{
                topLeftCorner, bottomLeftCorner,
                topRightCorner, topRightCorner,
                bottomRightCorner, bottomRightCorner,
                bottomLeftCorner, bottomLeftCorner
        };
    
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        path.addRoundRect(rectF, radii, Path.Direction.CW);
        canvas.drawPath(path, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        return output;
    }
    

    【讨论】:

    • 第二个元素应该是topLeftCorner而不是bottomLeftCorner,这样才有效。
    【解决方案6】:

    如果你还需要边框,那么: 1.您可以使用透明主体和外部白色的圆角框图像。例如:

    并将其与目标图像一起使用,如下所示:

    <FrameLayout
    android:layout_width="100px"
    android:layout_height="100px" >
    <ImageView
            android:id="@+id/targetImage"
            android:layout_width="100px"
            android:layout_height="100px"
            android:src="@drawable/app_icon"
            android:layout_gravity="center" />
    <ImageView
            android:id="@+id/boxImage"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:scaleType="fitXY"
            android:src="@drawable/box" />
    

    1. 添加CardView 作为ImageView 的父布局也是一个不错的解决方案。

    【讨论】:

      【解决方案7】:

      对我来说,下面的方法很神奇。 :) 此方法接受一个位图对象并将其返回为圆角。 roundPx 是您想要的圆角像素数:

      public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
          Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
          bitmap.getHeight(), 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 = 12;
      
          paint.setAntiAlias(true);
          canvas.drawARGB(0, 0, 0, 0);
          paint.setColor(color);
          canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
      
          paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
          canvas.drawBitmap(bitmap, rect, rect, paint);
      
          return output;
      }
      

      ...或者您可以使用 this 库而不是 ImageView 而无需任何进一步的编码。

      【讨论】:

        【解决方案8】:

        它可以通过背景drawable来完成,就像在包括这个在内的许多帖子中解释的那样,但它还需要设置剪辑。 这是一个完整的例子:

        代码:

        AppCompatImageView iconView = findViewById(R.id.thumbnail);
        iconView.setClipToOutline(true);
        

        布局:

        <android.support.v7.widget.AppCompatImageView
            android:id="@+id/thumbnail"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:contentDescription="@string/thumbnail"
            android:scaleType="centerInside"
            android:background="@drawable/round_view" <!--here set the drawable as background -->
            tools:src="@mipmap/ic_user" />
        

        可绘制对象:

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

        【讨论】:

          【解决方案9】:
          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 defStyle) {
                  super(context, attrs, defStyle);
              }
          
              @Override
              protected void onDraw(Canvas canvas) {
          
                  super.onDraw(canvas);
          
                  Bitmap rounder = Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);
                  Canvas canvasRound = new Canvas(rounder);    
          
                  Paint xferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                  xferPaint.setColor(Color.BLACK);
          
                  final int rx = this.getWidth(); //our x radius
                  final int ry = this.getHeight(); //our y radius
          
                  canvasRound.drawRoundRect(new RectF(0,0,rx,ry), rx, ry, xferPaint);     
          
                  xferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
          
                  canvas.drawBitmap(rounder, 0, 0, xferPaint);
          
              }
          
          }
          

          【讨论】:

            【解决方案10】:
            /**
             * Creates new circular bitmap based on original one.
             * @param newCornerRadius is optional
             */
            fun Bitmap.toCircular(context: Context, newCornerRadius: Float? = null): RoundedBitmapDrawable {
                return RoundedBitmapDrawableFactory.create(context.resources, this).apply {
                    isCircular = true
                    newCornerRadius?.let {
                        cornerRadius = it
                    }
                }
            }
            

            【讨论】:

              【解决方案11】:

              在android中为imageview制作圆角的方法不是火箭科学的家伙!只需使用具有与背景颜色相同的所需曲线的 png 并将叠加设置为 FITXY。!

              【讨论】:

              • 如果图片来自服务器怎么办。
              【解决方案12】:
              public void drawRoundImage(boolean isEditPicEnable){
                 if(originalImageBitmap != null){
                      setBackgroundResource(R.drawable.ic_account_user_outer_circle_blue);
              
                      if (isEditPicEnable) {
                          setBackgroundResource(R.drawable.ic_account_user_outer_circle_white);
                          Bitmap mask = BitmapFactory.decodeResource(getResources(), R.drawable.ic_account_white_mask);
                          Bitmap mask1 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_account_pencil_bg);
                          originalImageBitmap = Bitmap.createScaledBitmap(originalImageBitmap, mask.getWidth(), mask.getHeight(), true);
                          Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Bitmap.Config.ARGB_8888);
                          Canvas mCanvas = new Canvas(result);
                          Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
                          paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
                          mCanvas.drawBitmap(originalImageBitmap, 0, 0, null);
                          mCanvas.drawBitmap(mask, 0, 0, paint);
                          mCanvas.drawBitmap(mask1, 0, 0, null);
                          Bitmap mask2 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_account_pencil);
                          mCanvas.drawBitmap(mask2, 0, 0, null);
                          setImageBitmap(result);
                          setScaleType(ScaleType.FIT_XY);
                      } else {
                          Bitmap mask = BitmapFactory.decodeResource(getResources(),R.drawable.ic_account_white_mask);
                          originalImageBitmap = Bitmap.createScaledBitmap(originalImageBitmap, mask.getWidth(),mask.getHeight(), true);
                          Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(),Bitmap.Config.ARGB_8888);
                          Canvas mCanvas = new Canvas(result);
                          Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
                          paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
                          mCanvas.drawBitmap(originalImageBitmap, 0, 0, null);
                          mCanvas.drawBitmap(mask, 0, 0, paint);
                          paint.setXfermode(null);
                          setImageBitmap(result);
                          setScaleType(ScaleType.FIT_XY);
                      }
              
                  }else{
                      setBackgroundResource(R.drawable.ic_account_user_outer_circle_blue);
                      setImageResource(R.drawable.my_ac_default_profile_pic);
                  }
              
              }
              

              【讨论】:

              • 虽然这个答案可能解决了发布的问题,但建议您也添加一些人类可读的文本来解释代码的作用或与它的不同之处OP的代码。就像现在一样,它只是一个代码转储,甚至无法解释为什么这样做有什么好处。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-02-01
              • 2018-05-24
              • 2011-01-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多