【问题标题】:Custom view with rounded corners in AndroidAndroid中带有圆角的自定义视图
【发布时间】:2013-02-21 16:53:02
【问题描述】:

我有一个自定义视图,其中包含几层图像、带有文本的布局、绘图等。 我想让视图的一个角变成圆形(右上角)。 换句话说,我想裁剪这个角使其变圆 - 而不是设置圆角背景。

我设法通过使用clipPath() 来做到这一点,但它运行缓慢,因为我必须为这个视图打开硬件加速 - 所以这个解决方案不适合我。

还有其他方法吗?

【问题讨论】:

  • 您是否尝试过使用 XML Drawable?这可能适合您的目的。您可以使用图层列表拉出许多有趣的形状。
  • 我试过了,但据我所知,它只将圆角应用于背景,而不是整个视图。

标签: android android-view android-ui android-custom-view


【解决方案1】:

这是扩展 ImageView 的自定义圆角 ImageView 类。而这里的变量 CORNER_RADIUS 是半径的值。使用此代码,您只需从该视图扩展该类即可创建任何圆形视图。

public class RoundedImage extends android.support.v7.widget.AppCompatImageView
 {
private final static float CORNER_RADIUS = 100.0f;

private Bitmap maskBitmap;
private Paint paint, maskPaint;
private float cornerRadius;

public RoundedImage(Context context) {
    super(context);
    init(context, null, 0);

}

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

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

private void init(Context context, AttributeSet attrs, int defStyle) {
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);

    paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
    maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

    setWillNotDraw(false);
}

@Override
public void draw(Canvas canvas) {
    Bitmap offscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas offscreenCanvas = new Canvas(offscreenBitmap);

    super.draw(offscreenCanvas);

    if (maskBitmap == null) {
        maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
    }

    offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint);
    canvas.drawBitmap(offscreenBitmap, 0f, 0f, paint);
}

private Bitmap createMask(int width, int height) {
    Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
    Canvas canvas = new Canvas(mask);

    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setColor(Color.WHITE);

    canvas.drawRect(0, 0, width, height, paint);

    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);

    return mask;
}

}

使用方法是:

<com.packagename.RoundedImage
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:scaleType="centercrop"
 />

【讨论】:

    【解决方案2】:

    如果您为该自定义视图创建透明画布,这应该不是问题。然后在其上绘制一个圆角矩形作为其余图形之前的背景。

    圆角矩形应该比画布大并且向左移动,这样画布的右上角保持透明。

    但是,您是否在自定义视图中绘制了更大的图像,并且只想剪掉那个角,而不是用填充了油漆的角形状路径擦除那个角

    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    

    【讨论】:

    • 我试过这样:@Override public void draw(Canvas canvas) { super.draw(canvas);最终油漆油漆=新油漆();路径 p = 新路径(); p.addArc(new RectF(0, canvas.getHeight()/2, canvas.getWidth()/2, canvas.getHeight()), 90, -90); paint.setXfermode(新 PorterDuffXfermode(PorterDuff.Mode.DST_IN)); canvas.drawPath(p, 油漆); } -- 似乎不起作用,只是在我的视野上方用黑色绘制弧线
    • 这似乎更复杂。当您直接在画布上绘制它时,它会在默认活动背景上钻一个洞,即黑色。我找不到允许直接清除画布的自定义视图的示例。解决此问题的一种方法是创建位图并在其上绘制所有内容,然后使用 Mode.Clear 清除角落。然后在画布上绘制该位图。每次使画布无效时,它将被清除并变为透明,以便您可以再次绘制位图。位图必须是 RGBA_8888。
    • 我认为最便宜的方法是用与背景颜色相同的颜色来绘制角落,但位图选项实际上很快,而且现在的设备功能更强大。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 2020-11-04
    相关资源
    最近更新 更多