Como arredondar uma imagem com a biblioteca Glide?


197

Então, alguém sabe como exibir uma imagem com cantos arredondados com o Glide? Estou carregando uma imagem com o Glide, mas não sei como passar parâmetros arredondados para esta biblioteca.

Eu preciso exibir a imagem como no exemplo a seguir:

insira a descrição da imagem aqui


2
Eu uso o github.com/hdodenhof/CircleImageView para exibição de imagem
rondada

1
Eu sei como usar o Glide lib com o CircleImageView, mas busco a maneira possível de fazer isso apenas com o Glide lib. Existe algum método no Glide lib para fazer isso ou não é suportado?
precisa saber é o seguinte

Respostas:


486

Glide V4:

    Glide.with(context)
        .load(url)
        .circleCrop()
        .into(imageView);

Glide V3:

Você pode usar RoundedBitmapDrawablepara imagens circulares com Glide. Nenhum ImageView personalizado é necessário.

 Glide.with(context).load(url).asBitmap().centerCrop().into(new BitmapImageViewTarget(imageView) {
        @Override
        protected void setResource(Bitmap resource) {
            RoundedBitmapDrawable circularBitmapDrawable =
                    RoundedBitmapDrawableFactory.create(context.getResources(), resource);
            circularBitmapDrawable.setCircular(true);
            imageView.setImageDrawable(circularBitmapDrawable);
        }
    });

6
isso não cria uma borda, no entanto.
ZakTaccardi

1
@ jimmy0251 Não, você não pode. As gavetas deslizantes não são BitmapDrawables. São desenháveis ​​de transição e deslizantes planeados que passam do espaço reservado para a imagem real. O RoundedBitmapDrawable não pode lidar com isso.
22816 Greg Ennis

7
definir plano de fundo com forma drawable oval. e dê preenchimento à visualização de imagem para criar bordas.
Lalit Jadav

2
Se você tiver algum problema, verifique a próxima solução de Roman Samoylenko que funciona.
Pabel

1
Em vez de .centerCrop()você provavelmente quer dizer.circleCrop()
Thanasis Kapelonis

66

Confira este post, glide vs picasso ...
Editar : o post vinculado não indica uma diferença importante nas bibliotecas. Glide faz a reciclagem automaticamente. Veja o comentário de TWiStErRob para mais.

Glide.with(this).load(URL).transform(new CircleTransform(context)).into(imageView);

public static class CircleTransform extends BitmapTransformation {
    public CircleTransform(Context context) {
        super(context);
    }

    @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        return circleCrop(pool, toTransform);
    }

    private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
        if (source == null) return null;

        int size = Math.min(source.getWidth(), source.getHeight());
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;

        // TODO this could be acquired from the pool too
        Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);

        Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
        if (result == null) {
            result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(result);
        Paint paint = new Paint();
        paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        float r = size / 2f;
        canvas.drawCircle(r, r, r, paint);
        return result;
    }

    @Override public String getId() {
        return getClass().getName();
    }
} 

Soa interessante. Funciona bem com o Outline da API 21?
Teovald

hmm, eu posso usar isso então. Vou tentar simplesmente usar uma exibição personalizada, porém, gostaria de não precisar criar um segundo bitmap :). Além disso, você deve sempre utilizar a piscina bitmap, a fim de tentar obter um bitmap de lá :)
Teovald

Cuidado ao usar public String getId()a maneira mostrada no código, pois retorna o mesmo ID para todas as imagens e, portanto, pode acontecer que o glide defina imagens arredondadas antigas, enquanto que sem transformações, ele definirá a imagem correta! Eu não sei como o glide funciona, mas parece que ele armazena em cache as transformações das imagens (para evitar cálculos difíceis, presumo). E o id é usado como o id da imagem transformada. Eu adicionei um URL de imagem ao construtor e fiz o método mencionado retornando a identificação resultante, como:this.id = String.format("%s:%s",this.getClass().getSimpleName(),id);
Stan

2
O único requisito básico para os IDs de transformação é que eles sejam exclusivos entre todas as Transformações, portanto, o uso aqui é correto. As chaves de cache incluirão o ID de origem e o de transformação, portanto, o ID de transformação é um mixin e não um substituto. Veja github.com/bumptech/glide/wiki/…
Sam Judd

4
Existe uma maneira de aplicar a transformação ao espaço reservado?
Sinigami

45

A maneira mais fácil (requer Glide 4.xx)

Glide.with(context).load(uri).apply(RequestOptions().circleCrop()).into(imageView)

isso nem compila ... RequestOptions ()?
Rafael Lima

3
@RafaelLima Está escrito em Kotlin.
Roman Samoylenko

1
Observe, isso .apply()vai depois .load().
Johnny Cinco

é RequestOptions.circleCropTransform (), não RequestOptions ().
Sorri

você precisa escrever Glide.with (context) .load (uri) .apply (circleCrop ()). into (imageView) veja a função apply.
Jaspal

25

Tente desta maneira

código

Glide.with(this)
    .load(R.drawable.thumbnail)
    .bitmapTransform(new CropCircleTransformation(this))
    .into(mProfile);

XML

<ImageView
  android:id="@+id/img_profile"
  android:layout_width="76dp"
  android:layout_height="76dp"
  android:background="@drawable/all_circle_white_bg"
  android:padding="1dp"/>

all_circle_white_bg.xml

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

9

é muito simples, eu vi a biblioteca Glide, sua muito boa biblioteca e redação na biblioteca do Google

use esta biblioteca para visualização de imagem arredondada

https://github.com/hdodenhof/CircleImageView

agora

// Para uma visão simples:

 @Override
 public void onCreate(Bundle savedInstanceState) {
  ...

  CircleImageView civProfilePic = (CircleImageView)findViewById(R.id.ivProfile);
  Glide.load("http://goo.gl/h8qOq7").into(civProfilePic);
}

// Para uma lista:

@Override
public View getView(int position, View recycled, ViewGroup container) {
final ImageView myImageView;
 if (recycled == null) {
    myImageView = (CircleImageView) inflater.inflate(R.layout.my_image_view,
            container, false);
} else {
    myImageView = (CircleImageView) recycled;
}

String url = myUrls.get(position);

Glide.load(url)
    .centerCrop()
    .placeholder(R.drawable.loading_spinner)
    .animate(R.anim.fade_in)
    .into(myImageView);

  return myImageView;
}

e em XML

<de.hdodenhof.circleimageview.CircleImageView
   android:id="@+id/ivProfile
   android:layout_width="160dp"
   android:layout_height="160dp"
   android:layout_centerInParent="true"
   android:src="@drawable/hugh"
   app:border_width="2dp"
   app:border_color="@color/dark" />

2
Como mencionado na resposta anterior, comente dessa maneira também não funciona bem. Pelo menos para 'de.hdodenhof: circleimageview: 1.2.2' + 'com.github.bumptech.glide: glide: 3.5.2'. Verificado e verificado. Também o mesmo problema com o glide 3.4. + E o circleimageview 1.2.1
Stan

+1 para o .centerCrop (). Trabalhou para mim com o DiamondImageView mais .asBitmap ().
Felippe

1
Requer a chamada .dontAnimate () em deslize que não é aceitável
Greg Ennis

+1 Mas note também que os Carregando Internet Imagens com Glide
ouriço

9

As outras soluções não funcionaram para mim. Descobri que todos eles têm desvantagens significativas:

  • Soluções usando transformações de deslizamento não funcionam com espaços reservados
  • Soluções usando vistas de imagem arredondadas não funcionam com animações (por exemplo, crossfade)
  • Soluções que usam um método genérico de um pai ou mãe que prende seus filhos (isto é, a resposta aceita aqui ) não funcionam bem com o glide

É realmente interessante que, depois de me atrapalhar com isso, encontrei a página da biblioteca Fresco sobre cantos arredondados e círculos nos quais eles listam basicamente as mesmas limitações e concluem com a declaração:

não existe uma solução realmente boa para arredondar as esquinas no Android e é preciso escolher entre as compensações acima mencionadas

Inacreditável que ainda não tenhamos uma solução real. Eu tenho uma solução alternativa com base no link que eu coloquei acima. A desvantagem dessa abordagem é que ela assume que seu plano de fundo é uma cor sólida (os cantos não são realmente transparentes). Você usaria assim:

<RoundedCornerLayout ...>
    <ImageView ...>
</RoundedCornerLayout>

A essência está aqui e o código completo aqui:

public class RoundedCornerLayout extends RelativeLayout {
    private Bitmap maskBitmap;
    private Paint paint;
    private float cornerRadius;

    public RoundedCornerLayout(Context context) {
        super(context);
        init(context, null, 0);
    }

    public RoundedCornerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

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

    private void init(Context context, AttributeSet attrs, int defStyle) {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);

        setWillNotDraw(false);
    }

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

        if (maskBitmap == null) {
            // This corner radius assumes the image width == height and you want it to be circular
            // Otherwise, customize the radius as needed
            cornerRadius = canvas.getWidth() / 2;
            maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
        }

        canvas.drawBitmap(maskBitmap, 0f, 0f, paint);
    }

    private Bitmap createMask(int width, int height) {
        Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mask);

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.WHITE); // TODO set your background color as needed

        canvas.drawRect(0, 0, width, height, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);

        return mask;
    }
}

6

Agora, no Glide V4, você pode usar diretamente o CircleCrop ()

Glide.with(fragment)
  .load(url)
  .circleCrop()
  .into(imageView);

Tipos incorporados

  • CenterCrop
  • FitCenter
  • CircleCrop

5

Use essa transformação, ela funcionará bem.

public class CircleTransform extends BitmapTransformation {
public CircleTransform(Context context) {
    super(context);
}

@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
    return circleCrop(pool, toTransform);
}

private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
    if (source == null) return null;

    int borderColor = ColorUtils.setAlphaComponent(Color.WHITE, 0xFF);
    int borderRadius = 3;

    int size = Math.min(source.getWidth(), source.getHeight());
    int x = (source.getWidth() - size) / 2;
    int y = (source.getHeight() - size) / 2;

    // TODO this could be acquired from the pool too
    Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
    if (squared != source) {
        source.recycle();
    }

    Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
    if (result == null) {
        result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
    }

    Canvas canvas = new Canvas(result);
    Paint paint = new Paint();
    paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
    paint.setAntiAlias(true);
    float r = size / 2f;
    canvas.drawCircle(r, r, r, paint);

    // Prepare the background
    Paint paintBg = new Paint();
    paintBg.setColor(borderColor);
    paintBg.setAntiAlias(true);

    // Draw the background circle
    canvas.drawCircle(r, r, r, paintBg);

    // Draw the image smaller than the background so a little border will be seen
    canvas.drawCircle(r, r, r - borderRadius, paint);

    squared.recycle();

    return result;
}

@Override
public String getId() {
    return getClass().getName();
}} 

5

Para Glide 4.xx

usar

Glide
  .with(context)
  .load(uri)
  .apply(
      RequestOptions()
        .circleCrop())
  .into(imageView)

do doc afirmou que

Imagens redondas: Sabe-se que CircleImageView / CircularImageView / RoundedImageView tem problemas com TransitionDrawable (.crossFade () com .thumbnail () ou .placeholder ()) e GIFs animados, use um BitmapTransformation (.circleCrop () estará disponível na v4) ou .dontAnimate () para corrigir o problema


4

De acordo com esta resposta, a maneira mais fácil nos dois idiomas é:

Kotlin:

Glide.with(context).load(uri).apply(RequestOptions().circleCrop()).into(imageView)

Java:

Glide.with(context).load(uri).apply(new RequestOptions().circleCrop()).into(imageView)

Isso funciona no Glide 4.XX


4

A resposta de Roman Samoylenko estava correta, exceto que a função foi alterada. A resposta correta é

Glide.with(context)
                .load(yourImage)
                .apply(RequestOptions.circleCropTransform())
                .into(imageView);

3

Encontrei uma solução fácil e simples para adicionar borda sobre visualização de imagem na qual a cor deseja definir ou adicionar gradiente sobre a imagem.

PASSOS:

  1. Pegue um layout de quadro e adicione duas imagens. Você pode definir o tamanho conforme sua necessidade. Para imgPlaceHolder, você precisa de uma imagem ou cor branca que deseja definir.

        <ImageView
            android:id="@+id/imgPlaceHolder"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:src="@drawable/white_bg"/>

        <ImageView
            android:id="@+id/imgPic"
            android:layout_width="190dp"
            android:layout_height="190dp"
            android:layout_gravity="center"
            android:src="@drawable/image01"/>
    </FrameLayout>
  1. Depois de colocar esse código no arquivo xml, coloque a linha abaixo no arquivo java.

    Glide.with(this).load(R.drawable.image01).asBitmap().centerCrop().into(new BitmapImageViewTarget(imgPic) {
        @Override
        protected void setResource(Bitmap resource) {
            RoundedBitmapDrawable circularBitmapDrawable =
                    RoundedBitmapDrawableFactory.create(getResources(), resource);
            circularBitmapDrawable.setCircular(true);
            imageView.setImageDrawable(circularBitmapDrawable);
        }
    });
    
    Glide.with(this).load(R.drawable.white_bg).asBitmap().centerCrop().into(new BitmapImageViewTarget(imgPlaceHolder) {
        @Override
        protected void setResource(Bitmap resource) {
            RoundedBitmapDrawable circularBitmapDrawable =
                    RoundedBitmapDrawableFactory.create(getResources(), resource);
            circularBitmapDrawable.setCircular(true);
            imgTemp2.setImageDrawable(circularBitmapDrawable);
        }
    });

Isso tornará a borda da visualização de imagem simplesmente sem preenchimento e margem extras.

NOTA : A imagem em branco é obrigatória para borda, caso contrário não funcionará.

Happy codding :)


3

Com a biblioteca glide, você pode usar este código:

Glide.with(context)
    .load(imageUrl)
    .asBitmap()
    .placeholder(R.drawable.user_pic)
    .centerCrop()
    .into(new BitmapImageViewTarget(img_profPic) {
        @Override
        protected void setResource(Bitmap resource) {
            RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory.create(context.getResources(), resource);

            circularBitmapDrawable.setCircular(true);
            img_profPic.setImageDrawable(circularBitmapDrawable);
        }
    });

você também pode criar uma imagem arredondada usando a biblioteca glid.
Priti

2

Eu estava procurando por ele antes e fiz da maneira mais fácil, espero que você goste disso.

 //crete this method into your Utils class and call this method wherever you want to use.
    //you can set these placeHolder() and error() image static as well. I made it as comment inside this method, then no need to use [placeHolderUrl and errorImageUrl] parameters. remove it from this method.
    public static void loadImage(final Activity context, ImageView imageView, String url, int placeHolderUrl, int errorImageUrl) {
        if (context == null || context.isDestroyed()) return;

        //placeHolderUrl=R.drawable.ic_user;
        //errorImageUrl=R.drawable.ic_error;
            Glide.with(context) //passing context
                    .load(getFullUrl(url)) //passing your url to load image.
                    .placeholder(placeHolderUrl) //this would be your default image (like default profile or logo etc). it would be loaded at initial time and it will replace with your loaded image once glide successfully load image using url.
                    .error(errorImageUrl)//in case of any glide exception or not able to download then this image will be appear . if you won't mention this error() then nothing to worry placeHolder image would be remain as it is.
                    .diskCacheStrategy(DiskCacheStrategy.ALL) //using to load into cache then second time it will load fast.
                    .transform(new CircleTransform(context))//this CircleTransform class help to crop an image as circle.
                    .animate(R.anim.fade_in) // when image (url) will be loaded by glide then this face in animation help to replace url image in the place of placeHolder (default) image.
                    .fitCenter()//this method help to fit image into center of your ImageView
                    .into(imageView); //pass imageView reference to appear the image.
    } 

CircleTransform.java

  public class CircleTransform extends BitmapTransformation {
    public CircleTransform(Context context) {
        super(context);

        if(context==null)
            return;
    }

    private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
        if (source == null) return null;

        int size = Math.min(source.getWidth(), source.getHeight());
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;


        Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);

        Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
        if (result == null) {
            result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(result);
        Paint paint = new Paint();
        paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        float r = size / 2f;
        canvas.drawCircle(r, r, r, paint);
        return result;
    }

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        return circleCrop(pool, toTransform);
    }

    @Override
    public String getId() {
        return getClass().getName();
    }
}

fade_in.xml para desaparecer na animação.

    <set xmlns:android="http://schemas.android.com/apk/res/android">
<!--THIS ANIMATION IS USING FOR FADE IN -->

<alpha
    android:duration="800"
    android:fromAlpha="0.0"
    android:interpolator="@android:anim/decelerate_interpolator"
    android:toAlpha="1.0" />

finalmente para chamar esse método.

Utils.loadImage(YourClassName.this,mImageView,url,R.drawable.ic_user,R.drawable.ic_error);

2

Você pode simplesmente chamar o construtor RoundedCornersTransformation, que possui a entrada cornerType enum. Como isso:

Glide.with(context)
            .load(bizList.get(position).getCover())
            .bitmapTransform(new RoundedCornersTransformation(context,20,0, RoundedCornersTransformation.CornerType.TOP))
            .into(holder.bizCellCoverImg);

mas primeiro você precisa adicionar Glide Transformations ao seu projeto.


2

Aqui está uma maneira mais modular e mais limpa de circular o seu bitmap no Glide:

  1. Crie uma transformação personalizada estendendo BitmapTransformatione substituindo o transformmétodo como este:

Para Glide 4.xx

public class CircularTransformation extends BitmapTransformation {

@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
    RoundedBitmapDrawable circularBitmapDrawable =
            RoundedBitmapDrawableFactory.create(null, toTransform);
    circularBitmapDrawable.setCircular(true);
    Bitmap bitmap = pool.get(outWidth, outHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    circularBitmapDrawable.setBounds(0, 0, outWidth, outHeight);
    circularBitmapDrawable.draw(canvas);
    return bitmap;
    }

@Override
public void updateDiskCacheKey(MessageDigest messageDigest) {}

}

Para Glide 3.xx

public class CircularTransformation extends BitmapTransformation {

@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
    RoundedBitmapDrawable circularBitmapDrawable =
            RoundedBitmapDrawableFactory.create(null, toTransform);
    circularBitmapDrawable.setCircular(true);
    Bitmap bitmap = pool.get(outWidth, outHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    circularBitmapDrawable.setBounds(0, 0, outWidth, outHeight);
    circularBitmapDrawable.draw(canvas);
    return bitmap;
    }

@Override
public String getId() {
    // Return some id that uniquely identifies your transformation.
    return "CircularTransformation";
    }

}
  1. Em seguida, defina-o no construtor Glide, onde você precisar:
Glide.with(yourActivity)
   .load(yourUrl)
   .asBitmap()
   .transform(new CircularTransformation())
   .into(yourView);

Espero que isto ajude :)


2
private void setContactImage(@NonNull ViewHolder holder, ClsContactDetails clsContactDetails) {
    Glide.with(context).load(clsContactDetails.getPic())
        .apply(new RequestOptions().centerCrop().circleCrop().placeholder(R.mipmap.ic_launcher)).into(holder.ivPersonImage);
}

2
implementation 'com.github.bumptech.glide:glide:4.8.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'


RequestOptions options=new RequestOptions();
        options.centerCrop().placeholder(getResources().getDrawable(R.drawable.user_placeholder));
        Glide.with(this)
                .load(preferenceSingleTon.getImage())
                .apply(options)
                .into(ProfileImage);

2

Cortar em círculo + espaço reservado + crossfade

 Glide.with(context!!)
                    .load(randomImage)
                    .apply(RequestOptions.bitmapTransform(CircleCrop()).error(R.drawable.nyancat_animated))
                    .transition(DrawableTransitionOptions()
                            .crossFade())
                    .into(picture)

insira a descrição da imagem aqui


1

Glide versão 4.6.1

Glide.with(context)
.load(url)
.apply(RequestOptions.bitmapTransform(new CircleCrop()))
.into(imageView);

1

Nesse caso, preciso adicionar sombras e a elevação do imageView não está funcionando

implementação "com.github.bumptech.glide: glide: 4.10.0"

XML

<FrameLayout
    android:id="@+id/fl_image"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:layout_margin="10dp"
    android:background="@drawable/card_circle_background"
    android:elevation="8dp">

    <ImageView
        android:id="@+id/iv_item_employee"
        android:layout_width="60dp"
        android:layout_height="60dp"
        tools:background="@color/colorPrimary" />
</FrameLayout>

Forma desenhável

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

Configuração Glide

Glide.with(this)
    .asBitmap()
    .load(item.image)
    .apply(RequestOptions.circleCropTransform())
    .into(iv_item_employee)

0

Você precisa usar CircularImageView para exibir esse tipo de imagem ...

Você está usando a biblioteca Glide, que costumava carregar imagens.

Crie um ClassFile em seu projeto e carregue-o no Imageview ... e você obterá o resultado desejado ...

Tente seguir o código ...

XML

 <com.yourpackage.CircularImageView
    android:id="@+id/imageview"
    android:layout_width="96dp"
    android:layout_height="96dp"
    app:border="true"
    app:border_width="3dp"
    app:border_color="@color/white"
    android:src="@drawable/image" />

CircularImageView.java

public class CircularImageView extends ImageView {
    private int borderWidth;
    private int canvasSize;
    private Bitmap image;
    private Paint paint;
    private Paint paintBorder;

    public CircularImageView(final Context context) {
        this(context, null);
    }

    public CircularImageView(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.circularImageViewStyle);
    }

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

        // init paint
        paint = new Paint();
        paint.setAntiAlias(true);

        paintBorder = new Paint();
        paintBorder.setAntiAlias(true);

        // load the styled attributes and set their properties
        TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CircularImageView, defStyle, 0);

        if(attributes.getBoolean(R.styleable.CircularImageView_border, true)) {
            int defaultBorderSize = (int) (4 * getContext().getResources().getDisplayMetrics().density + 0.5f);
            setBorderWidth(attributes.getDimensionPixelOffset(R.styleable.CircularImageView_border_width, defaultBorderSize));
            setBorderColor(attributes.getColor(R.styleable.CircularImageView_border_color, Color.WHITE));
        }

        if(attributes.getBoolean(R.styleable.CircularImageView_shadow, false))
            addShadow();
    }

    public void setBorderWidth(int borderWidth) {
        this.borderWidth = borderWidth;
        this.requestLayout();
        this.invalidate();
    }

    public void setBorderColor(int borderColor) {
        if (paintBorder != null)
            paintBorder.setColor(borderColor);
        this.invalidate();
    }

    public void addShadow() {
        setLayerType(LAYER_TYPE_SOFTWARE, paintBorder);
        paintBorder.setShadowLayer(4.0f, 0.0f, 2.0f, Color.BLACK);
    }

    @Override
    public void onDraw(Canvas canvas) {
        // load the bitmap
        image = drawableToBitmap(getDrawable());

        // init shader
        if (image != null) {

            canvasSize = canvas.getWidth();
            if(canvas.getHeight()<canvasSize)
                canvasSize = canvas.getHeight();

            BitmapShader shader = new BitmapShader(Bitmap.createScaledBitmap(image, canvasSize, canvasSize, false), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            paint.setShader(shader);

            // circleCenter is the x or y of the view's center
            // radius is the radius in pixels of the cirle to be drawn
            // paint contains the shader that will texture the shape
            int circleCenter = (canvasSize - (borderWidth * 2)) / 2;
            canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) + borderWidth - 4.0f, paintBorder);
            canvas.drawCircle(circleCenter + borderWidth, circleCenter + borderWidth, ((canvasSize - (borderWidth * 2)) / 2) - 4.0f, paint);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    private int measureWidth(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            // The parent has determined an exact size for the child.
            result = specSize;
        } else if (specMode == MeasureSpec.AT_MOST) {
            // The child can be as large as it wants up to the specified size.
            result = specSize;
        } else {
            // The parent has not imposed any constraint on the child.
            result = canvasSize;
        }

        return result;
    }

    private int measureHeight(int measureSpecHeight) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpecHeight);
        int specSize = MeasureSpec.getSize(measureSpecHeight);

        if (specMode == MeasureSpec.EXACTLY) {
            // We were told how big to be
            result = specSize;
        } else if (specMode == MeasureSpec.AT_MOST) {
            // The child can be as large as it wants up to the specified size.
            result = specSize;
        } else {
            // Measure the text (beware: ascent is a negative number)
            result = canvasSize;
        }

        return (result + 2);
    }

    public Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable == null) {
            return null;
        } else if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        }

        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
                drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);

        return bitmap;
    }
}

Nota :

Você pode usar

CircularImageView imgIcon = (CircularImageView)findViewById(R.id.imageview);

ou

ImageView imgIcon = (ImageView)findViewById(R.id.imageview);

isso não afetará suas outras bibliotecas ... não precisa alterar seu código para baixar imagens ou qualquer outra coisa ... simplesmente pode ser definido usando XML também ..


3
Tentei o Glide + CircularImageView (e RoundedImageView) e não funcionará bem se você começar a usar o espaço reservado (enquanto a imagem está sendo baixada) e as animações de aparência. Picasso não tem esse problema. Você pode ler
zmicer

Basta usar .asBitmap na chamada Glide e ele funcionará bem.
granko87

Requer a chamada .dontAnimate () em deslize que não é aceitável
Greg Ennis
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.