添加图像圆形图像android的边框

时间:2014-12-01 19:53:07

标签: android picasso

我有什么 ::我有一个Imageview,我使用picassso将图像作为一个圆圈 enter image description here

我该怎么做 ::我想使用我当前的实现为圆形图像添加黑色边框,如何在不使用第三方库的情况下实现此目的

Picasso.with(this)
.load("http://i.imgur.com/DvpvklR.png")
.transform(new RoundedTransformation(50, 4))
.resize(100, 100)
.centerCrop().into(imageView1);

RoundedTransformation.java

// enables hardware accelerated rounded corners
// original idea here : http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/
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";
    }
}

修改

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

        Paint paint1 = new Paint();      
        paint1.setColor(Color.RED);
        paint1.setStyle(Style.STROKE);
        paint1.setAntiAlias(true);
        paint1.setStrokeWidth(2);
        canvas.drawCircle((source.getWidth() - margin)/2, (source.getHeight() - margin)/2, radius-2, paint1);


        return output;
    }

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

enter image description here

4 个答案:

答案 0 :(得分:17)

最终转型课,感谢blackbelt

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.drawCircle((source.getWidth() - margin)/2, (source.getHeight() - margin)/2, radius-2, paint);

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

        Paint paint1 = new Paint();      
        paint1.setColor(Color.RED);
        paint1.setStyle(Style.STROKE);
        paint1.setAntiAlias(true);
        paint1.setStrokeWidth(2);
        canvas.drawCircle((source.getWidth() - margin)/2, (source.getHeight() - margin)/2, radius-2, paint1);


        return output;
    }

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

答案 1 :(得分:8)

您可以将drawCircle与另一个Paint object一起使用。例如:

Paint paint = new Paint();      
paint.setColor(Color.RED);
paint.setStyle(Style.STROKE);
paint.setAntiAlias(true);
paint.setStrokeWidth(2);
canvas.drawCircle((source.getWidth() - margin)/2, (source.getHeight() - margin)/2, radius-2, paint);

此外,您可以使用drawRoundRect

而不是使用drawCircle绘制圆圈

答案 2 :(得分:1)

BlackBelt和Devrath的答案很棒。如果您正在寻找此类的Kotlin版本,则为:

class RoundedBorderTransform(private val radius: Int, private val margin: Int) : com.squareup.picasso.Transformation {

override fun transform(source: Bitmap?): Bitmap {
    val paint = Paint()
    paint.isAntiAlias = true
    paint.shader = BitmapShader(source!!, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)

    val output = Bitmap.createBitmap(source.width, source.height, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(output)
    canvas.drawCircle((source.width - margin) / 2f, (source.height - margin) / 2f, radius - 2f, paint)

    if (source != output) {
        source.recycle()
    }

    val borderPaint = Paint()
    borderPaint.color = Color.RED
    borderPaint.style = Paint.Style.STROKE
    borderPaint.isAntiAlias = true
    borderPaint.strokeWidth = 2f
    canvas.drawCircle((source.width - margin) / 2f, (source.height - margin) / 2f, radius - 2f, borderPaint)

    return output
}

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

}

答案 3 :(得分:0)

这是圆形和矩形形状的解决方案。此外,它不仅对使用毕加索很有用,而且对一般的Android Canvas任务也很有用。

我创建它们的内容非常详尽,仅是为了您对过程的了解,请根据需要将其缩短。

但我想澄清许多人面临的主要问题。 在android中,无法创建内部或外部边框-仅居中:

enter image description here

这就是为什么您收到这样的边界元素被剪掉的原因:

enter image description here

所以只有一种方法可以重新计算边框的位置:

  • ,您需要通过半边宽减小圆半径
  • 矩形,您必须1)将边界线“向内”移动半边宽度; 2)通过半边宽减小拐角半径

这些操作将为您提供预期的结果:

enter image description here

如果您只需要边界代码,请仅选择相应的drawBorder()方法。 这是带有两个图像的空片段的示例:

ViewsCroppingAndBorderingTestFragment.kt

class ViewsCroppingAndBorderingTestFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_test_views_cropping_and_bordering, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val urlCircle      = "https://images-na.ssl-images-amazon.com/images/I/71zLQIfmTlL._AC_SX466_.jpg"
        val urlRectRounded = "https://www.gardendesign.com/pictures/images/675x529Max/site_3/helianthus-yellow-flower-pixabay_11863.jpg"

        val ivCircle       = view.findViewById<ImageView>(R.id.ivCircle)
        val ivRectRounded  = view.findViewById<ImageView>(R.id.ivRectRounded)

        val trCircle       = CircleTransformation()
        val trRectRounded  = RectRoundedTransformation()

        Picasso.get().load(urlCircle).transform(trCircle).into(ivCircle)
        Picasso.get().load(urlRectRounded).transform(trRectRounded).into(ivRectRounded)
    }


    class CircleTransformation() : Transformation {

        override fun transform(source: Bitmap): Bitmap {

            val size = Math.min(source.width, source.height)
            val x = (source.width  - size) / 2
            val y = (source.height - size) / 2
            val w = size
            val h = size
            val squaredBitmap = Bitmap.createBitmap(source, x, y, w, h)

            if (squaredBitmap != source) {
                source.recycle()
            }

            val bitmap = Bitmap.createBitmap(w, h, source.config)

            val canvas = Canvas(bitmap)

//          >>  Draw original rectangle image
//            val paint = Paint(Paint.ANTI_ALIAS_FLAG)
//            canvas.drawBitmap(squaredBitmap, 0F, 0F, paint)

            val rImage = w / 2f

            cropWithCircle(squaredBitmap, canvas, rImage)
            squaredBitmap.recycle()


            drawBorder(canvas, rImage)


            return bitmap
        }

        private fun cropWithCircle(bitmapSource: Bitmap, canvas: Canvas, rImage: Float) {

            val shader = BitmapShader(bitmapSource, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)

            val paint         = Paint(Paint.ANTI_ALIAS_FLAG)
            paint.shader      = shader
            paint.isAntiAlias = true

            val xCenter = rImage
            val yCenter = rImage

            canvas.drawCircle(xCenter, yCenter, rImage, paint)
        }

        private fun drawBorder(canvas: Canvas, rImage: Float) {

            val borderWidth = 30F

            val paintBorder         = Paint()
            paintBorder.strokeWidth = borderWidth
            paintBorder.style       = Paint.Style.STROKE
            paintBorder.color       = Color.GREEN
            paintBorder.isAntiAlias = true


            val cCenter = rImage
            val yCenter = rImage

            // ANDROID'S BORDER IS ALWAYS CENTERED.
            //  So have to reduce radius by half of border's width

            val rBorder = rImage - borderWidth / 2

            canvas.drawCircle(cCenter, yCenter, rBorder, paintBorder)
        }

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

    class RectRoundedTransformation() : Transformation {

        override fun transform(source: Bitmap): Bitmap {

            val x = 0
            val y = 0
            val w = source.width
            val h = source.height
            val squaredBitmap = Bitmap.createBitmap(source, x, y, w, h)

            if (squaredBitmap != source) {
                source.recycle()
            }

            val bitmap = Bitmap.createBitmap(w, h, source.config)

            val canvas = Canvas(bitmap)

//          >>  Draw original rectangle image
//            val paint = Paint(Paint.ANTI_ALIAS_FLAG)
//            canvas.drawBitmap(squaredBitmap, 0F, 0F, paint)

            val rCorner = 80F

            cropCorners(squaredBitmap, canvas, rCorner)
            squaredBitmap.recycle()


            drawBorder(canvas, rCorner)


            return bitmap
        }

        private fun cropCorners(bitmapSource: Bitmap, canvas: Canvas, rCorner: Float) {

            val width  = canvas.width
            val height = canvas.height

            val maskBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8)
            val maskCanvas = Canvas(maskBitmap)
            val maskPaint  = Paint(Paint.ANTI_ALIAS_FLAG)
            val maskRect   = RectF(0F, 0F, width.toFloat(), height.toFloat())

            // 1. draw base rect
            maskCanvas.drawRect(maskRect, maskPaint)

            // 2. cut off inner rounded rect, leave corners
            maskPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
            maskCanvas.drawRoundRect(maskRect, rCorner, rCorner, maskPaint)

            // 3. draw original rectangle image
            val paintSource = Paint(Paint.ANTI_ALIAS_FLAG)

            canvas.drawBitmap(bitmapSource, 0f, 0f, paintSource)

            // 4.cut off corners
            val paintCropped = Paint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG)
            paintCropped!!.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)

            canvas.drawBitmap(maskBitmap!!, 0f, 0f, paintCropped)
        }

        private fun drawBorder(canvas: Canvas, rCorner: Float) {

            val borderWidth  = 30F

            val paintBorder         = Paint()
            paintBorder.strokeWidth = borderWidth
            paintBorder.style       = Paint.Style.STROKE
            paintBorder.color       = Color.RED
            paintBorder.isAntiAlias = true


//            // ANDROID'S BORDER IS ALWAYS CENTERED.
//            //  So have to shift every side by half of border's width

            val rectLeft   = 0 + borderWidth / 2
            val rectTop    = 0 + borderWidth / 2
            val rectRight  = canvas.width.toFloat() - borderWidth / 2
            val rectBottom = canvas.height.toFloat() - borderWidth / 2
            val rectF      = RectF(rectLeft, rectTop, rectRight, rectBottom)

//            //  So have to corner reduce radius by half of border's width
            val rectRCorner = rCorner - borderWidth / 2

            canvas.drawRoundRect(rectF, rectRCorner, rectRCorner, paintBorder)
        }

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

fragment_test_views_cropping_and_bordering.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/temp"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:background="@android:color/darker_gray">


    <ImageView
        android:id="@+id/ivCircle"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_margin="10dp"/>


    <ImageView
        android:id="@+id/ivRectRounded"
        android:layout_width="200dp"
        android:layout_height="160dp"
        android:layout_margin="10dp"/>


</LinearLayout>