android: crea una imagen circular con picasso

108

Se había hecho la pregunta y se había hecho una promesa para la misma versión de Picasso que estoy usando: ¿Cómo envío un mapa de bits circular a un ImageView usando Picasso? Soy nuevo en Picasso y lo único que he usado es

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

Ya encontré https://gist.github.com/julianshen/5829333 pero no estoy seguro de cómo combinarlo con la línea anterior de una manera no incómoda.

Catedral Pillon
fuente
El enlace que proporcionó fue suficiente para responder su propia pregunta. Y solo necesitaba aplicar Picasso.with (activity) .load (mayorShipImageLink) .transform (new CircleTransform ()). Into (ImageView);
lagos

Respuestas:

286

Investigue un poco antes, ya que hay respuestas disponibles. De todos modos, siga este enlace y léalo detenidamente para saber cómo usarlo.

prueba esto:

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

luego simplemente aplíquelo como:

Picasso.with(activity).load(mayorShipImageLink).transform(new CircleTransform()).into(ImageView);
Anirudh Sharma
fuente
@ anirudh-sharma asegúrese de agregar estas importaciones: import android.graphics.Bitmap; importar android.graphics.BitmapShader; importar android.graphics.Canvas; importar android.graphics.Paint; import com.squareup.picasso.Transformation;
AG1
1
@todos: si obtiene una excepción de puntero nulo en imágenes gif, verifique esto
Cerlin
Funciona como un encanto en Kotlin también. Un cambio para las API existentes, BitmapShader.TileMode.CLAMPya no existe, he actualizado la respuesta
sud007
¡NO FUNCIONA! Señal potencialmente fatal 6 (SIGBART) , lo que significa que bitmap.recycle () en realidad está eliminando la referencia de la memoria y provocando un mensajesignal 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: 'Error, ¡no se puede acceder a un mapa de bits no válido / libre aquí! porque es basura recolectada de la memoria. bitmap.recyclese usa para dispositivos Android más antiguos, es lo que entiendo.
Haroun Hajem
47

¡aquí hay algo que proporciona la biblioteca support-v4 ! Mire en RoundedBitmapDrawable . No es necesario enrollar el tuyo:

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 también tiene una llamada .transform (customTransformation) que teóricamente podrías usar, sin embargo, tuve problemas con eso. Esto de arriba funciona. ¡Buena suerte!

goodKode
fuente
Esto funcionará perfectamente para una imagen cuadrada. Utilice Math.min en el radio de la esquina para cualquier imagen. imageDrawable.setCornerRadius (Math.min (imageBitmap.getWidth (), imageBitmap.getHeight ()) / 2.0f);
Xplosive
¿No deberíamos crear un hilo separado en OnSuccess (), porque puede ser una tarea larga crear un mapa de bits redondeado a partir del mapa de bits de origen?
HasaDev
17

Otra alternativa que encontré fue esta biblioteca de chicos. Funciona de forma independiente o en conjunto con Picasso. Elegí la ruta de Picasso, como a continuación:

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

¡Trabajó para mi!

Breeno
fuente
12

Hay una biblioteca de transformación para Picasso.

Simplemente agregue la dependencia de Gradle

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

Fin de usarlo

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

Wiki: Transformaciones de Picasso

Nikolay Krasilnikov
fuente
Esta es realmente la respuesta perfecta para esta pregunta, ¿por qué tiene tan pocos votos?
DDisciple
10

He probado todas las soluciones anteriores, pero ninguna de ellas me da una transformación circular sin recortar la imagen ... esa solución funcionará solo para imágenes con el mismo ancho y alto ... esta es mi solución arriba

primero ------

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

entonces haz esto --------

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";
    }
}
amit
fuente
8

Utilice esta biblioteca para crear una vista de imagen circular. Para hacer un ImageView circular, agregue esta biblioteca CircularImageView a su proyecto y agregue CircularImageView en su diseño 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" />`

Luego use picasso para cargar la imagen requerida en este imageView. Picasso hace todo el almacenamiento en caché, no tienes que preocuparte por eso

NIPHIN
fuente
2

Incluya el dibujable xml de tipo Layer- list con el siguiente código

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

luego use el xml para su ImageView en 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"/>
Marco Aurelio
fuente
0

Este está trabajando con la instantánea actual de 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()"
  }
}

Esencial de Picasso3: https://gist.github.com/G00fY2/f3fbc468570024930c1fd9eb4cec85a1

G00fY
fuente
0

Esto es lo que funcionó para mí con 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()"
}

}

chabislav
fuente