与毕加索的圆角

时间:2014-03-12 20:50:43

标签: android picasso

是否有合理的方法与毕加索做圆角

  1. 不会显着减慢绘图速度
  2. 适用于硬件层
  3. 不为每个图像创建额外的位图
  4. 允许将下载的位图大小调整为目标imageview的大小

大多数关于圆角的毕加索建议都表明要使用转换,但我还没有看到一个例子,它不会在转换过程中创建额外的位图。

这似乎是因为Picasso只使用位图,而使用圆角的技巧使用的事实是你可以合理有效地动态绘制圆角(大多数解决方案都使用http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/行的内容)。

与Volley一起做这个有点hacky但可能,只需将ImageView的类型更改为采用自定义drawable的东西,它绘制了圆角。由于Picasso需要位图(至少,只有位图 - >位图转换),所以这是不合适的,因为drawable转换为位图会在过程中创建位图。

一个解决方案就是在我自己的分支中修改毕加索,添加一个位图 - >可绘制的变换,但我想象有一个更好的方法来解决这个问题。

我不想在视图顶部绘制9个补丁,以提供圆角的外观。

4 个答案:

答案 0 :(得分:25)

  1. 此代码适用于我        enter image description here

    Picasso.with(getApplicationContext())
            .load(sp.getString("image_url", ""))
            .transform(new RoundedTransformation(100, 0))
            .fit()
            .into(userProfileImg);
    
  2. //这里是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";
        }
    }
    

答案 1 :(得分:5)

我也需要这样的东西,但有边框。我搜索了互联网,我发现一个版本(没有圆角)看起来不错,但边框是在图像上,我不喜欢那样。所以我用图像外的边框制作了自己的版本。

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

以下是一些样本:

你也可以做没有圆角的边框:
新的BitmapBorderTransformation(3,Color.WHITE);

答案 2 :(得分:3)

这适用于任何大小的任何图像 -

1)首先为不同的分辨率创建一个空图像容器 2)然后在运行时通过这个-------

得到它的高度和宽度
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)现在转型类----

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

}

答案 3 :(得分:2)

编辑:我建议的答案是等待Picasso 2.3,或者现在分叉他们的github,你可以实际获得BitmapDrawable。

到目前为止我发现的一种方法是你可以将图像加载到Target对象中,从位图创建一个自定义drawable,然后将drawable设置为ImageView,它将在没有绘制的情况下绘制创建一个新的位图。

这种方法有点糟糕,但有几个原因:

1)您必须管理Target对象。这些是弱引用的(谢天谢地),所以你必须自己跟踪它们。伊克。内存泄漏啊。

2)当你收到回调时,你最好检查以确保世界状态仍然与图片相关,这是你想要使用毕加索避免的一部分。

简而言之,有一些事情似乎阻止了更好的解决方案。

1)Picasso在PicassoDrawables中包装了位图。这意味着您必须在自定义imageView中处理任意drawable(如果您选择该路径),或者此类的特殊情况。 2)PicassoDrawable不会公开源位图,所以你必须将drawable转换为位图(需要创建一个新的位图,afaict)。 3)没有位图 - >可绘制的变换函数(参见#1为什么,最有可能)。

我很想知道是否有我失踪的东西,或者有人提出了更好的解决方案。现在我最好的计划是要么执行上面提出的目标管理,要么分叉毕加索回购,改变PicassoDrawable以获得底层位图的公共访问器,并在我的imageView中以这种方式转换为自定义drawable。