How to make an ImageView with rounded corners?

前端 未结 30 2535
天涯浪人
天涯浪人 2020-11-21 05:39

In Android, an ImageView is a rectangle by default. How can I make it a rounded rectangle (clip off all 4 corners of my Bitmap to be rounded rectangles) in the ImageView?

相关标签:
30条回答
  • 2020-11-21 06:09

    Props to George Walters II above, I just took his answer and extended it a bit to support rounding individual corners differently. This could be optimized a bit further (some of the target rects overlap), but not a whole lot.

    I know this thread is a bit old, but its one of the top results for queries on Google for how to round corners of ImageViews on Android.

    /**
     * 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;
    }
    
    0 讨论(0)
  • 2020-11-21 06:10

    In the v21 of the Support library there is now a solution to this: it's called RoundedBitmapDrawable.

    It's basically just like a normal Drawable except you give it a corner radius for the clipping with:

    setCornerRadius(float cornerRadius)
    

    So, starting with Bitmap src and a target ImageView, it would look something like this:

    RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(res, src);
    dr.setCornerRadius(cornerRadius);
    imageView.setImageDrawable(dr);
    
    0 讨论(0)
  • 2020-11-21 06:10

    Here is a simple example overriding imageView, you can then also use it in layout designer to preview.

    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);
        }
    }
    

    This is for fast solution. Radius is used on all corners and is based of percentage of bitmap width.

    I just overrided setImageDrawable and used support v4 method for rounded bitmap drawable.

    Usage:

    <com.example.widgets.RoundedImageView
            android:layout_width="39dp"
            android:layout_height="39dp"
            android:src="@drawable/your_drawable" />
    

    Preview with imageView and custom imageView:

    0 讨论(0)
  • 2020-11-21 06:10

    If you are using Glide Library this would be helpful:

    Glide.with(getApplicationContext())
         .load(image_url)
         .asBitmap()
         .centerCrop()
         .into(new BitmapImageViewTarget(imageView) {
            @Override
            protected void setResource(Bitmap resource) {
              RoundedBitmapDrawable circularBitmapDrawable =
                           RoundedBitmapDrawableFactory.create(getApplicationContext().getResources(), resource);
              circularBitmapDrawable.setCornerRadius(dpToPx(10));
              circularBitmapDrawable.setAntiAlias(true);
              imageView.setImageDrawable(circularBitmapDrawable);
            }
         });
    
    
    public int dpToPx(int dp) {
      DisplayMetrics displayMetrics = getApplicationContext().getResources().getDisplayMetrics();
      return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
    }
    
    0 讨论(0)
  • 2020-11-21 06:11

    Another easy way is to use a CardView with the corner radius and an ImageView inside:

      <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:cardCornerRadius="8dp"
                android:layout_margin="5dp"
                android:elevation="10dp">
    
                <ImageView
                    android:id="@+id/roundedImageView"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:src="@drawable/image"
                    android:background="@color/white"
                    android:scaleType="centerCrop"
                    />
            </androidx.cardview.widget.CardView>
    

    0 讨论(0)
  • 2020-11-21 06:13

    I have done by Custom ImageView:

    public class RoundRectCornerImageView extends ImageView {
    
        private float radius = 18.0f;
        private Path path;
        private RectF rect;
    
        public RoundRectCornerImageView(Context context) {
            super(context);
            init();
        }
    
        public RoundRectCornerImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public RoundRectCornerImageView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
    
        private void init() {
            path = new Path();
    
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            rect = new RectF(0, 0, this.getWidth(), this.getHeight());
            path.addRoundRect(rect, radius, radius, Path.Direction.CW);
            canvas.clipPath(path);
            super.onDraw(canvas);
        }
    }
    

    How to use:

    <com.mypackage.RoundRectCornerImageView
         android:id="@+id/imageView"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:background="@drawable/image"
         android:scaleType="fitXY" />
    

    Output:

    Hope this would help you.

    0 讨论(0)
提交回复
热议问题