Renderizado esquinas redondeadas para imageView en Android

Tengo el siguiente pedazo de código para renderizar una imageView con esquinas redondeadas.

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> 

Funciona en el hecho de que está recortando las esquinas de la imagen. Sin embargo, el problema surge cuando intento hacer esto dentro de un linearLayout que tiene un color de fondo # a3deef. La pantalla resultante es un color de fondo de # a3deef con cada imagen mostrada con las esquinas redondeadas donde las 4 esquinas recortadas están todas en negro.

¿Qué debo hacer para que las esquinas recortadas sean transparentes en lugar de negras? Además, sería genial si alguien me explicara por qué sería negro, y no cualquier otro color también!

Gracias por adelantado.

El enfoque que está tomando realmente no funciona bien si la fuente no es ya un Bitmap , principalmente porque es mejor dibujar el contenido en la Canvas utilizando modos de transferencia fuera de la devolución de llamada de dibujo (por lo que sólo sucede una vez en lugar de en cada dibujo actualizar) y llamar Drawable.draw() cualquier otro lugar no producirá los resultados correctos ya que los límites no se establecerán como se espera.

Un método significativamente más eficiente de hacer esto no es modificar los datos de origen y simplemente aplicar un clip redondeado al dibujo Canvas . Para radios muy grandes, esto puede crear un poco de aliasing, pero a 10px no se notará. El único otro inconveniente de este enfoque es que clipPath() no está soportado actualmente por la aceleración de hardware, por lo que tendrá que establecer el tipo de capa para esta vista de software para que el procesamiento funcione en 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); } } 

En la versión modificada, simplemente actualiza el trazado de recorte cada vez que cambia el tamaño de la vista o el radio, y aplica ese Path como un clip al Canvas antes de dibujar.

HTH

Añada esta línea para que el lienzo sea transparente:

 canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), 255, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG); 

También, utilizo una trayectoria rectangular redondeada invertida para enmascarar el mapa de bits así que no necesito un mapa de bits de enmascaramiento intermediario como usted.

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

Esto se debe a que su Canvas que está trabajando no es transparente. Un Canvas no transparente tiene un fondo negro.

Esta respuesta establece un SurfaceView de SurfaceView para ser transparente. Para usted, puede ser tan simple como configurar el fondo del Bitmap de Bitmap para que sea transparente.

 Bitmap rounder = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888); rounder.eraseColor(Color.TRANSPARENT); 

También puede probar esto en su ImageView , para establecer su fondo a 100% transparente:

 setBackgroundColor(0); 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.