Rounded corners with Picasso

后端 未结 4 1106
被撕碎了的回忆
被撕碎了的回忆 2020-12-15 09:02

Is there a reasonable way to do rounded corners with Picasso that

  1. Doesn\'t significantly slow down drawing
  2. Works with hardware layers
  3. Doesn\'t create a
相关标签:
4条回答
  • 2020-12-15 09:23

    this will work for any image of any size--

    1) first create an empty image container for different resolution 2) then on runtime get its height and width by this-------

    BitmapFactory.Options dimensions = new BitmapFactory.Options(); 
    dimensions.inJustDecodeBounds = true;
    Bitmap mBitmap = BitmapFactory.decodeResource(activity.getResources(), R.drawable.icon, dimensions);
            int height = dimensions.outHeight;
            int width =  dimensions.outWidth;
    

    3)

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

    4) now transformation class----

    import android.graphics.Bitmap;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.PorterDuff.Mode;
    import android.graphics.PorterDuffXfermode;
    import android.graphics.Bitmap.Config;
    import android.graphics.Rect;
    import android.graphics.RectF;
    import com.squareup.picasso.Transformation;
    
    public class ImageTrans_roundedcorner implements Transformation{
    
        private int mBorderSize=10;
        private int mCornerRadius = 20;
        private int mColor=Color.BLACK;
    
        @Override
        public Bitmap transform(Bitmap source) {
            // TODO Auto-generated method stub
            Bitmap output = Bitmap.createBitmap(source.getWidth(), source.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, source.getWidth(), source.getHeight());
            final RectF rectF = new RectF(rect);
            final float roundPx = mCornerRadius;
    
            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(source, rect, rect, paint);
    
         // draw border
            paint.setColor(color);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth((float) mBorderSize);
            canvas.drawRoundRect(rectF, mCornerRadius, mCornerRadius, paint);
            //-------------------
    
                if(source != output) source.recycle();
    
                return output;
        }
    
        @Override
        public String key() {
            // TODO Auto-generated method stub
            return "grayscaleTransformation()";
        }
    
    }
    
    0 讨论(0)
  • 2020-12-15 09:36
    1. This code works fine for me
      enter image description here

      Picasso.with(getApplicationContext())
              .load(sp.getString("image_url", ""))
              .transform(new RoundedTransformation(100, 0))
              .fit()
              .into(userProfileImg);
      

    // here is the class for make

        public class RoundedTransformation implements
            com.squareup.picasso.Transformation {
        private final int radius;
        private final int margin; // dp
    
        // radius is corner radii in dp
        // margin is the board in dp
        public RoundedTransformation(final int radius, final int margin) {
            this.radius = radius;
            this.margin = margin;
        }
    
        @Override
        public Bitmap transform(final Bitmap source) {
            final Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP,
                    Shader.TileMode.CLAMP));
    
            Bitmap output = Bitmap.createBitmap(source.getWidth(),
                    source.getHeight(), Config.ARGB_8888);
            Canvas canvas = new Canvas(output);
            canvas.drawRoundRect(new RectF(margin, margin, source.getWidth()
                    - margin, source.getHeight() - margin), radius, radius, paint);
    
            if (source != output) {
                source.recycle();
            }
    
            return output;
        }
    
        @Override
        public String key() {
            return "rounded";
        }
    }
    
    0 讨论(0)
  • 2020-12-15 09:38

    EDIT: the answer I would suggest would be to wait for Picasso 2.3, or fork their github now, where you can actually get at a BitmapDrawable.

    One approach I've found so far is that you can load images into a Target object, create a custom drawable from the bitmap that way, then set the drawable into the ImageView, where it'll draw without creating a new bitmap.

    This approach sort of sucks for a few reasons though:

    1) You have to manage Target objects. These are weak-referenced (thankfully), so you have to keep track of them yourself. Ick. Memory leaks ahoy.

    2) When you get the callback, you had better check to make sure the state of the world is still relevant to the picture, which is part of what you want to avoid by using picasso.

    In short, there are a few things that seem to prevent a better solution.

    1) Picasso wraps bitmaps in PicassoDrawables. This means you you have to handle arbitrary drawables in your custom imageView (if you go that route), or special case for this class. 2) PicassoDrawable doesn't expose the source bitmap, so you have to convert the drawable to a bitmap (requires creating a new bitmap, afaict). 3) There's no bitmap -> drawable transform function (see #1 for why, most likely).

    Would love to hear if there's something I'm missing, or someone has come up with a better solution. Right now my best plan is to either do the Target management proposed above, or fork the picasso repo, change PicassoDrawable to have a public accessor for the underlying bitmap, and do the conversion into a custom drawable that way in my imageView.

    0 讨论(0)
  • 2020-12-15 09:44

    I also needed something like this, but with a border. I've searched the internet and I've found one version (without rounded corners) that looked good, but the border was over the image and I didn't like that. So I made my own version with the border outside the image.

    public class BitmapBorderTransformation implements Transformation {
    private int mBorderSize;
    private int mCornerRadius = 0;
    private int mColor;
    
    public BitmapBorderTransformation(int borderSize, int color) {
        this.mBorderSize = borderSize;
        this.mColor = color;
    }
    
    public BitmapBorderTransformation(int borderSize, int cornerRadius, int color) {
        this.mBorderSize = borderSize;
        this.mCornerRadius = cornerRadius;
        this.mColor = color;
    }
    
    @Override 
    public Bitmap transform(Bitmap source) {
        int width = source.getWidth();
        int height = source.getHeight();
    
        Bitmap image = Bitmap.createBitmap(width, height, source.getConfig());
        Canvas canvas = new Canvas(image);
        canvas.drawARGB(0, 0, 0, 0);
    
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        Rect rect = new Rect(0, 0, width, height);
    
    
        if(this.mCornerRadius == 0) {
            canvas.drawRect(rect, paint);
        }
        else {
            canvas.drawRoundRect(new RectF(rect),
                    this.mCornerRadius, this.mCornerRadius, paint);
        }
    
        paint.setXfermode(new PorterDuffXfermode((PorterDuff.Mode.SRC_IN)));
        canvas.drawBitmap(source, rect, rect, paint);
    
        Bitmap output;
    
        if(this.mBorderSize == 0) {
            output = image;
        }
        else {
            width = width + this.mBorderSize * 2;
            height = height + this.mBorderSize * 2;
    
            output = Bitmap.createBitmap(width, height, source.getConfig());
            canvas.setBitmap(output);
            canvas.drawARGB(0, 0, 0, 0);
    
            rect = new Rect(0, 0, width, height);
    
            paint.setXfermode(null);
            paint.setColor(this.mColor);
            paint.setStyle(Paint.Style.FILL);
    
            canvas.drawRoundRect(new RectF(rect), this.mCornerRadius, this.mCornerRadius, paint);
    
            canvas.drawBitmap(image, this.mBorderSize, this.mBorderSize, null);
        }
    
        if(source != output){
            source.recycle();
        }
        return output;
    }
    
    @Override 
    public String key() {
        return "bitmapBorder(" +
                "borderSize=" + this.mBorderSize + ", " +
                "cornerRadius=" + this.mCornerRadius + ", " +
                "color=" + this.mColor +")";
     }
    }
    

    Here are some samples:

    • Border with rounded corners:
      new BitmapBorderTransformation(3, 15, Color.WHITE);
      http://postimg.org/image/68fz5md39/

    • Rounded corners without border:
      new BitmapBorderTransformation(0, 15, Color.WHITE);
      http://postimg.org/image/he4681rsv/

    Also you can do border without rounded corners:
    new BitmapBorderTransformation(3, Color.WHITE);

    0 讨论(0)
提交回复
热议问题