android: crie uma imagem circular com picasso


108

A pergunta foi feita e houve uma promessa feita para a própria versão do Picasso que estou usando: Como faço para enviar um bitmap circular para um ImageView usando o Picasso? Eu sou novo no Picasso e a única coisa que usei foi

Picasso.with(context).load(url).resize(w, h).into(imageview);

Já encontrei https://gist.github.com/julianshen/5829333, mas não tenho certeza de como combiná-lo com a linha acima de uma forma não estranha.


O link que você deu foi suficiente para responder à sua própria pergunta. E você só precisava aplicar Picasso.with (activity) .load (mayorShipImageLink) .transform (new CircleTransform ()). Into (ImageView);
lagos

Respostas:


286

Pesquise um pouco antes, pois há respostas disponíveis. De qualquer forma, siga este Link e leia com atenção para saber como usá-lo.

tente isto:

import com.squareup.picasso.Transformation;

public class CircleTransform implements Transformation {
    @Override
    public Bitmap transform(Bitmap source) {
        int size = Math.min(source.getWidth(), source.getHeight());

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

        Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
        if (squaredBitmap != source) {
            source.recycle();
        }

        Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());

        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        BitmapShader shader = new BitmapShader(squaredBitmap,
                Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        paint.setShader(shader);
        paint.setAntiAlias(true);

        float r = size / 2f;
        canvas.drawCircle(r, r, r, paint);

        squaredBitmap.recycle();
        return bitmap;
    }

    @Override
    public String key() {
        return "circle";
    }
}

em seguida, basta aplicá-lo como:

Picasso.with(activity).load(mayorShipImageLink).transform(new CircleTransform()).into(ImageView);

@ anirudh-sharma certifique-se de adicionar estas importações: import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Paint; import com.squareup.picasso.Transformation;
AG1 de

1
@todos: Se você obtiver uma exceção de ponteiro nulo em imagens GIF, verifique isto
Cerlin

Funciona como um encanto em Kotlin também. Uma mudança para as APIs existentes BitmapShader.TileMode.CLAMPnão existe mais, atualizei a resposta
sud007

NÃO FUNCIONA! Sinal potencial fatal 6 (SIGBART) , significando que bitmap.recycle () está realmente removendo a referência da memória e causando uma mensagemsignal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- 11-12 00:03:47.941 29091 29091 F DEBUG : Abort message: 'Error, cannot access an invalid/free'd bitmap here!' -> Abortar: 'Erro, não é possível acessar um bitmap inválido / livre aqui! porque é lixo coletado longe da memória. bitmap.recycleé usado para dispositivos Android mais antigos, é o que eu entendo.
Haroun Hajem

47

aqui está algo que é fornecido pela biblioteca support-v4 ! Procure em RoundedBitmapDrawable . Não há necessidade de fazer o seu próprio:

Picasso.with(context).load(url)
                        .resize(w, h)
                        .into(myImageView, new Callback() {
                            @Override
                            public void onSuccess() {
                                Bitmap imageBitmap = ((BitmapDrawable) myImageView.getDrawable()).getBitmap();
                                RoundedBitmapDrawable imageDrawable = RoundedBitmapDrawableFactory.create(getResources(), imageBitmap);
                                imageDrawable.setCircular(true);
                                imageDrawable.setCornerRadius(Math.max(imageBitmap.getWidth(), imageBitmap.getHeight()) / 2.0f);
                                myImageView.setImageDrawable(imageDrawable);
                            }
                            @Override
                            public void onError() {
                                myImageView.setImageResource(R.drawable.default_image);
                            }
                        });

Nota: Picasso também tem uma chamada .transform (customTransformation) que você poderia usar teoricamente, no entanto, tive problemas com isso. Isso acima funciona. Boa sorte!


Isso funcionará perfeitamente para imagens quadradas. Use Math.min no raio do canto para qualquer imagem. imageDrawable.setCornerRadius (Math.min (imageBitmap.getWidth (), imageBitmap.getHeight ()) / 2.0f);
Xplosive

Não deveríamos criar thread separado em OnSuccess (), porque pode ser uma tarefa longa criar bitmap arredondado a partir do bitmap de origem?
HasaDev

17

Outra alternativa que encontrei foi a biblioteca desse cara. Funciona sozinho ou em conjunto com o Picasso. Escolhi a rota do Picasso, conforme abaixo:

https://github.com/vinc3m1/RoundedImageView

Transformation transformation = new RoundedTransformationBuilder()
          .borderColor(Color.BLACK)
          .borderWidthDp(3)
          .cornerRadiusDp(30)
          .oval(false)
          .build();

Picasso.with(context)
    .load(url)
    .fit()
    .transform(transformation)
    .into(imageView);

Funcionou para mim!


11

Existe uma biblioteca de transformação para Picasso.

Basta adicionar dependência do Gradle

implementation 'jp.wasabeef:picasso-transformations:2.2.1'

Fim de uso

Picasso.with(context)
       .load(url)
       .resize(w, h)
       .transform(new CropCircleTransformation())
       .into(imageview);

Wiki: Transformações de Picasso


10

Eu tentei todas as soluções acima, mas nenhuma delas me dá a transformação do círculo sem cortar a imagem ... essa solução funcionará apenas para imagens com a mesma largura e altura ... esta é a minha solução acima

primeiro ------

Picasso.with(getActivity())
            .load(url)
            .error(R.drawable.image2)
            .placeholder(R.drawable.ic_drawer)
            .resize(200, 200)
            .transform(new ImageTrans_CircleTransform())
            .into(imageView1);

então faça isso --------

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Shader.TileMode;

import com.squareup.picasso.Transformation;
public class ImageTrans_CircleTransform implements Transformation {
 @Override
    public Bitmap transform(Bitmap source) {
 if (source == null || source.isRecycled()) {
                return null;
            }

            final int width = source.getWidth() + borderwidth;
            final int height = source.getHeight() + borderwidth;

            Bitmap canvasBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            BitmapShader shader = new BitmapShader(source, TileMode.CLAMP, TileMode.CLAMP);
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setShader(shader);

            Canvas canvas = new Canvas(canvasBitmap);
            float radius = width > height ? ((float) height) / 2f : ((float) width) / 2f;
            canvas.drawCircle(width / 2, height / 2, radius, paint);

            //border code
            paint.setShader(null);
            paint.setStyle(Paint.Style.STROKE);
            paint.setColor(bordercolor);
            paint.setStrokeWidth(borderwidth);
            canvas.drawCircle(width / 2, height / 2, radius - borderwidth / 2, paint);
            //--------------------------------------

            if (canvasBitmap != source) {
                source.recycle();
            }

            return canvasBitmap;
}
 @Override
    public String key() {
        return "circle";
    }
}

8

Use esta biblioteca para criar uma visualização de imagem circular. Para fazer um ImageView circular, adicione esta biblioteca CircularImageView ao seu projeto e adicione CircularImageView ao seu layout XML

<com.pkmmte.view.CircularImageView
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:src="@drawable/image"
        app:border_color="#EEEEEE"
        app:border_width="4dp"
        app:shadow="true" />`

Em seguida, use o picasso para carregar a imagem necessária neste imageView. O Picasso faz todo o cache de que você não precisa se preocupar com isso


2

Inclua o drawable xml do tipo Layer- list com o código abaixo

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/shape_status">
        <shape android:shape="oval">
            <solid android:color="@android:color/black"/>
        </shape>
    </item>
<item android:drawable="@drawable/ic_status_content"/></layer-list>

em seguida, use o xml para seu ImageView no android.src

 <ImageView
            android:id="@+id/iconStatus"
            android:layout_width="55dp"
            android:layout_height="55dp"
            android:layout_gravity="right"
            android:src="@drawable/ic_circle_status"
            android:layout_alignParentTop="true"
            android:layout_alignParentEnd="true"/>


0

Este está trabalhando com o instantâneo atual do Picasso 3:

class CircleTransformation : Transformation {

  override fun transform(source: RequestHandler.Result): RequestHandler.Result {
    if (source.bitmap == null) {
      return source
    }

    var bitmap: Bitmap

    // since we cant transform hardware bitmaps create a software copy first
    if (VERSION.SDK_INT >= VERSION_CODES.O && source.bitmap!!.config == Config.HARDWARE) {
      val softwareCopy = source.bitmap!!.copy(Config.ARGB_8888, true)
      if (softwareCopy == null) {
        return source
      } else {
        bitmap = softwareCopy
        source.bitmap!!.recycle()
      }
    } else {
      bitmap = source.bitmap!!
    }

    var size = bitmap.width
    // if bitmap is non-square first create square one
    if (size != bitmap.height) {
      var sizeX = size
      var sizeY = bitmap.height
      size = Math.min(sizeY, sizeX)
      sizeX = (sizeX - size) / 2
      sizeY = (sizeY - size) / 2

      val squareSource = Bitmap.createBitmap(bitmap, sizeX, sizeY, size, size)
      bitmap.recycle()
      bitmap = squareSource
    }

    val circleBitmap = Bitmap.createBitmap(size, size, Config.ARGB_8888)
    val canvas = Canvas(circleBitmap)
    val paint = Paint()
    val shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)

    paint.shader = shader
    paint.isAntiAlias = true
    val centerAndRadius = size / 2f
    canvas.drawCircle(centerAndRadius, centerAndRadius, centerAndRadius, paint)

    bitmap.recycle()
    return RequestHandler.Result(circleBitmap, source.loadedFrom, source.exifRotation)
  }

  override fun key(): String {
    return "circleTransformation()"
  }
}

Essência do Picasso3: https://gist.github.com/G00fY2/f3fbc468570024930c1fd9eb4cec85a1


0

Aqui está o que funcionou para mim com Picasso v2.71828

class CircleTransform : Transformation {
override fun transform(source: Bitmap?): Bitmap? {
    if (source == null) {
        return source
    }

    var bitmap: Bitmap

    // since we cant transform hardware bitmaps create a software copy first
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && source.config == Bitmap.Config.HARDWARE) {
        val softwareCopy = source.copy(Bitmap.Config.ARGB_8888, true)
        if (softwareCopy == null) {
            return source
        } else {
            bitmap = softwareCopy
            source.recycle()
        }
    } else {
        bitmap = source
    }

    var size = bitmap.width
    // if bitmap is non-square first create square one
    if (size != bitmap.height) {
        var sizeX = size
        var sizeY = bitmap.height
        size = Math.min(sizeY, sizeX)
        sizeX = (sizeX - size) / 2
        sizeY = (sizeY - size) / 2

        val squareSource = Bitmap.createBitmap(bitmap, sizeX, sizeY, size, size)
        bitmap.recycle()
        bitmap = squareSource
    }

    val circleBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(circleBitmap)
    val paint = Paint()
    val shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)

    paint.shader = shader
    paint.isAntiAlias = true
    val centerAndRadius = size / 2f
    canvas.drawCircle(centerAndRadius, centerAndRadius, centerAndRadius, paint)

    bitmap.recycle()
    return circleBitmap
}


override fun key(): String {
    return "circleTransformation()"
}

}

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.