在 Android 上为 imageView 渲染圆角 [英] Rendering rounded corners for imageView on Android

查看:66
本文介绍了在 Android 上为 imageView 渲染圆角的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下一段代码来渲染带有圆角的 imageView.

I have the following piece of code for rendering an imageView with rounded corners.

public class RoundedCornerImageView extends ImageView {

private int rounded;
public RoundedCornerImageView(Context context) {
    super(context);
}

public RoundedCornerImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public RoundedCornerImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}


public int getRounded() {
    return rounded;
}

public void setRounded(int rounded) {
    this.rounded = rounded;

}


@Override
public void onDraw(Canvas canvas)
{


    Drawable drawable = getDrawable();

    int w = drawable.getIntrinsicHeight(),
        h = drawable.getIntrinsicWidth();

    Bitmap rounder = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
    Canvas tmpCanvas = new Canvas(rounder);

    // We're going to apply this paint eventually using a porter-duff xfer mode.
    // This will allow us to only overwrite certain pixels. RED is arbitrary. This
    // could be any color that was fully opaque (alpha = 255)
    Paint xferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    xferPaint.setColor(Color.WHITE);

    // We're just reusing xferPaint to paint a normal looking rounded box, the 20.f
    // is the amount we're rounding by.
    tmpCanvas.drawRoundRect(new RectF(0,0,w,h), 10.0f, 10.0f, xferPaint);

    // Now we apply the 'magic sauce' to the paint
    xferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));

    drawable.draw(canvas);
    canvas.drawBitmap(rounder, 0, 0, xferPaint);
}
}



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:background='#a3deef'
    >
<com.example.scheduling_android.view.RoundedCornerImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/eventImageView"
        android:adjustViewBounds="false"/>
</LinearLayout>

它的作用在于它确实裁剪了图像的角落.但是,当我尝试在具有背景颜色 #a3deef 的线性布局中呈现它时,问题就出现了.结果显示为#a3deef 的背景颜色,每个图像都显示为圆角,其中 4 个裁剪角均为黑色.

It works in that it is indeed cropping off the corners of the image. However, the problem arises when I try to render this inside a linearLayout that has a background color #a3deef. The resulting display is a background color of #a3deef with each image displayed with rounded corners where the 4 cropped corner are all in black.

我应该怎么做才能使裁剪后的角变得透明而不是黑色?另外,如果有人能向我解释为什么它是黑色的,而不是任何其他颜色,那就太好了!

What should I do to make the cropped corners transparent rather than black? Also, it would be great if someone could explain to me why it would black, and not any other colors too!

提前致谢.

推荐答案

如果源还不是 Bitmap,那么您所采用的方法实际上并不奏效,主要是因为最好使用绘图回调之外的传输模式将内容绘制到 Canvas 中(因此它只发生一次而不是每次绘制刷新时发生)并在其他任何地方调用 Drawable.draw() 获胜不会产生正确的结果,因为边界不会按照您的预期设置.

The approach you are taking doesn't really work well if the source isn't already a Bitmap, primarily because it's better to draw the content into the Canvas using transfer modes outside the drawing callback (so it only happens once instead of on every draw refresh) and calling Drawable.draw() anywhere else won't produce the correct results since the bounds won't be set as you expect.

执行此操作的一个明显更有效的方法是不修改源数据,而只是将圆形剪辑应用于绘图Canvas.对于非常大的半径,这可能会产生一些锯齿,但在 10px 时不会很明显.这种方法唯一的另一个缺点是硬件加速目前不支持 clipPath(),因此您必须将此视图的图层类型设置为软件,以便渲染在 Android 上工作3.0+

A significantly more efficient method of doing this is not to modify the source data and just apply a rounded clip to the drawing Canvas. For really large radii, this can create a little aliasing, but at 10px it won't be noticeable. The only other drawback to this approach is that clipPath() is not currently supported by hardware acceleration, so you will have to set the layer type for this view to software in order for the rendering to work on Android 3.0+

public class RoundedCornerImageView extends ImageView {

    private Path roundedPath;
    private int rounded;

    public RoundedCornerImageView(Context context) {
        super(context);
        init();
    }

    public RoundedCornerImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RoundedCornerImageView(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        // If the application is hardware accelerated,
        // must disable it for this view.
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        // Set a default radius
        setRounded(10);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if (w != oldw || h != oldh) {
            roundedPath = new Path();
            roundedPath.addRoundRect(new RectF(0, 0, w, h),
                    rounded, rounded, Path.Direction.CW);
        }
    }

    public int getRounded() {
        return rounded;
    }

    public void setRounded(int rounded) {
        this.rounded = rounded;
        roundedPath = new Path();
        roundedPath.addRoundRect(new RectF(0, 0, getWidth(), getHeight()),
                rounded, rounded, Path.Direction.CW);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //Apply the clip
        canvas.clipPath(roundedPath);
        //Let the view draw as normal
        super.onDraw(canvas);
    }
}

在修改后的版本中,您只需在每次视图或半径大小更改时更新剪辑路径,然后将该Path 作为剪辑应用到 Canvas 之前绘图.

In the modified version, you simply update the clipping path each time either the view or the radius size changes, and apply that Path as a clip to the Canvas before drawing.

HTH

这篇关于在 Android 上为 imageView 渲染圆角的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆