我有下面这段代码来渲染一个圆角的imageView。
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的linearLayout中呈现它时,问题就出现了。结果显示的背景颜色为#a3deef,每个图像都以圆角显示,其中4个裁剪的角全部为黑色。
我应该怎么做,使裁剪的角落透明,而不是黑色?另外,如果有人能向我解释为什么它会是黑色的,而不是其他颜色的,那就太好了!
提前谢谢。
发布于 2012-09-11 05:45:38
如果源还不是Bitmap,那么所采用的方法就不能很好地工作,主要是因为最好使用绘图回调之外的传输模式将内容绘制到Canvas中(因此它只发生一次,而不是在每次绘制刷新时),并且调用Drawable.draw() anywhere不会产生正确的结果,因为界限不会像您预期的那样设置。
执行此操作的一种明显更有效的方法是不修改源数据,而只是将四舍五入的剪裁应用于绘图Canvas。对于非常大的半径,这可以创建一些锯齿,但在10px时它不会明显。这种方法唯一的另一个缺点是,硬件加速目前不支持clipPath(),因此您必须将此视图的图层类型设置为软件,以便在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。
HTH
发布于 2012-11-30 14:19:04
添加以下行以使画布透明:
canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), 255, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);此外,我使用反向填充的圆角矩形路径来遮罩位图,因此我不需要像您一样的中间遮罩位图。
public class RoundedImageView extends ImageView {
private Path mMaskPath;
private Paint mMaskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private int mCornerRadius = 10;
public RoundedImageView(Context context) {
super(context);
init();
}
public RoundedImageView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
init();
}
public RoundedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, null);
mMaskPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
}
/**
* Set the corner radius to use for the RoundedRectangle.
*
* @param Primitive int - The corner radius of the rounded rectangle.
*/
public void setCornerRadius(int cornerRadius) {
mCornerRadius = cornerRadius;
generateMaskPath(getWidth(), getHeight());
invalidate();
}
@Override
protected void onSizeChanged(int w, int h, int oldW, int oldH) {
super.onSizeChanged(w, h, oldW, oldH);
if (w != oldW || h != oldH) {
generateMaskPath(w, h);
}
}
private void generateMaskPath(int w, int h) {
mMaskPath = new Path();
mMaskPath.addRoundRect(new RectF(0,0,w,h), mCornerRadius, mCornerRadius, Direction.CW);
mMaskPath.setFillType(FillType.INVERSE_WINDING);
}
@Override
protected void onDraw(Canvas canvas) {
if(canvas.isOpaque()) { // If canvas is opaque, make it transparent
canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), 255, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
}
super.onDraw(canvas);
if(mMaskPath != null) {
canvas.drawPath(mMaskPath, mMaskPaint);
}
}
}发布于 2012-09-11 03:52:05
这是因为您正在使用的Canvas是不透明的。非透明Canvas的背景为黑色。
This answer将SurfaceView的Canvas设置为透明。对你来说,这可能和将Bitmap的背景设置为透明一样简单。
Bitmap rounder = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
rounder.eraseColor(Color.TRANSPARENT);你也可以在你的ImageView中尝试一下,将它的背景设置为100%透明:
setBackgroundColor(0);https://stackoverflow.com/questions/12358350
复制相似问题