Question Comment faire un ImageView avec des coins arrondis?


Dans Android, un ImageView est un rectangle par défaut. Comment puis-je en faire un rectangle arrondi (couper les 4 coins de mon Bitmap pour obtenir des rectangles arrondis) dans ImageView?


445
2018-03-17 04:32


origine


Réponses:


C'est assez tard dans la réponse, mais pour toute autre personne qui cherche cela, vous pouvez faire le code suivant pour arrondir manuellement les coins de vos images.

http://www.ruibm.com/?p=184

Ce n'est pas mon code, mais je l'ai utilisé et ça fonctionne à merveille. Je l'ai utilisé comme assistant dans une classe ImageHelper et l'ai étendu un peu pour transmettre la quantité de plumes dont j'ai besoin pour une image donnée.

Le code final ressemble à ceci:

package com.company.app.utils;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;

public class ImageHelper {
    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;
    }
}

J'espère que cela aide quelqu'un!


510
2017-07-20 17:48



Alors que la réponse ci-dessus fonctionne, Romain Guy (un développeur Android de base) montre une meilleure méthode dans son blog qui utilise moins de mémoire en utilisant un shader ne créant pas une copie de l'image bitmap. L'essentiel général de la fonctionnalité est ici:

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

Les avantages de cette méthode par rapport aux autres méthodes sont les suivants:

  • ne crée pas de copie séparée du bitmap, qui utilise beaucoup de mémoire avec de grandes images [vs la plupart des autres réponses ici]
  • les soutiens antialisasing [vs méthode clipPath]
  • les soutiens alpha [vs xfermode + méthode porterduff]
  • les soutiens accélération matérielle [vs méthode clipPath]
  • seulement dessine une fois sur la toile [vs méthodes xfermode et clippath]

J'ai créé un ArrondiImageView basé sur ce code qui enveloppe cette logique dans une ImageView et ajoute ScaleType support et une bordure arrondie optionnelle.


182
2018-02-22 19:59



Dans la v21 de la bibliothèque de support il y a maintenant une solution à cela: ça s'appelle RoundedBitmapDrawable.

C'est fondamentalement comme un dessinable normal sauf que vous lui donnez un rayon de coin pour le découpage avec:

setCornerRadius(float cornerRadius)

Donc, à partir de Bitmap src et une cible ImageView, ça ressemblerait à ça:

RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(res, src);
dr.setCornerRadius(cornerRadius);
imageView.setImageDrawable(dr);

100
2017-10-20 17:48



Un autre moyen simple consiste à utiliser un CardView avec le rayon de coin et un ImageView à l'intérieur:

  <android.support.v7.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"
                />
        </android.support.v7.widget.CardView>

enter image description here


84
2018-01-05 07:43



Clipping à des formes arrondies a été ajouté à la View classe dans l'API 21.

Fais juste ceci:

  • Créez une forme arrondie pouvant être dessinée, quelque chose comme ceci:

res / drawable / round_outline.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="10dp" />
    ...
</shape>
  • Définissez le dessin comme arrière-plan de votre ImageView: android:background="@drawable/round_outline"
  • Selon ce Documentation, alors tout ce que vous devez faire est d'ajouter android:clipToOutline="true"

Malheureusement, il y a un bug et cet attribut XML n'est pas reconnu. Heureusement, nous pouvons toujours configurer le découpage en Java:

  • Dans votre activité ou fragment: ImageView.setClipToOutline(true)

Voici à quoi cela ressemblera:

enter image description here

Remarque:

Cette méthode fonctionne pour tout forme dessinable (pas seulement arrondie). Il découpera l'image dans la forme que vous avez définie dans votre fichier XML.

Note spéciale sur ImageViews

setClipToOutline() ne fonctionne que lorsque l'arrière-plan de la vue est défini sur une forme pouvant être dessinée. Si cette forme d'arrière-plan existe, View traite le contour de la forme comme les bordures à des fins d'écrêtage et d'occultation.

Cela signifie que si vous voulez utiliser setClipToOutline() pour arrondir les coins sur un ImageView, votre image doit être définie en utilisant android:src au lieu de android:background (puisque le fond doit être réglé sur votre forme arrondie). Si vous devez utiliser l'arrière-plan pour définir votre image à la place de src, vous pouvez utiliser cette solution de contournement:

  • Créez une mise en page et définissez son arrière-plan sur votre mise en forme
  • Enroulez cette mise en page autour de votre ImageView (sans remplissage)
  • L'imageView (y compris toute autre chose dans la mise en page) sera désormais affichée avec une forme de mise en page arrondie.

53
2018-06-07 10:29



J'ai trouvé que les deux méthodes étaient très utiles pour trouver une solution de travail. Voici ma version composite, qui est indépendante des pixels et vous permet d'avoir des coins carrés avec le reste des coins ayant le même rayon (ce qui est le cas d'utilisation habituel). En remerciant les deux solutions ci-dessus:

public static Bitmap getRoundedCornerBitmap(Context context, Bitmap input, int pixels , int w , int h , boolean squareTL, boolean squareTR, boolean squareBL, boolean squareBR  ) {

    Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
    Canvas canvas = new Canvas(output);
    final float densityMultiplier = context.getResources().getDisplayMetrics().density;

    final int color = 0xff424242;
    final Paint paint = new Paint();
    final Rect rect = new Rect(0, 0, w, h);
    final RectF rectF = new RectF(rect);

    //make sure that our rounded corner is scaled appropriately
    final float roundPx = pixels*densityMultiplier;

    paint.setAntiAlias(true);
    canvas.drawARGB(0, 0, 0, 0);
    paint.setColor(color);
    canvas.drawRoundRect(rectF, roundPx, roundPx, paint);


    //draw rectangles over the corners we want to be square
    if (squareTL ){
        canvas.drawRect(0, h/2, w/2, h, paint);
    }
    if (squareTR ){
        canvas.drawRect(w/2, h/2, w, h, paint);
    }
    if (squareBL ){
        canvas.drawRect(0, 0, w/2, h/2, paint);
    }
    if (squareBR ){
        canvas.drawRect(w/2, 0, w, h/2, paint);
    }


    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    canvas.drawBitmap(input, 0,0, paint);

    return output;
}

De plus, j'ai remplacé ImageView pour le mettre dans le fichier afin que je puisse le définir en XML. Vous voudrez peut-être ajouter une partie de la logique que le super appel fait ici, mais je l'ai commenté car ce n'est pas utile dans mon cas.

    @Override
protected void onDraw(Canvas canvas) {
    //super.onDraw(canvas);
        Drawable drawable = getDrawable();

        Bitmap b =  ((BitmapDrawable)drawable).getBitmap() ;
        Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);

        int w = getWidth(), h = getHeight();


        Bitmap roundBitmap =  CropImageView.getRoundedCornerBitmap( getContext(), bitmap,10 , w, h , true, false,true, false);
        canvas.drawBitmap(roundBitmap, 0,0 , null);
}

J'espère que cela t'aides!


49
2018-03-09 22:00



Image arrondie ImageLoader  ici

Créer DisplayImageOptions:

DisplayImageOptions options = new DisplayImageOptions.Builder()
    // this will make circle, pass the width of image 
    .displayer(new RoundedBitmapDisplayer(getResources().getDimensionPixelSize(R.dimen.image_dimen_menu))) 
    .cacheOnDisc(true)
    .build();

imageLoader.displayImage(url_for_image,ImageView,options);

Ou vous pouvez user Picasso Bibliothèque de la place.

Picasso.with(mContext)
    .load(com.app.utility.Constants.BASE_URL+b.image)
    .placeholder(R.drawable.profile)
    .error(R.drawable.profile)
    .transform(new RoundedTransformation(50, 4))
    .resizeDimen(R.dimen.list_detail_image_size, R.dimen.list_detail_image_size)
    .centerCrop()
    .into(v.im_user);

vous pouvez télécharger le fichier RoundedTransformation ici ici


44
2018-05-27 09:30



J'ai fait par 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);
    }
}

Comment utiliser:

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

Sortie:

enter image description here

J'espère que cela vous aidera.


40
2017-10-20 09:36



Comme toutes les réponses semblaient trop compliquées pour moi juste pour les coins arrondis je pensais et suis venu à une autre solution que je pense vaut la peine de partager, juste avec XML au cas où vous auriez un peu d'espace autour de l'image:

Créez une forme encadrée avec du contenu transparent comme ceci:

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

Ensuite, dans un RelativeLayout, vous pouvez d'abord placer votre image, puis au même endroit au-dessus de la forme avec un autre ImageView. La forme de la couverture doit être plus grande que la largeur de la bordure. Veillez à prendre un rayon d'angle plus grand lorsque le rayon extérieur est défini, mais le rayon intérieur correspond à votre image.

J'espère que ça aide quelqu'un aussi.

modifier selon CQM demander l'exemple de mise en page relative:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/imageToShow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/imgCorners"
        android:layout_alignLeft="@+id/imgCorners"
        android:layout_alignRight="@+id/imgCorners"
        android:layout_alignTop="@+id/imgCorners"
        android:background="#ffffff"
        android:contentDescription="@string/desc"
        android:padding="5dp"
        android:scaleType="centerCrop" />

    <ImageView
        android:id="@+id/imgCorners"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:contentDescription="@string/desc"
        android:src="@drawable/corners_white" />

</RelativeLayout>

24
2017-10-23 11:45



Mon implémentation du widget ImageView avec coins arrondis, qui (down || up) taille l'image aux dimensions requises. Il utilise la forme de code CaspNZ.

public class ImageViewRounded extends ImageView {

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

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

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

    @Override
    protected void onDraw(Canvas canvas) {
        BitmapDrawable drawable = (BitmapDrawable) getDrawable();

        if (drawable == null) {
            return;
        }

        if (getWidth() == 0 || getHeight() == 0) {
            return; 
        }

        Bitmap fullSizeBitmap = drawable.getBitmap();

        int scaledWidth = getMeasuredWidth();
        int scaledHeight = getMeasuredHeight();

        Bitmap mScaledBitmap;
        if (scaledWidth == fullSizeBitmap.getWidth() && scaledHeight == fullSizeBitmap.getHeight()) {
            mScaledBitmap = fullSizeBitmap;
        } else {
            mScaledBitmap = Bitmap.createScaledBitmap(fullSizeBitmap, scaledWidth, scaledHeight, true /* filter */);
        }

        Bitmap roundBitmap = ImageUtilities.getRoundedCornerBitmap(getContext(), mScaledBitmap, 5, scaledWidth, scaledHeight,
                false, false, false, false);
        canvas.drawBitmap(roundBitmap, 0, 0, null);

    }

}

13
2017-10-15 16:37