Come realizzare un ImageView con angoli arrotondati?


573

In Android, ImageView è un rettangolo per impostazione predefinita. Come posso renderlo un rettangolo arrotondato (ritagliare tutti e 4 gli angoli della mia Bitmap per essere rettangoli arrotondati) in ImageView?


Questo potrebbe essere utile stackoverflow.com/questions/26850780/…
Mangesh

Nascosto sotto le risposte più vecchie e più complicate è quello che penso dovrebbe essere la risposta accettata ora: RoundedBitmapDrawable , aggiunto in v4 Support Library revisione 21.
Jonik

Si può farlo modo più semplice usando solo il CardView con un dentro ImageView - guarda l'esempio qui stackoverflow.com/a/41479670/4516797
Taras Vovkovych

Questa libreria è molto utile.
grrigore,

Controllare questo ora dobbiamo ShapeableImageViewfare circolare o arrotondata IMAGEVIEW stackoverflow.com/a/61086632/7666442
Nilesh Rathod

Risposte:


545

La risposta è abbastanza tardi, ma per chiunque lo stia cercando, puoi fare il seguente codice per arrotondare manualmente gli angoli delle tue immagini.

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

Questo non è il mio codice, ma l'ho usato e funziona meravigliosamente. L'ho usato come aiuto all'interno di una classe ImageHelper e l'ho esteso solo un po 'per passare la quantità di sfumature di cui ho bisogno per una data immagine.

Il codice finale è simile al seguente:

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

Spero che questo aiuti qualcuno!


4
Non funziona per tutti i dispositivi. Devo cambiare ovunque?
Spring Breaker,

7
Ci vogliono quasi 0,03 secondi per farlo per un'immagine 200 * 200, quindi penso che non sia la soluzione migliore.
Jacky,

2
Arrotonda solo gli angoli in alto a sinistra e in alto a destra. Perché ?
Prateek,

1
La soluzione @ vinc3m1 qui github.com/makeramen/RoundedImageView funziona davvero bene! vedi anche la sua risposta ( stackoverflow.com/a/15032283/2048266 )
nommer

16
Non funziona bene quando si cerca di impostare lo scaletype di imageview, solo fitXY funziona, centerCrop e altri mostrano risultati imprevedibili, qualcuno qui ha gli stessi problemi?
Shivansh,

211

Mentre la risposta sopra funziona, Romain Guy (uno sviluppatore Android di base) mostra un metodo migliore nel suo blog che utilizza meno memoria usando uno shader che non crea una copia della bitmap. L'essenza generale della funzionalità è qui:

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

I vantaggi di questo rispetto ad altri metodi è che:

  • non crea una copia separata della bitmap, che utilizza molta memoria con immagini di grandi dimensioni [rispetto alla maggior parte delle altre risposte qui]
  • supporti antialisasing [vs metodo clipPath]
  • supporta alpha [vs xfermode + metodo porterduff]
  • supporta l'accelerazione hardware [vs metodo clipPath]
  • disegna solo una volta sulla tela [vs xfermode e metodi clippath]

Ho creato un RoundedImageView basato su questo codice che avvolge questa logica in un ImageView e aggiunge il ScaleTypesupporto adeguato e un bordo arrotondato opzionale.


nel tuo / example / res / layout / rounded_item.xml perché specifichi un'immagine src quando tutte le tue fonti sono hardcoded? Bella demo, semplicemente eccessiva.
Someone Somewhere

il tuo campione ha un grave problema di memoria insufficiente, proprio come il campione originale di Romain Guy. Non so ancora cosa lo causi, ma proprio come il suo codice, questa è davvero una cosa difficile da trovare. Se non riesci a vedere un arresto anomalo dall'app a causa di OOM, puoi ruotare l'app più volte fino a quando si verifica (dipende dal tuo dispositivo, ROM, ecc ...). Ne ho parlato in passato qui: stackoverflow.com/questions/14109187/…
sviluppatore Android

1
Nessun altro sta segnalando il problema di memoria insufficiente, quindi deve essere qualcosa che stai facendo al di fuori del codice che non è corretto. L'esempio contiene correttamente un set limitato di bitmap nell'adattatore senza ricrearle ogni volta che viene disegnata una vista. L'esempio mostrato qui è uno snippet del metodo draw () nel Drawable, che usa il riferimento alla bitmap originale che contiene e funziona correttamente. È non intende cambiare la bitmap originale, ma solo renderlo con angoli arrotondati. Anche il ritaglio centrale funziona bene nell'esempio.
vinc3m1,

1
Se è possibile fornire schermate o dispositivi in ​​cui non funziona, o addirittura arrivare a offrire una richiesta di correzione e pull, sarebbe molto produttivo. Ho provato a ruotare più volte sui miei dispositivi e la memoria rimane invariata.
vinc3m1

11
Si noti che non funzionerà se la dimensione dell'immagine è superiore a 2048 pixel. Lo shader non supporta una trama più grande di quella.
Gábor,

209

Un altro modo semplice è usare un CardView con il raggio d'angolo e un ImageView all'interno:

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

inserisci qui la descrizione dell'immagine


5
Sembra una buona soluzione. Ma non ritaglia immagini su pre-lecca-lecca.
Nikolai,

1
E se volessimo solo il raggio sugli angoli in alto a sinistra e in alto a destra e non su tutti gli angoli?
Pratik Singhal,

3
Modo molto semplice e intelligente per applicare il bordo della curva in qualsiasi vista.
AMI CHARADAVA,

1
Buona soluzione, ma l'elevazione è supportata solo nel livello 21 API e oltre
Saad Bilal

1
Per disabilitare l'elevazione delle carte usa l'app: cardElevation = "0dp" (non android: elevazione)
Johnny Five,

150

Il taglio a forme arrotondate è stato aggiunto alla Viewclasse in API 21.

Basta fare questo:

  • Crea una forma arrotondata disegnabile, qualcosa del genere:

res / drawable / round_outline.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="10dp" />
    ...
</shape>
  • Imposta il disegno come sfondo del tuo ImageView: android:background="@drawable/round_outline"
  • Secondo questa documentazione , tutto ciò che devi fare è aggiungereandroid:clipToOutline="true"

Sfortunatamente, c'è un bug e quell'attributo XML non è riconosciuto. Fortunatamente, possiamo ancora impostare il clipping in Java:

  • Nella tua attività o frammento: ImageView.setClipToOutline(true)

Ecco come sarà:

inserisci qui la descrizione dell'immagine

Nota:

Questo metodo funziona per qualsiasi forma tracciabile (non solo arrotondata). Aggancerà ImageView a qualsiasi contorno di forma che hai definito nel tuo Drawable xml.

Nota speciale su ImageViews

setClipToOutline()funziona solo quando lo sfondo della vista è impostato su una forma tracciabile. Se esiste questa forma di sfondo, Visualizza considera il contorno della forma come i bordi per scopi di ritaglio e ombreggiatura.

Ciò significa che se si desidera utilizzare setClipToOutline()per arrotondare gli angoli su un ImageView, l'immagine deve essere impostata utilizzando android:srcinvece di android:background(poiché lo sfondo deve essere impostato sulla forma arrotondata). Se DEVI utilizzare lo sfondo per impostare l'immagine anziché src, puoi utilizzare questa soluzione alternativa:

  • Crea un layout e imposta lo sfondo sul tuo disegno disegnabile
  • Avvolgi quel layout attorno a ImageView (senza imbottitura)
  • ImageView (incluso qualsiasi altra cosa nel layout) ora verrà visualizzato con una forma di layout arrotondata.

10
Errore: (x) Nessun identificatore di risorsa trovato per l'attributo 'clipToOutline' nel pacchetto 'android'
Anu Martin

7
Invece android:clipToOutline, si deve usare android:outlineProvider="background".
WindRider,

2
Un'altra ragione per cui "amo" così tanto Google è che questo bug ha quasi la mia età e risiede ancora nel suo piccolo mondo. Google sembra non dare alcuna spiegazione al riguardo))
Farid

1
Sembra che non abbia successo con questo metodo quando imposto solo arrotondato topleft e topRight corner nella forma di sfondo.
Peterdk,

@AnuMartin questo è un problema noto - issuetracker.google.com/issues/37036728
Vadim Kotov

132

Nella v21 della libreria Support ora esiste una soluzione a questo: si chiama RoundedBitmapDrawable .

Fondamentalmente è proprio come un normale Drawable tranne che gli dai un raggio d'angolo per il ritaglio con:

setCornerRadius(float cornerRadius)

Quindi, a partire da Bitmap srce un obiettivo ImageView, sarebbe simile a questo:

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

3
Grazie mille, ecco il prossimo passo: stackoverflow.com/questions/24878740/…
David d C e Freitas

in realtà c'è android.support.v4.graphics.drawable.RoundedBitmapDrawableFactoryquindi v4lo supporta anche.
pesce morto

2
@deadfish sì è nella v4libreria di supporto ma non fino REVISION 21alla libreria di supporto
tyczj

3
Questa soluzione è semplice e aggiornata. Richiede la minima quantità di codice e ha una grande estensibilità. Può lavorare con immagini da file locali, disegni cache memorizzati o anche con NetworkImageView di Volley. Sono pienamente d'accordo sul fatto che questa dovrebbe essere la risposta accettata al giorno d'oggi, come ha sottolineato @Jonik.
Katie,

2
Sfortunatamente non funziona con scaleType centerCrop(support library v25.3.1)
rocknow

67

Ho fatto da ImageView personalizzato:

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

Come usare:

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

Produzione:

inserisci qui la descrizione dell'immagine

Spero che questo ti possa aiutare.


questo rende l'immagine sfocata
Amit Hooda,

2
funziona anche con Android: scaleType = "centerCrop", semplice, non crea nuova bitmap. Grazie!
ernazm

1
@Hiren Questa soluzione funziona bene con ImageView con un'immagine di sfondo. Ma non funziona per ImageViews che ha solo il colore di sfondo e nessuna immagine. Potete per favore dirmi perché questo sta accadendo?
user2991413

Canvas.clipPath()può causare java.lang.UnsupportedOperationExceptionin alcuni casi. Vedi stackoverflow.com/questions/13248904/…
Artyom il

1
Questa soluzione funziona solo con l'immagine impostata con android:background, ma non android:src.
CoolMind

65

Una rapida soluzione XML -

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

È possibile impostare la larghezza, l'altezza e il raggio desiderati su CardView e scaleType su ImageView.

Con AndroidX, utilizzare <androidx.cardview.widget.CardView>


4
questo approccio ha funzionato nel mio caso con androidx.cardview.widget.CardView
Ivan il

7
Non sei sicuro del perché questo non abbia più voti? Secondo me la migliore soluzione senza librerie e tonnellate di codice di merda (anche se nel mio caso ho usato il ridimensionamento centerCrop).
ThemBones

1
Non ci sono ancora molti voti, perché è una nuova risposta. Ma ho messo il mio +1 per spostarlo presto! Grazie!
Micer,

tuttavia, funziona ma qui l'immagine si allungherà a causa scaleType="fitXY"e non sembra corretta @ThemBones
WIZARD

@WIZARD ecco perché ho detto che puoi impostare la scala desiderata Digita su ImageView
Chirag Mittal

57

Ho scoperto che entrambi i metodi sono stati molto utili nel trovare una soluzione funzionante. Ecco la mia versione composita, che è indipendente dai pixel e ti permette di avere degli angoli quadrati con il resto degli angoli che hanno lo stesso raggio (che è il solito caso d'uso). Grazie a entrambe le soluzioni sopra:

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

Inoltre, ho ignorato ImageView per inserirlo in modo da poterlo definire in XML. Potresti voler aggiungere alcune delle logiche che la super chiamata fa qui, ma l'ho commentato perché non è utile nel mio caso.

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

Spero che sia di aiuto!


4
piuttosto fantastico, soprattutto estendendo ImageView
Someone Somewhere

2
Un modo semplice per mantenere la logica di ImageView # onDraw () consiste nell'impostare la bitmap dell'angolo arrotondato sul disegno di ImageView e lasciare super.onDraw () per disegnare la bitmap. Ho creato una classe RoundedCornerImageView e il suo esempio di utilizzo è qui . Si noti che getRoundedCornerBitmap () che ho usato non è indipendente dai pixel.
umbalaconmeogia

Grazie per il RoundedCornerImageView. L'ho usato ma modificato per essere indipendente dalla densità di pixel.
PacificSky

Il codice sorgente di RoundedCornerImageView di umba è qui: code.google.com/p/android-batsg/source/browse/trunk/…
Someone Somewhere

@Caspar Harmer funziona bene solo 1 modifica ... ci sono quattro condizioni ... basta cambiarle come se avessi impostato vero, vero, falso, falso imposterà l'angolo inferiore invece dell'angolo superiore ... altrimenti il ​​codice funziona bene.so squareTL e squareTR sono condizioni per rispettivamente rispettivamente squareBL e squareBR e vica-versa.
TheFlash,

48

Immagine arrotondata Utilizzo ImageLoader qui

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

Oppure puoi utilizzare PicassoLibrary da 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);

puoi scaricare il file RoundedTransformation qui qui


1
Immagine non visualizzata
Amit Thaper,

3
Quello di Picasso Library è buono e molto facile da implementare, grazie mille +1
Hitesh

3
La libreria Picasso sembra non trasformare l'immagine "segnaposto" e "errore", quindi se l'immagine non riesce a caricare (errore) o impiega un po 'a caricarsi inizialmente (segnaposto), non visualizzerà l'immagine come un'immagine arrotondata. github.com/square/picasso/issues/337
Pelpotronic

Altre utili trasformazioni di Picasso sono fornite da questa libreria, che contiene anche una RoundedCornersTransformation: github.com/wasabeef/picasso-transformations
Massimo

Non funziona con le immagini ritagliate in Univ. Caricatore di immagini.
Anno

26

Poiché tutte le risposte mi sono sembrate troppo complicate solo per gli angoli arrotondati, ho pensato e ho trovato un'altra soluzione che penso valga la pena condividere, solo con XML nel caso in cui tu abbia un po 'di spazio attorno all'immagine:

Crea una forma bordata con contenuto trasparente come questo:

<?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> 

Quindi in un RelativeLayout puoi prima posizionare l'immagine e poi nella stessa posizione sopra la forma con un altro ImageView. La forma della copertina dovrebbe essere di dimensioni maggiori in base alla larghezza del bordo. Fai attenzione a prendere un raggio d'angolo maggiore quando viene definito il raggio esterno, ma il raggio interno è ciò che copre l'immagine.

Spero che aiuti anche qualcuno.

Modifica come da richiesta CQM il relativo esempio di layout:

<?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>

puoi approfondire questo con più codice, in particolare cosa si sta facendo con la seconda vista dell'immagine e dove viene applicato il codice XML "forma delimitata" (come src o come sfondo?) qui diverse domande. Voglio questa soluzione poiché mi permetterà di controllare tutti e quattro gli angoli in modo indipendente
CQM,

1
Sebbene sembri una risposta semplice, sfortunatamente aggiunge margine attorno alla vista "mascherata" dell'immagine che è indesiderabile effetto collaterale.
Abdalrahman Shatou,

sì, ma lo stesso funziona con un ImageView basato su un PNG-Drawable con angoli arrotondati e sfondo trasparente o un 9-Patch-Drawable se hai un aspetto indefinito.
Christian,

Sto facendo lo stesso, e il suo funzionamento; disposto a sapere se non creerà alcun problema con l'orientamento e le diverse dimensioni del telefono?
aperto e gratuito il

Se si mantengono le dimensioni l'una rispetto all'altra, ciò non dovrebbe creare problemi.
Christian,

22

A partire dalla versione 1.2.0-alpha03della libreria dei componenti materiali c'è il nuovo ShapeableImageView.

Puoi usare qualcosa come:

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

con:

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

O programmaticamente:

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

inserisci qui la descrizione dell'immagine


Se l'immagine ha un colore di sfondo, questo attualmente produce il colore di sfondo da far apparire sotto gli angoli arrotondati. Ciò ignora anche la proprietà scaleType sull'immagine.
entrata il

14

La mia implementazione di ImageView con il widget degli angoli arrotondati, che (giù || su) dimensiona l'immagine alle dimensioni richieste. Utilizza il codice di 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);

    }

}

12
Da dove proviene ImageUtilities?
JasonWyatt,

1
@JasonWyatt vedi post di sorrodos qui sotto
Damjan,

12

Di recente, esiste un altro modo: utilizzare l'API generata di Glide . Ci vuole un po 'di lavoro iniziale ma poi ti dà tutta la potenza di Glide con la flessibilità di fare qualsiasi cosa perché scrivi il codice attuale, quindi penso che sia una buona soluzione a lungo termine. Inoltre, l'utilizzo è molto semplice e pulito.

Innanzitutto, installa Glide versione 4+:

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

Quindi crea la classe del modulo app Glid per attivare l'elaborazione delle annotazioni:

@GlideModule
public final class MyAppGlideModule extends AppGlideModule {}

Quindi crea l'estensione Glide che effettivamente fa il lavoro. Puoi personalizzarlo per fare quello che vuoi:

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

Dopo aver aggiunto questi file, crea il tuo progetto.

Quindi usalo nel tuo codice in questo modo:

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

Non dimenticare di aggiungere uno spazio tra RequestOptionse optionsin params
StevenTB

Fatto. Grazie per l'input.
Sir Codesalot,

.roundedCorners che non arrivano, dobbiamo impostare qualcos'altro? Anche dopo aver ricostruito il progetto
Dr. aNdRO il

Questo ha funzionato per me, grazie. Ho trovato più semplice evitare di usare la @GlideExtensionclasse annotata e sono andato solo .transform(new RoundedCorners(px))dove pxè lo stesso ( int px = Math.round(cornerRadius * (context.getResources().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));).
Michael Osofsky,

10

C'è una libreria interessante che ti consente di modellare le visualizzazioni delle immagini.

Ecco un esempio:

<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"/>

Definizione della forma:

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

Risultato:

risultato


1
Questo è fantastico, e fa molto di più, come puoi aggiungere un bordo e usare qualsiasi forma
Adam Kis

8

Ecco un semplice esempio che sovrascrive imageView, quindi puoi anche usarlo nella progettazione del layout per visualizzare l'anteprima.

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

Questo è per una soluzione rapida. Il raggio viene utilizzato su tutti gli angoli e si basa sulla percentuale della larghezza della bitmap.

Ho appena ignorato setImageDrawablee utilizzato il metodo support v4 per il disegno bitmap arrotondato.

Uso:

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

Anteprima con imageView e imageView personalizzati:

inserisci qui la descrizione dell'immagine


Funziona in ogni situazione, grazie. Mi hai salvato la giornata.
Mehul Solanki,

7

Dovresti estendere ImageViewe disegnare il tuo rettangolo arrotondato.

Se si desidera una cornice attorno all'immagine, è anche possibile sovrapporre la cornice arrotondata nella parte superiore della vista dell'immagine nel layout.

[modifica] Sovrapponi la cornice per op sull'immagine originale, usando FrameLayoutad esempio un. Il primo elemento di FrameLayoutsarà l'immagine che vuoi visualizzare arrotondata. Quindi aggiungine un altro ImageViewcon la cornice. Il secondo ImageViewverrà visualizzato sopra l'originale ImageViewe quindi Android disegnerà i suoi contenuti sopra l'originale ImageView.


Grazie. Ma esiste solo il metodo setDrawable per ImageView, come posso impostareDrawable di ImageView sul contenuto della mia immagine e quindi sovrapporre una cornice arrotondata sopra a ImageView?
michael

Mi dispiace, non ero chiaro. Intendevo sovrapporre il layout: quindi (es.) Usa un FrameLayoutput ImageViewin esso e aggiungine un altro ImageViewcon la cornice arrotondata. In questo modo il primo ImageViewvisualizzerà l'immagine selezionata e il secondo ImageFramevisualizzerà la cornice arrotondata.
MrSnowflake,

Corretto: con FrameLayout è possibile sovrapporre un'immagine / vista a un'altra. Puoi anche utilizzare il tag android: foreground di FrameLayout.
Richard Le Mesurier,

7

Romain Guy è dove si trova.

Versione ridotta come segue.

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

purtroppo, anche se funziona, ma proprio come il resto delle soluzioni qui, crea una nuova bitmap invece di utilizzare quella corrente.
sviluppatore Android

non proprio. bitmapRounded verrebbe usato più e più volte. se hai avuto accesso all'area di disegno, puoi utilizzare direttamente il metodo di disegno invece di generare una nuova bitmap.
Alex

Come si fa a farlo? supponiamo che io non usi alcun disegno speciale e gestisca solo una singola bitmap e usi setImageBitmap alla fine del processo. come raggiungerei una cosa del genere?
sviluppatore Android

guarda l'esempio di romain guy curious-creature.org/2012/12/11/… e prova l'
Alex

entrambi non cambiano la bitmap, ma la avvolgono usando un disegno personalizzato e una visualizzazione immagine personalizzata. questo non è quello che ho chiesto. ho chiesto come si modifica la bitmap stessa.
sviluppatore Android

7

Questa soluzione xml pura è stata abbastanza buona nel mio caso. http://www.techrepublic.com/article/pro-tip-round-corners-on-an-android-imageview-with-this-hack/

MODIFICARE

Ecco la risposta in breve:

Nella cartella / res / drawable, crea un file frame.xml. In esso, definiamo un semplice rettangolo con angoli arrotondati e un centro trasparente .

<?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>

Nel tuo file di layout aggiungi un LinearLayout che contiene un ImageView standard, nonché un FrameLayout nidificato. FrameLayout utilizza l'imbottitura e il disegno personalizzato per dare l'illusione di angoli arrotondati.

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

bella idea, l'ho usato per mostrare angoli di ImageView non pari
Gal Rom

6

Puntelli a George Walters II sopra, ho appena preso la sua risposta e l'ho estesa un po 'per supportare gli angoli individuali in modo diverso. Questo potrebbe essere ulteriormente ottimizzato (alcuni dei rects target si sovrappongono), ma non molto.

So che questo thread è un po 'vecchio, ma è uno dei migliori risultati per le query su Google su come arrotondare gli angoli di ImageViews su 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;
}

+1 per l'aggiunta del moltiplicatore di densità e l'aggiunta del supporto per gli angoli di arrotondamento individuali. In realtà ho usato la soluzione in alto, poiché la tua soluzione non ha funzionato del tutto, ma è stata molto utile! Vedi la mia soluzione composita di seguito:
Caspar Harmer

6

Applica una forma al tuo imageViewcome di seguito:

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

potrebbe essere utile per il tuo amico.


6

Perché non tagliare draw()?

Ecco la mia soluzione:

  • Estendi RelativeLayout con ritaglio
  • Inserisci ImageView (o altre viste) nel layout:

Codice:

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

}

1
Mi piace questo approccio. L'ho usato per creare il mio RoundImageView. Grazie per questo.
Pascal,

Questo non funziona con l'accelerazione hardward attivata, giusto? Non ho visto una soluzione semplice ...
secureboot

Puoi per favore mostrare come farlo, avendo il risultato come un disegno, avere la possibilità di aggiungere un contorno (tratto AKA) attorno al contenuto e avere anche la possibilità di fare solo alcuni degli angoli da arrotondare?
Sviluppatore Android

5

Di seguito viene creato un oggetto layout di rettangolo arrotondato che disegna un rettangolo arrotondato attorno a tutti gli oggetti figlio che vengono inseriti in esso. Viene inoltre illustrato come creare viste e layout a livello di codice senza utilizzare i file xml di layout.

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 per l'oggetto layout RoundedRectangle è come definita qui:

/**
 *  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;
 }

}

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)

Per rendere ImageViewcircolare possiamo cambiare cornerRadiuscon:

rounded.isCircular = true

4

Grazie mille per la prima risposta. Ecco una versione modificata per convertire un'immagine rettangolare in una quadrata (e arrotondata) e il colore di riempimento viene passato come parametro.

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

4

Se stai usando Glide Library questo sarebbe 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));
}

Se usi Glide versione 4 e successive usa --- RequestOptions requestOptions = new RequestOptions (); requestOptions = requestOptions.transforms (new CenterCrop (), new RoundedCorners (16)); Glide.with (itemView.getContext ()) .load (item.getImage ()) .apply (requestOptions) .into (mProgramThumbnail);
B.shruti,

3

se la tua immagine è su internet il modo migliore è usare glide e RoundedBitmapDrawableFactory(da API 21 - ma disponibile nella libreria di supporto) in questo modo:

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

Si tratta di un'API elegante, tuttavia .centerInside sembra mancare, quindi è forse meglio usare xml per definire tali parametri
carl

Questo è utile anche quando l'immagine è nelle risorse e devi usarlacenterCrop
Artyom il

3

puoi usare solo ImageViewnel tuo layout e usando glide, puoi applicare gli angoli arrotondati usando questo metodo.

prima nella tua scrittura di laurea,

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

per immagine con angoli arrotondati,

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

metodo di chiamata:

loadImageWithCorners("your url","your imageview");

Ciò aggiungerà una libreria per il caricamento di immagini tramite richiesta HTTP, che non è rilevante per la domanda.
creativecreatorormaybenot

Quale libreria verrà caricata? Per il caricamento delle immagini è possibile utilizzare la planata e lo snippet basandosi esclusivamente su metodi e classi della planata stessa. Non è necessario aggiungere altre biblioteche
Deep Patel

Glide è una libreria principalmente per il caricamento di immagini su HTTP, ma OP ha voluto sapere come arrotondare gli angoli di un ImageView.
creativecreatorormaybenot

2

Risposta per la domanda che viene reindirizzata qui: "Come creare un ImageView circolare in 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;
}

2

Con l'aiuto della libreria glide e della classe RoundedBitmapDrawableFactory è facile da raggiungere. Potrebbe essere necessario creare un'immagine segnaposto circolare.

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

2

Per quelli che usano Glide e Kotlin, puoi farlo estendendo RequestBuilder

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

e usa come;

 GlideApp.with(context)
            .load(url)
            .roundCorners(context.resources.getDimension(R.dimen.radius_in_dp).toInt())
            .into(imgView)

.roundedCorners che non arrivano, dobbiamo impostare qualcos'altro?
Dr. aNdRO,

hai aggiunto la funzione di estensione roundCornerscome sopra? @ Dr.aNdRO
dgngulcan il

Si prega di fornire l'esempio corretto! Questa risposta è confusa!
Junia Montana,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.