Comment faire une ImageView avec des coins arrondis?

573

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

Michael
la source
Cela pourrait être utile stackoverflow.com/questions/26850780/…
Mangesh
Ci-dessous, les réponses plus anciennes et plus compliquées sont ce que je pense devrait être la réponse acceptée maintenant: RoundedBitmapDrawable , ajouté dans la révision 21 de la bibliothèque de support v4
Jonik
Vous pouvez le faire de la manière la plus simple en utilisant simplement CardView avec une ImageView à l'intérieur - regardez l'exemple ici stackoverflow.com/a/41479670/4516797
Taras Vovkovych
Cette bibliothèque est très utile.
grrigore
Vérifiez cela maintenant, nous devons ShapeableImageViewfaire une image circulaire ou arrondieView stackoverflow.com/a/61086632/7666442
Nilesh Rathod

Réponses:

545

C'est assez tard dans la réponse, mais pour quiconque le recherche, 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 cela fonctionne à merveille. Je l'ai utilisé comme aide dans une classe ImageHelper et je 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!

George Walters II
la source
4
Cela ne fonctionne pas pour tous les appareils. Dois-je changer quelque part?
Spring Breaker
7
Cela prend près de 0,03 seconde pour le faire pour une image 200 * 200, donc je pense que ce n'est pas la meilleure solution.
Jacky
2
Il arrondit uniquement les coins supérieurs gauche et supérieur droit. Pourquoi ?
Prateek
1
La solution @ vinc3m1 ici github.com/makeramen/RoundedImageView fonctionne très bien! voir aussi sa réponse ( stackoverflow.com/a/15032283/2048266 )
Nommer
16
Ne fonctionne pas bien lorsque vous essayez de définir le type de scalaire de imageview, seul fitXY fonctionne, centerCrop et d'autres affichent des résultats imprévisibles, quelqu'un ici a les mêmes problèmes?
Shivansh
211

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 du 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 une copie séparée du bitmap, qui utilise beaucoup de mémoire avec de grandes images [vs la plupart des autres réponses ici]
  • prend en charge l' antialasie [par rapport à la méthode clipPath ]
  • prend en charge alpha [vs méthode xfermode + porterduff]
  • prend en charge l'accélération matérielle [méthode clipPath]
  • ne dessine qu'une seule fois sur le canevas [vs méthodes xfermode et clippath]

J'ai créé un RoundedImageView basé sur ce code qui enveloppe cette logique dans un ImageView et ajoute un ScaleTypesupport approprié et une bordure arrondie facultative.

vinc3m1
la source
dans votre / example / res / layout / rounded_item.xml pourquoi spécifiez-vous une image src lorsque toutes vos sources sont codées en dur? Belle démo, juste exagérée.
Someone Somewhere
votre échantillon a un grave problème de mémoire insuffisante, tout comme l'échantillon original de Romain Guy. Je ne sais toujours pas ce qui en est la cause, mais tout comme son code, c'est une chose vraiment difficile à trouver. Si vous ne voyez pas de plantage de l'application à cause du MOO, vous pouvez faire pivoter l'application plusieurs fois jusqu'à ce qu'elle se produise (cela dépend de votre appareil, de votre ROM, etc ...). Je l'ai signalé dans le passé ici: stackoverflow.com/questions/14109187/…
développeur Android
1
Personne d'autre ne signale le problème de mémoire insuffisante, donc ce doit être quelque chose que vous faites en dehors du code qui est incorrect. L'exemple contient correctement un ensemble limité de bitmaps dans l'adaptateur sans les recréer chaque fois qu'une vue est dessinée. L'exemple présenté ici est un extrait de la méthode draw () dans Drawable, qui utilise la référence au bitmap d'origine qu'il contient et fonctionne correctement. Il n'est pas destiné à modifier le bitmap d'origine, mais uniquement à le rendre avec des coins arrondis. Le recadrage central fonctionne également très bien dans l'exemple.
vinc3m1
1
Si vous pouvez fournir des captures d'écran ou des appareils là où cela ne fonctionne pas, ou même aller jusqu'à proposer une demande de correction et d'extraction, ce serait plus productif. J'ai testé la rotation plusieurs fois sur mes appareils et la mémoire reste la même.
vinc3m1
11
Notez que cela ne fonctionnera pas si la taille de l'image est supérieure à 2048 pixels. Le shader ne prend pas en charge une texture plus grande que cela.
Gábor
209

Un autre moyen simple consiste à utiliser une CardView avec le rayon de coin et une 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>

entrez la description de l'image ici

Taras Vovkovych
la source
5
Cela semble être une bonne solution de contournement. Mais il ne coupe pas les images sur les pré-Lollipops.
Nikolai
1
Et si, nous voulons seulement un rayon dans les coins supérieurs gauche et supérieur droit et pas tous les coins?
Pratik Singhal
3
Un moyen très simple et intelligent pour appliquer une bordure de courbe dans n'importe quelle vue.
AMI CHARADAVA
1
Bonne solution mais l'élévation n'est prise en charge que dans les niveaux 21 et supérieurs de l'API
Saad Bilal
1
Pour désactiver l'élévation de la carte, utilisez l'application: cardElevation = "0dp" (pas android: élévation)
Johnny Five
150

Le découpage en formes arrondies a été ajouté à la Viewclasse dans l'API 21.

Faites juste ceci:

  • Créez une forme arrondie à dessiner, 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 dessinable comme arrière-plan de votre ImageView: android:background="@drawable/round_outline"
  • Selon cette documentation , il vous suffit d'ajouterandroid:clipToOutline="true"

Malheureusement, il y a un bogue et cet attribut XML n'est pas reconnu. Heureusement, nous pouvons toujours configurer l'écrêtage en Java:

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

Voici à quoi cela ressemblera:

entrez la description de l'image ici

Remarque:

Cette méthode fonctionne pour toutes les formes dessinables (pas seulement arrondies). Il fixera l'ImageView à n'importe quel contour de forme que vous avez défini dans votre xml Drawable.

Note spéciale sur ImageViews

setClipToOutline()ne fonctionne que lorsque l'arrière-plan de la vue est défini sur une forme dessinable. Si cette forme d'arrière-plan existe, View traite le contour de la forme comme des bordures à des fins de découpe et d'ombrage.

Cela signifie que si vous souhaitez utiliser setClipToOutline()pour arrondir les coins d'une ImageView, votre image doit être définie à l'aide de android:srcau lieu de android:background(car l'arrière-plan doit être défini selon votre forme arrondie). Si vous DEVEZ utiliser l'arrière-plan pour définir votre image au lieu de src, vous pouvez utiliser cette solution de contournement:

  • Créez une mise en page et définissez son arrière-plan à votre forme
  • Enveloppez cette disposition autour de votre ImageView (sans rembourrage)
  • L'imageView (y compris tout autre élément de la mise en page) s'affiche désormais avec une forme de mise en page arrondie.
faim
la source
10
Erreur: (x) Aucun identifiant de ressource trouvé pour l'attribut 'clipToOutline' dans le package 'android'
Anu Martin
7
Au lieu de cela android:clipToOutline, il faut utiliser android:outlineProvider="background".
WindRider
2
Une autre raison pour laquelle j'aime tant Google est que ce bug a presque mon âge et réside toujours dans son petit monde. Google semble ne donner aucun cr * ap à ce sujet))
Farid
1
Il me semble que cette méthode ne réussit pas lorsque je mets uniquement topleft et topRight corner dans la forme d'arrière-plan à round.
Peterdk
@AnuMartin, il s'agit d'un problème connu - issuetracker.google.com/issues/37036728
Vadim Kotov
132

Dans la version 21 de la bibliothèque de support, il existe maintenant une solution à cela: elle s'appelle RoundedBitmapDrawable .

C'est fondamentalement comme un Drawable normal, sauf que vous lui donnez un rayon de coin pour l'écrêtage avec:

setCornerRadius(float cornerRadius)

Donc, en commençant par Bitmap srcet une cible ImageView, cela ressemblerait à ceci:

RoundedBitmapDrawable dr = RoundedBitmapDrawableFactory.create(res, src);
dr.setCornerRadius(cornerRadius);
imageView.setImageDrawable(dr);
tyczj
la source
3
Grand merci, voici la prochaine étape: stackoverflow.com/questions/24878740/…
David d C e Freitas
en fait il y a android.support.v4.graphics.drawable.RoundedBitmapDrawableFactorydonc v4aussi le soutient.
deadfish
2
@deadfish oui c'est dans la v4bibliothèque de support mais pas avant REVISION 21la bibliothèque de support
tyczj
3
Cette solution est simple et à jour. Il nécessite le moins de code et possède une grande extensibilité. Peut fonctionner avec des images à partir d'un fichier local, dessinables en cache ou même avec NetworkImageView de Volley. Je suis tout à fait d'accord que cela devrait être la réponse acceptée de nos jours, comme l'a souligné @Jonik.
katie
2
Malheureusement, ne fonctionne pas avec scaleType centerCrop(bibliothèque de support v25.3.1)
rocknow
67

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:background="@drawable/image"
     android:scaleType="fitXY" />

Production:

entrez la description de l'image ici

J'espère que cela vous aidera.

Hiren Patel
la source
cela rend l'image floue
Amit Hooda
2
fonctionne même avec android: scaleType = "centerCrop", simple, ne crée pas de nouveau bitmap. Merci!
ernazm
1
@Hiren Cette solution fonctionne très bien pour ImageView avec une image d'arrière-plan. Mais cela ne fonctionne pas pour ImageViews qui n'a qu'une couleur d'arrière-plan et aucune image. Pouvez-vous me dire pourquoi cela se produit?
user2991413
Canvas.clipPath()peut provoquer java.lang.UnsupportedOperationExceptiondans certains cas. Voir stackoverflow.com/questions/13248904/…
Artyom
1
Cette solution ne fonctionne que pour les images définies avec android:background, mais pas android:src.
CoolMind
65

Une solution xml rapide -

<android.support.v7.widget.CardView
            android:layout_width="40dp"
            android:layout_height="40dp"
            app:cardElevation="0dp"
            app:cardCornerRadius="4dp">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/rounded_user_image"
        android:scaleType="fitXY"/>

</android.support.v7.widget.CardView>

Vous pouvez définir la largeur, la hauteur et le rayon souhaités sur CardView et scaleType sur ImageView.

Avec AndroidX, utilisez <androidx.cardview.widget.CardView>

Chirag Mittal
la source
4
cette approche a fonctionné dans mon cas avec androidx.cardview.widget.CardView
Ivan
7
Vous ne savez pas pourquoi cela n'a pas plus de votes positifs? À mon avis, la meilleure solution sans bibliothèques et des tonnes de code merdique (même si j'ai utilisé la mise à l'échelle centerCrop dans mon cas).
ThemBones
1
Pas encore beaucoup de votes positifs, car c'est une nouvelle réponse. Mais j'ai mis mon +1 pour le remonter bientôt! Merci!
Micer
cependant, cela fonctionne, mais ici l'image va s'étirer à cause de scaleType="fitXY"et ne semble pas correcte @ThemBones
WIZARD
@WIZARD c'est pourquoi j'ai mentionné que vous pouvez définir votre scaleType souhaité sur ImageView
Chirag Mittal
57

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). Merci aux 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 outrepassé ImageView pour le mettre afin de pouvoir 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ée car elle 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!

Caspar Harmer
la source
4
assez génial, en particulier l'extension de ImageView
Someone Somewhere
2
Un moyen simple de conserver la logique de ImageView # onDraw () consiste à définir le bitmap de coin arrondi sur le dessin de ImageView et à laisser le super.onDraw () pour dessiner le bitmap. J'ai créé une classe RoundedCornerImageView , et son exemple d'utilisation est ici . Veuillez noter que le getRoundedCornerBitmap () que j'ai utilisé n'est pas indépendant des pixels.
umbalaconmeogia
Merci pour le RoundedCornerImageView. Je l'ai utilisé mais je l'ai modifié pour qu'il soit indépendant de la densité de pixels.
PacificSky
Le code source de RoundedCornerImageView d'omba est ici: code.google.com/p/android-batsg/source/browse/trunk/…
Someone Somewhere
@Caspar Harmer fonctionne bien juste 1 édition ... il y a quatre conditions..modifiez-les comme si je définissais true, true, false, false, cela définira le coin inférieur au lieu du coin supérieur..autrement, le code fonctionne bien.so squareTL et squareTR sont des conditions pour squareBL et squareBR respectivement .. et vice-versa.
TheFlash
48

Image arrondie Utilisation 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 utiliser la Picassobibliothèque de Square.

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

shailesh
la source
1
N'affiche
3
La bibliothèque Picasso est bonne et très facile à mettre en œuvre, merci beaucoup +1
Hitesh
3
La bibliothèque Picasso ne semble cependant pas transformer l'image "espace réservé" et "erreur", donc si votre image ne parvient pas à se charger (erreur) ou prend un certain temps à charger initialement (espace réservé), elle n'affichera pas l'image comme une image arrondie. github.com/square/picasso/issues/337
Pelpotronic
D'autres transformations picasso utiles sont fournies par cette bibliothèque, qui contient également une RoundedCornersTransformation: github.com/wasabeef/picasso-transformations
Massimo
Ne fonctionne pas avec le recadrage d'images dans Univ. Chargeur d'images.
Yar
26

Comme toutes les réponses me semblaient trop compliquées juste pour les coins ronds, j'ai pensé et suis venu à une autre solution qui, je pense, mérite d'être partagée, juste avec XML au cas où vous auriez un peu d'espace autour de l'image:

Créez une forme bordée avec un contenu transparent comme celui-ci:

<?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 une autre ImageView. La forme du couvercle doit être plus grande en fonction de la largeur de la bordure. Faites attention à prendre un rayon d'angle plus grand car le rayon extérieur est défini mais le rayon intérieur est ce qui recouvre votre image.

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

Modifiez selon la demande CQM l'exemple de disposition 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>
Christian
la source
pouvez-vous en dire plus avec plus de code, en particulier ce qui est fait avec la deuxième vue d'image et où le xml "forme bordée" est appliqué (comme src ou comme arrière-plan?) plusieurs questions ici. Je veux aimer cette solution car elle me permettra de contrôler les quatre coins de façon indépendante
CQM
1
Bien que cela semble être une réponse simple, il ajoute malheureusement une marge autour de l'image "masquée", ce qui est un effet secondaire indésirable.
Abdalrahman Shatou
oui, mais la même chose fonctionne avec une ImageView basée sur un PNG-Drawable avec des coins arrondis et un fond transparent ou un 9-Patch-Drawable si vous avez un aspect indéfini.
Christian
Je fais de la même manière, et son fonctionnement; juste disposé à savoir si cela ne créera aucun problème d'orientation et de taille de téléphone différente?
ouvert et gratuit
Si vous conservez les dimensions les unes par rapport aux autres, cela ne devrait pas créer de problème.
Christian
22

À partir de la version 1.2.0-alpha03de la bibliothèque de composants de matériaux, il y a la nouvelle ShapeableImageView.

Vous pouvez utiliser quelque chose comme:

  <com.google.android.material.imageview.ShapeableImageView
      ...
      app:shapeAppearanceOverlay="@style/roundedImageView"
      app:srcCompat="@drawable/ic_image" />

avec:

  <style name="roundedImageView" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">8dp</item>
  </style>

Ou par programmation:

float radius = getResources().getDimension(R.dimen.default_corner_radius);
imageView.setShapeAppearanceModel(imageView.getShapeAppearanceModel()
    .toBuilder()
    .setAllCorners(CornerFamily.ROUNDED,radius)
    .build());

entrez la description de l'image ici

Gabriele Mariotti
la source
Si l'image a une couleur d'arrière-plan, cela produit actuellement la couleur d'arrière-plan à apparaître sous les coins arrondis. Cela ignore également la propriété scaleType sur l'image.
inokey
14

Mon implémentation du widget ImageView avec coins arrondis, qui (bas || haut) dimensionne 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);

    }

}
Damjan
la source
12
D'où viennent ImageUtilities?
JasonWyatt
1
@JasonWyatt voir le post de sorrodos ci
Damjan
12

Récemment, il existe un autre moyen: utiliser l'API générée de Glide . Cela prend un peu de travail initial mais vous donne ensuite toute la puissance de Glide avec la flexibilité de faire n'importe quoi parce que vous écrivez le code réel, donc je pense que c'est une bonne solution à long terme. De plus, l'utilisation est très simple et soignée.

Tout d'abord, configurez Glide version 4+:

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

Créez ensuite la classe de module d'application de Glid pour déclencher le traitement des annotations:

@GlideModule
public final class MyAppGlideModule extends AppGlideModule {}

Créez ensuite l'extension Glide qui fait le travail. Vous pouvez le personnaliser pour faire ce que vous voulez:

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

Après avoir ajouté ces fichiers, générez votre projet.

Ensuite, utilisez-le dans votre code comme ceci:

GlideApp.with(this)
        .load(imageUrl)
        .roundedCorners(getApplicationContext(), 5)
        .into(imageView);
Monsieur Codesalot
la source
N'oubliez pas d'ajouter un espace entre RequestOptionset optionsdans les paramètres
StevenTB
Terminé. Merci pour la contribution.
Sir Codesalot
.roundedCorners ne venant pas avons-nous besoin de configurer autre chose? Même après le projet de reconstruction
Dr. aNdRO
Cela a fonctionné pour moi, merci. J'ai trouvé plus simple d'éviter d'utiliser la @GlideExtensionclasse annotée et je suis allé avec .transform(new RoundedCorners(px))pxest le même ( int px = Math.round(cornerRadius * (context.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));).
Michael Osofsky
10

Il y a une bibliothèque sympa qui vous permet de façonner des vues d'images.

Voici un exemple:

<com.github.siyamed.shapeimageview.mask.PorterShapeImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:siShape="@drawable/shape_rounded_rectangle"
    android:src="@drawable/neo"
    app:siSquare="true"/>

Définition de la forme:

<shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android">
    <corners
        android:topLeftRadius="18dp"
        android:topRightRadius="18dp"
        android:bottomLeftRadius="18dp"
        android:bottomRightRadius="18dp" />
    <solid android:color="@color/black" />
</shape>

Résultat:

résultat

grrigore
la source
1
C'est génial, et fait beaucoup plus, comme vous pouvez ajouter une bordure et utiliser n'importe quelle forme
Adam Kis
8

Voici un exemple simple remplaçant imageView, vous pouvez également l'utiliser dans le concepteur de mise en page pour prévisualiser.

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

C'est pour une solution rapide. Le rayon est utilisé à tous les coins et est basé sur le pourcentage de largeur de bitmap.

Je viens de remplacer setImageDrawableet d'utiliser la méthode de support v4 pour le bitmap arrondi dessinable.

Usage:

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

Aperçu avec imageView et imageView personnalisée:

entrez la description de l'image ici

poisson mort
la source
Cela fonctionne dans toutes les situations, merci. Tu m'as sauvé la journée.
Mehul Solanki
7

Vous devez étendre ImageViewet dessiner votre propre rectangle arrondi.

Si vous voulez un cadre autour de l'image, vous pouvez également superposer le cadre arrondi au-dessus de la vue de l'image dans la mise en page.

[modifier] Superposez le cadre pour opérer l'image originale, en utilisant un FrameLayoutpar exemple. Le premier élément du FrameLayoutsera l'image que vous souhaitez afficher arrondie. Ajoutez ensuite un autre ImageViewavec le cadre. Le second ImageViewsera affiché au-dessus de l'original ImageViewet ainsi Android dessinera son contenu au-dessus de l'origine ImageView.

MrSnowflake
la source
Je vous remercie. Mais il n'y a qu'une méthode setDrawable pour ImageView, comment puis-je définirDrawable de ImageView sur le contenu de mon image, puis superposer un cadre arrondi au-dessus de ImageView?
michael
Je suis désolé, je n'étais pas clair. Je voulais dire superposer dans la mise en page: ainsi (c'est-à-dire) utiliser un FrameLayoutmettre un ImageViewdedans et en ajouter un autre ImageViewavec le cadre arrondi. De cette façon, le premier ImageViewaffichera votre image sélectionnée et le second ImageFrameaffichera le cadre arrondi.
MrSnowflake
Correct - avec FrameLayout, vous pouvez superposer une image / vue avec une autre. Vous pouvez également utiliser la balise android: foreground de FrameLayout.
Richard Le Mesurier
7

Romain Guy est là où il en est.

Version réduite comme suit.

Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.image)).getBitmap();

Bitmap bitmapRounded = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
Canvas canvas = new Canvas(bitmapRounded);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
canvas.drawRoundRect((new RectF(0.0f, 0.0f, bitmap.getWidth(), bitmap.getHeight())), 10, 10, paint);

imageView.setImageBitmap(bitmapRounded);
Alex
la source
malheureusement, même si cela fonctionne, mais tout comme les autres solutions ici, il crée un nouveau bitmap au lieu d'utiliser l'actuel.
développeur Android
pas vraiment. bitmapRounded serait utilisé encore et encore. si vous aviez accès au canevas dessinable, vous pouvez utiliser la méthode draw directement au lieu de générer un nouveau bitmap.
Alex
comment tu fais ça? Supposons que je n'utilise aucun dessinable spécial et que je ne gère qu'un seul bitmap et que j'utilise setImageBitmap à la fin du processus. comment pourrais-je réaliser une telle chose?
développeur Android
Découvrez l'exemple de romain guy curious-creature.org/2012/12/11/… et un exemple d'application docs.google.com/file/d/0B3dxhm5xm1sia2NfM3VKTXNjUnc/edit
Alex
les deux ne modifient pas le bitmap, mais l'enveloppent en utilisant un dessin personnalisé et une vue d'image personnalisée. ce n'est pas ce que j'ai demandé. J'ai demandé comment changer le bitmap lui-même.
développeur Android
7

Cette solution XML pure était assez bonne dans mon cas. http://www.techrepublic.com/article/pro-tip-round-corners-on-an-android-imageview-with-this-hack/

ÉDITER

Voici la réponse en bref:

Dans le dossier / res / drawable, créez un fichier frame.xml. Dans celui-ci, nous définissons un rectangle simple avec des coins arrondis et un centre transparent .

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
     <solid android:color="#00ffffff" />
     <padding android:left="6dp"
        android:top="6dp"
        android:right="6dp"
        android:bottom="6dp" />
     <corners android:radius="12dp" />
     <stroke android:width="6dp" android:color="#ffffffff" />
</shape>

Dans votre fichier de mise en page, vous ajoutez un LinearLayout qui contient un ImageView standard, ainsi qu'un FrameLayout imbriqué. Le FrameLayout utilise un rembourrage et le dessinable personnalisé pour donner l'illusion de coins arrondis.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_gravity="center"
    android:gravity="center" 
    android:background="#ffffffff">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="6dp"
        android:src="@drawable/tr"/>

    <FrameLayout 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="6dp"
            android:src="@drawable/tr"/>

        <ImageView 
             android:src="@drawable/frame"
             android:layout_width="match_parent"
             android:layout_height="match_parent" />

    </FrameLayout>

</LinearLayout>
j7nn7k
la source
bonne idée, je l'ai utilisé pour montrer des coins ImageView non pairs
Gal Rom
6

Accessoires à George Walters II ci-dessus, je viens de prendre sa réponse et de l'étendre un peu pour prendre en charge les arrondis individuels différemment. Cela pourrait être optimisé un peu plus (certains des rects cibles se chevauchent), mais pas beaucoup.

Je sais que ce fil est un peu ancien, mais c'est l'un des meilleurs résultats pour les requêtes sur Google pour savoir comment arrondir les coins d'ImageViews sur 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;
}
sorrodos
la source
+1 pour ajouter le multiplicateur de densité et ajouter un support pour arrondir les coins individuellement. En fait, j'ai utilisé la solution en haut, car votre solution ne fonctionnait pas tout à fait - mais c'était très utile! Voir ma solution composite ci-dessous:
Caspar Harmer
6

Appliquez une forme à votre imageViewcomme ci-dessous:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    <solid android:color="#faf5e6" />
    <stroke
        android:width="1dp"
        android:color="#808080" />
    <corners android:radius="15dp" />
    <padding
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp" />
</shape>

cela peut vous être utile, mon ami.

jigar
la source
6

Pourquoi ne pas couper draw()?

Voici ma solution:

  • Étendre RelativeLayout avec écrêtage
  • Mettez ImageView (ou d'autres vues) dans la mise en page:

Code:

public class RoundRelativeLayout extends RelativeLayout {

    private final float radius;

    public RoundRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray attrArray = context.obtainStyledAttributes(attrs,
                R.styleable.RoundRelativeLayout);
        radius = attrArray.getDimension(
                R.styleable.RoundRelativeLayout_radius, 0);
    }

    private boolean isPathValid;
    private final Path path = new Path();

    private Path getRoundRectPath() {
        if (isPathValid) {
            return path;
        }

        path.reset();

        int width = getWidth();
        int height = getHeight();
        RectF bounds = new RectF(0, 0, width, height);

        path.addRoundRect(bounds, radius, radius, Direction.CCW);
        isPathValid = true;
        return path;
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        canvas.clipPath(getRoundRectPath());
        super.dispatchDraw(canvas);
    }

    @Override
    public void draw(Canvas canvas) {
        canvas.clipPath(getRoundRectPath());
        super.draw(canvas);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int oldWidth = getMeasuredWidth();
        int oldHeight = getMeasuredHeight();
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int newWidth = getMeasuredWidth();
        int newHeight = getMeasuredHeight();
        if (newWidth != oldWidth || newHeight != oldHeight) {
            isPathValid = false;
        }
    }

}
fishautumn
la source
1
J'aime cette approche. Je l'ai utilisé pour créer mon propre RoundImageView. Merci pour cela.
Pascal
Cela ne fonctionne pas avec une accélération difficile activée, n'est-ce pas? Je n'ai pas vu de solution de contournement facile ...
secureboot
Pouvez-vous s'il vous plaît montrer comment le faire, en ayant le résultat sous forme de dessin, avez la possibilité d'ajouter un contour (trait AKA) autour du contenu, et avez également la possibilité de ne faire que certains des coins à arrondir?
développeur Android
5

Ce qui suit crée un objet de présentation en rectangle arrondi qui dessine un rectangle arrondi autour des objets enfants qui y sont placés. Il montre également comment créer des vues et des présentations par programme sans utiliser les fichiers xml de présentation.

package android.example;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MessageScreen extends Activity {
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  int mainBackgroundColor = Color.parseColor("#2E8B57");
  int labelTextColor = Color.parseColor("#FF4500");
  int messageBackgroundColor = Color.parseColor("#3300FF");
  int messageTextColor = Color.parseColor("#FFFF00");

  DisplayMetrics metrics = new DisplayMetrics();
  getWindowManager().getDefaultDisplay().getMetrics(metrics);
  float density = metrics.density;
  int minMarginSize = Math.round(density * 8);
  int paddingSize = minMarginSize * 2;
  int maxMarginSize = minMarginSize * 4;

  TextView label = new TextView(this);
  /*
   * The LayoutParams are instructions to the Layout that will contain the
   * View for laying out the View, so you need to use the LayoutParams of
   * the Layout that will contain the View.
   */
  LinearLayout.LayoutParams labelLayoutParams = new LinearLayout.LayoutParams(
    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  label.setLayoutParams(labelLayoutParams);
  label.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
  label.setPadding(paddingSize, paddingSize, paddingSize, paddingSize);
  label.setText(R.string.title);
  label.setTextColor(labelTextColor);

  TextView message = new TextView(this);
  RoundedRectangle.LayoutParams messageLayoutParams = new RoundedRectangle.LayoutParams(
 LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  /*
   * This is one of the calls must made to force a ViewGroup to call its
   * draw method instead of just calling the draw method of its children.
   * This tells the RoundedRectangle to put some extra space around the
   * View.
   */
  messageLayoutParams.setMargins(minMarginSize, paddingSize,
    minMarginSize, maxMarginSize);
  message.setLayoutParams(messageLayoutParams);
  message.setTextSize(TypedValue.COMPLEX_UNIT_SP, paddingSize);
  message.setText(R.string.message);
  message.setTextColor(messageTextColor);
  message.setBackgroundColor(messageBackgroundColor);

  RoundedRectangle messageContainer = new RoundedRectangle(this);
  LinearLayout.LayoutParams messageContainerLayoutParams = new LinearLayout.LayoutParams(
    LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  messageContainerLayoutParams.setMargins(paddingSize, 0, paddingSize, 0);
  messageContainer.setLayoutParams(messageContainerLayoutParams);
  messageContainer.setOrientation(LinearLayout.VERTICAL);
  /*
   * This is one of the calls must made to force a ViewGroup to call its
   * draw method instead of just calling the draw method of its children.
   * This tells the RoundedRectangle to color the the exta space that was
   * put around the View as well as the View. This is exterior color of
   * the RoundedRectangle.
   */
  messageContainer.setBackgroundColor(mainBackgroundColor);
  /*
   * This is one of the calls must made to force a ViewGroup to call its
   * draw method instead of just calling the draw method of its children.
   * This is the interior color of the RoundedRectangle. It must be
   * different than the exterior color of the RoundedRectangle or the
   * RoundedRectangle will not call its draw method.
   */
  messageContainer.setInteriorColor(messageBackgroundColor);
  // Add the message to the RoundedRectangle.
  messageContainer.addView(message);

  //
  LinearLayout main = new LinearLayout(this);
  LinearLayout.LayoutParams mainLayoutParams = new LinearLayout.LayoutParams(
    LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  main.setLayoutParams(mainLayoutParams);
  main.setOrientation(LinearLayout.VERTICAL);
  main.setBackgroundColor(mainBackgroundColor);
  main.addView(label);
  main.addView(messageContainer);

  setContentView(main);
 }
}

La classe de l'objet de présentation RoundedRectangle est celle définie ici:

/**
 *  A LinearLayout that draws a rounded rectangle around the child View that was added to it.
 */
package android.example;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.LinearLayout;

/**
 * A LinearLayout that has rounded corners instead of square corners.
 * 
 * @author Danny Remington
 * 
 * @see LinearLayout
 * 
 */
public class RoundedRectangle extends LinearLayout {
 private int mInteriorColor;

 public RoundedRectangle(Context p_context) {
  super(p_context);
 }

 public RoundedRectangle(Context p_context, AttributeSet attributeSet) {
  super(p_context, attributeSet);
 }

 // Listener for the onDraw event that occurs when the Layout is drawn.
 protected void onDraw(Canvas canvas) {
  Rect rect = new Rect(0, 0, getWidth(), getHeight());
  RectF rectF = new RectF(rect);
  DisplayMetrics metrics = new DisplayMetrics();
  Activity activity = (Activity) getContext();
  activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
  float density = metrics.density;
  int arcSize = Math.round(density * 10);

  Paint paint = new Paint();
  paint.setColor(mInteriorColor);

  canvas.drawRoundRect(rectF, arcSize, arcSize, paint);
 }

 /**
  * Set the background color to use inside the RoundedRectangle.
  * 
  * @param Primitive int - The color inside the rounded rectangle.
  */
 public void setInteriorColor(int interiorColor) {
  mInteriorColor = interiorColor;
 }

 /**
  * Get the background color used inside the RoundedRectangle.
  * 
  * @return Primitive int - The color inside the rounded rectangle.
  */
 public int getInteriorColor() {
  return mInteriorColor;
 }

}
Danny Remington - OMS
la source
5

Kotlin

import android.graphics.BitmapFactory
import android.os.Bundle
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory
import kotlinx.android.synthetic.main.activity_main.*

val bitmap = BitmapFactory.decodeResource(resources, R.drawable.myImage)
val rounded = RoundedBitmapDrawableFactory.create(resources, bitmap)
rounded.cornerRadius = 20f
profileImageView.setImageDrawable(rounded)

Pour faire ImageViewCirculaire, nous pouvons changer cornerRadiusavec:

rounded.isCircular = true
Vahid
la source
4

Merci beaucoup pour la première réponse. Voici une version modifiée pour convertir une image rectangulaire en une image carrée (et arrondie) et la couleur de remplissage est passée en paramètre.

public static Bitmap getRoundedBitmap(Bitmap bitmap, int pixels, int color) {

    Bitmap inpBitmap = bitmap;
    int width = 0;
    int height = 0;
    width = inpBitmap.getWidth();
    height = inpBitmap.getHeight();

    if (width <= height) {
        height = width;
    } else {
        width = height;
    }

    Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
    Canvas canvas = new Canvas(output);

    final Paint paint = new Paint();
    final Rect rect = new Rect(0, 0, width, height);
    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(inpBitmap, rect, rect, paint);

    return output;
}
mkm
la source
4

Si vous utilisez Glide Library, cela serait utile:

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));
}
Anirudh
la source
Si vous utilisez Glide version 4 et supérieure, utilisez --- RequestOptions requestOptions = new RequestOptions (); requestOptions = requestOptions.transforms (nouveau CenterCrop (), nouveaux RoundedCorners (16)); Glissez. Avec (itemView.getContext ()) .load (item.getImage ()) .apply (requestOptions) .into (mProgramThumbnail);
B.shruti
3

si votre image est sur Internet, le meilleur moyen est d'utiliser glide et RoundedBitmapDrawableFactory(à partir d'API 21 - mais disponible dans la bibliothèque de support) comme ceci:

 Glide.with(ctx).load(url).asBitmap().centerCrop().into(new BitmapImageViewTarget(imageView) {
    @Override
    protected void setResource(Bitmap res) {
        RoundedBitmapDrawable bitmapDrawable =
             RoundedBitmapDrawableFactory.create(ctx.getResources(), res);
        bitmapDrawable.setCircular(true);//comment this line and uncomment the next line if you dont want it fully cricular
        //circularBitmapDrawable.setCornerRadius(cornerRadius);
        imageView.setImageDrawable(bitmapDrawable);
    }
});
Amir Ziarati
la source
Il s'agit d'une API élégante, cependant, .centerInside semble être manquant, il est donc peut-être préférable d'utiliser xml pour définir de tels paramètres
car
Ceci est également utile lorsque l'image est dans les ressources et que vous devez l'utilisercenterCrop
Artyom
3

vous pouvez utiliser uniquement ImageViewdans votre mise en page et en utilisant glide, vous pouvez appliquer des coins arrondis en utilisant cette méthode.

d'abord dans votre écriture gradle,

compile 'com.github.bumptech.glide:glide:3.7.0'

pour une image aux coins arrondis,

public void loadImageWithCorners(String url, ImageView view) {
    Glide.with(context)
            .load(url)
            .asBitmap()
            .centerCrop()
            .placeholder(R.color.gray)
            .error(R.color.gray)
            .diskCacheStrategy(DiskCacheStrategy.SOURCE)
            .into(new BitmapImageViewTarget(view) {
                @Override
                protected void setResource(Bitmap resource) {
                    RoundedBitmapDrawable circularBitmapDrawable =
                            RoundedBitmapDrawableFactory.create(context.getResources(), resource);
                    circularBitmapDrawable.setCornerRadius(32.0f); // radius for corners
                    view.setImageDrawable(circularBitmapDrawable);
                }
            });
}

méthode d'appel:

loadImageWithCorners("your url","your imageview");
Deep Patel
la source
Cela ajoutera une bibliothèque pour charger des images via une requête HTTP, ce qui n'est pas pertinent pour la question.
creativecreatorormaybenot
Quelle bibliothèque sera chargée? Pour le chargement d'images, vous pouvez utiliser glide et l'extrait de code uniquement en fonction des méthodes et des classes de glide. Aucune autre bibliothèque n'a besoin d'être ajoutée
Deep Patel
Glide est une bibliothèque principalement pour charger des images sur HTTP, mais OP voulait savoir comment arrondir les coins d'un ImageView.
creativecreatorormaybenot
2

Répondez à la question qui est redirigée ici: "Comment créer une ImageView circulaire dans Android?"

public static Bitmap getRoundBitmap(Bitmap bitmap) {

    int min = Math.min(bitmap.getWidth(), bitmap.getHeight());

    Bitmap bitmapRounded = Bitmap.createBitmap(min, min, bitmap.getConfig());

    Canvas canvas = new Canvas(bitmapRounded);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
    canvas.drawRoundRect((new RectF(0.0f, 0.0f, min, min)), min/2, min/2, paint);

    return bitmapRounded;
}
Andrey
la source
2

Avec l'aide de la bibliothèque glide et de la classe RoundedBitmapDrawableFactory , c'est facile à réaliser. Vous devrez peut-être créer une image d'espace réservé circulaire.

    Glide.with(context)
        .load(imgUrl)
        .asBitmap()
        .placeholder(R.drawable.placeholder)
        .error(R.drawable.placeholder)
        .into(new BitmapImageViewTarget(imgProfilePicture) {
            @Override
            protected void setResource(Bitmap resource) {
                RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(context.getResources(),
                        Bitmap.createScaledBitmap(resource, 50, 50, false));
                drawable.setCornerRadius(10); //drawable.setCircular(true);
                imgProfilePicture.setImageDrawable(drawable);
            }
        });
Chitrang
la source
2

Pour ceux qui utilisent Glide et Kotlin, vous pouvez le faire en étendant RequestBuilder

fun <T> GlideRequest<T>.roundCorners(cornerRadius: Int) =
    apply(RequestOptions().transform(RoundedCorners(cornerRadius)))

et utiliser comme;

 GlideApp.with(context)
            .load(url)
            .roundCorners(context.resources.getDimension(R.dimen.radius_in_dp).toInt())
            .into(imgView)
dgngulcan
la source
.roundedCorners ne venant pas avons-nous besoin de configurer autre chose?
Dr aNdRO
avez-vous ajouté la fonction d'extension roundCornerscomme ci-dessus? @ Dr.aNdRO
dgngulcan
Veuillez fournir un bon exemple! Cette réponse prête à confusion!
Junia Montana