android: tạo hình ảnh tròn với picasso


108

Câu hỏi đã được đặt ra và đã có một lời hứa được đưa ra cho chính phiên bản Picasso mà tôi đang sử dụng: Làm cách nào để gửi một bitmap hình tròn đến ImageView bằng Picasso? Tôi mới biết đến Picasso và điều duy nhất tôi đã sử dụng là

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

Tôi đã tìm thấy https://gist.github.com/julianshen/5829333 nhưng tôi không chắc làm thế nào để kết hợp nó với dòng ở trên một cách dễ hiểu.


Liên kết bạn đưa ra đã đủ để trả lời câu hỏi của chính bạn. Và bạn chỉ cần áp dụng Picasso.with (activity) .load (mayorShipImageLink) .transform (new CircleTransform ()). Vào (ImageView);
lagos

Câu trả lời:


286

Nghiên cứu một chút trước khi có sẵn câu trả lời. Nhưng dù sao, hãy làm theo Liên kết này và đọc kỹ để biết cách sử dụng nó.

thử cái này:

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

sau đó chỉ cần áp dụng nó như:

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

@ anirudh-sharma hãy đảm bảo thêm các mục nhập sau: import android.graphics.Bitmap; nhập android.graphics.BitmapShader; nhập android.graphics.Canvas; nhập android.graphics.Paint; nhập com.squareup.picasso.Transformation;
AG1

1
@all: Nếu bạn nhận được vào một ngoại lệ con trỏ null trên hình ảnh gif, kiểm tra này
Cerlin

Hoạt động như một sự quyến rũ ở Kotlin. Một sự thay đổi cho các API có sẵn, BitmapShader.TileMode.CLAMPkhông được exsting nữa, tôi đã cập nhật câu trả lời
sud007

KHÔNG HOẠT ĐỘNG! Tín hiệu nguy hiểm tiềm tàng 6 (SIGBART) , có nghĩa là bitmap.recycle () thực sự đang xóa tham chiếu khỏi bộ nhớ và gây ra thông báo signal 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!'-> Hủy bỏ: 'Lỗi, không thể truy cập bitmap không hợp lệ / miễn phí tại đây! bởi vì đó là rác được thu thập khỏi bộ nhớ. bitmap.recycleđược sử dụng cho các thiết bị Android cũ hơn, đó là những gì tôi hiểu.
Haroun Hajem,

47

đây là thứ được cung cấp bởi thư viện support-v4 ! Nhìn vào RoundedBitmapDrawable . Không cần cuộn của riêng bạn:

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

Lưu ý: Picasso cũng có lệnh gọi .transform (customTransformation) mà bạn có thể sử dụng về mặt lý thuyết, tuy nhiên, tôi gặp vấn đề với điều đó. Điều này ở trên hoạt động. Chúc may mắn!


Điều này sẽ hoạt động hoàn hảo cho hình ảnh vuông. Sử dụng Math.min trong bán kính góc cho bất kỳ hình ảnh nào. imageDrawable.setCornerRadius (Math.min (imageBitmap.getWidth (), imageBitmap.getHeight ()) / 2.0f);
Xplosive

Chúng ta không nên tạo luồng riêng biệt trong OnSuccess (), bởi vì việc tạo bitmap tròn từ bitmap gốc có thể là một nhiệm vụ dài?
HasaDev

17

Một thay thế khác mà tôi tìm thấy là thư viện kẻ này. Nó hoạt động độc lập hoặc kết hợp với Picasso. Tôi đã chọn tuyến đường Picasso, như dưới đây:

https://github.com/vinc3m1/RoundsImageView

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

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

Đã làm cho tôi!


12

Có một thư viện chuyển đổi cho Picasso.

Chỉ cần thêm phụ thuộc gradle

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

Kết thúc sử dụng nó

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

Wiki: Picasso Transformations


Đây thực sự là câu trả lời hoàn hảo cho câu hỏi này, tại sao nó lại có ít lượt bình chọn như vậy ..
Đệ tử

10

Tôi đã thử tất cả các giải pháp ở trên nhưng không có giải pháp nào cho tôi biến đổi hình tròn mà không cắt ảnh..giải pháp này sẽ chỉ hoạt động với các hình ảnh có cùng chiều rộng và chiều cao..đây là giải pháp của tôi ở trên

Đầu tiên ------

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

sau đó làm điều này --------

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

Sử dụng thư viện này để tạo chế độ xem hình ảnh tròn. Để tạo ImageView hình tròn, hãy thêm thư viện CircularImageView này vào dự án của bạn và thêm CircularImageView trong XML bố cục của bạn

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

Sau đó, sử dụng picasso để tải hình ảnh cần thiết vào imageView này. Picasso thực hiện tất cả các bộ nhớ đệm mà bạn không cần phải lo lắng về nó


2

Bao gồm danh sách có thể vẽ xml của loại Layer- với mã bên dưới

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

sau đó sử dụng xml cho ImageView của bạn trong 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

Cái này đang làm việc với ảnh chụp nhanh Picasso 3 hiện tại:

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()"
  }
}

Ý chính của Picasso3: https://gist.github.com/G00fY2/f3fbc468570024930c1fd9eb4cec85a1


0

Đây là những gì hiệu quả với tôi với 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()"
}

}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.