Cómo hacer una vista en android con esquinas redondeadas

Estoy tratando de hacer una vista en android con bordes redondeados. La solución que he encontrado hasta ahora es definir una forma con esquinas redondeadas y usarla como fondo de esa vista.

Aquí es lo que hice, definir un dibujable como se indica a continuación

<padding android:top="2dp" android:bottom="2dp"/> <corners android:bottomRightRadius="20dp" android:bottomLeftRadius="20dp" android:topLeftRadius="20dp" android:topRightRadius="20dp"/> 

Ahora utilicé esto como el fondo para mi disposición como abajo

 <LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginBottom="10dp" android:clipChildren="true" android:background="@drawable/rounded_corner"> 

Esto funciona perfectamente bien, puedo ver que la vista tiene bordes redondeados.

Pero mi diseño tiene muchas otras vistas de niño en ella Diga un ImageView o un MapView. Cuando coloco un ImageView dentro del diseño anterior, las esquinas de la imagen no se cortan / recortan, sino que aparecen llenas.

He visto otras soluciones para hacer que funcione como el explicado aquí .

Pero ¿hay un método para establecer esquinas redondeadas para una vista y todas sus vistas secundarias están contenidas dentro de esa vista principal que tiene esquinas redondeadas?

Gracias.

Otro enfoque consiste en crear una clase de diseño personalizado como la que se muestra a continuación. Esta disposición dibuja primero su contenido en un mapa de bits fuera de pantalla, enmascara el mapa de bits sin pantalla con un rectángulo redondeado y, a continuación, dibuja el mapa de bits fuera de pantalla en el lienzo real.

Lo intenté y parece que funciona (al menos para mi testcase simple). Por supuesto, afectará el rendimiento en comparación con un diseño regular.

 package com.example; import android.content.Context; import android.graphics.*; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; import android.widget.FrameLayout; public class RoundedCornerLayout extends FrameLayout { private final static float CORNER_RADIUS = 40.0f; private Bitmap maskBitmap; private Paint paint, maskPaint; private float cornerRadius; public RoundedCornerLayout(Context context) { super(context); init(context, null, 0); } public RoundedCornerLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } public RoundedCornerLayout(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; } } 

Use esto como un diseño normal:

 <com.example.RoundedCornerLayout android:layout_width="200dp" android:layout_height="200dp"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/test"/> <View android:layout_width="match_parent" android:layout_height="100dp" android:background="#ff0000" /> </com.example.RoundedCornerLayout> 

Shape.xml

 <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <solid android:color="#f6eef1" /> <stroke android:width="2dp" android:color="#000000" /> <padding android:bottom="5dp" android:left="5dp" android:right="5dp" android:top="5dp" /> <corners android:radius="5dp" /> </shape> 

Y dentro de su diseño

 <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginBottom="10dp" android:clipChildren="true" android:background="@drawable/shape"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/your image" android:background="@drawable/shape"> </LinearLayout> 

O puede utilizar un android.support.v7.widget.CardView así:

 <android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content" card_view:cardBackgroundColor="@color/white" card_view:cardCornerRadius="4dp"> <!--YOUR CONTENT--> </android.support.v7.widget.CardView> 

Si tiene problemas al agregar oyentes táctiles al diseño. Utilice este diseño como diseño principal.

 import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.graphics.Region; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.View; import android.widget.FrameLayout; public class RoundedCornerLayout extends FrameLayout { private final static float CORNER_RADIUS = 6.0f; private float cornerRadius; public RoundedCornerLayout(Context context) { super(context); init(context, null, 0); } public RoundedCornerLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } public RoundedCornerLayout(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); setLayerType(View.LAYER_TYPE_SOFTWARE, null); } @Override protected void dispatchDraw(Canvas canvas) { int count = canvas.save(); final Path path = new Path(); path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), cornerRadius, cornerRadius, Path.Direction.CW); canvas.clipPath(path, Region.Op.REPLACE); canvas.clipPath(path); super.dispatchDraw(canvas); canvas.restoreToCount(count); } } 

como

 <?xml version="1.0" encoding="utf-8"?> <com.example.view.RoundedCornerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:id="@+id/patentItem" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingRight="20dp"> ... your child goes here </RelativeLayout> </com.example.view.RoundedCornerLayout> 

Crear un xml round.xml en la carpeta dibujable

 <solid android:color="#FFFFFF" /> <stroke android:width=".05dp" android:color="#d2d2d2" /> <corners android:topLeftRadius="5dp" android:topRightRadius="5dp" android:bottomLeftRadius="5dp" android:bottomRightRadius="5dp" /> 

A continuación, utilizar round.xml como fondo de los elementos .. A continuación, dará esquinas redondeadas

En Android L, sólo podrás usar View.setClipToOutline para obtener ese efecto. En versiones anteriores no hay forma de limitar el contenido de un grupo de vistas aleatorio en una determinada forma.

Usted tendrá que pensar en algo que le daría un efecto similar:

  • Si sólo necesita esquinas redondeadas en ImageView, puede utilizar un sombreador para "pintar" la imagen sobre la forma que está utilizando como fondo. Echa un vistazo a esta biblioteca por ejemplo.

  • Si realmente necesita que todos los niños se corten, tal vez usted puede otra vista sobre su diseño? ¿Uno con un fondo del color que usted está utilizando, y un "agujero redondo" en el centro? En realidad, podría crear un grupo de vistas personalizado que dibuje esa forma sobre todos los niños sobreescribiendo el método onDraw.

La respuesta de Jaap van Hengstum funciona muy bien, sin embargo, creo que es caro y si aplicamos este método en un botón, por ejemplo, el efecto táctil se pierde ya que la vista se representa como un mapa de bits.

Para mí el mejor método y el más sencillo consiste en aplicar una máscara en la vista, así:

 @Override protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { super.onSizeChanged(width, height, oldWidth, oldHeight); float cornerRadius = <whatever_you_want>; this.path = new Path(); this.path.addRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, Path.Direction.CW); } @Override protected void dispatchDraw(Canvas canvas) { if (this.path != null) { canvas.clipPath(this.path); } super.dispatchDraw(canvas); } 

El enlace de tutorial que proporcionaste parece sugerir que debes establecer las propiedades layout_width y layout_height de tus elementos secundarios en match_parent.

 <ImageView android:layout_width="match_parent" android:layout_height="match_parent"> 

Pruebe esta propiedad con su diseño lineal que le ayudará
Herramientas: context = ". Youractivity"

Siga este tutorial y toda la discusión debajo de élhttp://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/

De acuerdo con este post escrito por Guy Romain, uno de los principales desarrolladores de todo el conjunto de herramientas de la interfaz de usuario de Android, es posible hacer un contenedor (y todas sus vistas de niño) con esquinas redondeadas, pero explicó que es demasiado caro Problemas de representación).

Te recomiendo que vayas de acuerdo a su post, y si quieres esquinas redondeadas, luego implementar esquinas redondeadas ImageView acuerdo a este post. Entonces, podría colocarlo dentro de un contenedor con cualquier fondo, y obtendrá el efecto que desea.

Eso es lo que hice también con el tiempo.

Diferencia de la respuesta de Jaap van Hengstum:

  1. Utilice BitmapShader en lugar de mapa de bits de máscara.
  2. Crear mapa de bits sólo una vez.
 public class RoundedFrameLayout extends FrameLayout { private Bitmap mOffscreenBitmap; private Canvas mOffscreenCanvas; private BitmapShader mBitmapShader; private Paint mPaint; private RectF mRectF; public RoundedFrameLayout(Context context) { super(context); init(); } public RoundedFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); init(); } public RoundedFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { setWillNotDraw(false); } @Override public void draw(Canvas canvas) { if (mOffscreenBitmap == null) { mOffscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888); mOffscreenCanvas = new Canvas(mOffscreenBitmap); mBitmapShader = new BitmapShader(mOffscreenBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setShader(mBitmapShader); mRectF = new RectF(0f, 0f, canvas.getWidth(), canvas.getHeight()); } super.draw(mOffscreenCanvas); canvas.drawRoundRect(mRectF, 8, 8, mPaint); } } 
 public class RoundedCornerLayout extends FrameLayout { private double mCornerRadius; public RoundedCornerLayout(Context context) { this(context, null, 0); } public RoundedCornerLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RoundedCornerLayout(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(); setLayerType(View.LAYER_TYPE_SOFTWARE, null); } public double getCornerRadius() { return mCornerRadius; } public void setCornerRadius(double cornerRadius) { mCornerRadius = cornerRadius; } @Override public void draw(Canvas canvas) { int count = canvas.save(); final Path path = new Path(); path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), (float) mCornerRadius, (float) mCornerRadius, Path.Direction.CW); canvas.clipPath(path, Region.Op.REPLACE); canvas.clipPath(path); super.draw(canvas); canvas.restoreToCount(count); } } 
 public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) { Bitmap roundedBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap .getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(roundedBitmap); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); final RectF rectF = new RectF(rect); final float roundPx = pixels; paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(bitmap, rect, rect, paint); return roundedBitmap; } 

Use la forma en xml con rectangle.set la propiedad del radio inferior o superior como want.then aplicar ese xml como fondo a ur view …. o … usar gradientes para hacerlo desde el código.

  • ¿Cómo referenciar un control de otro durante la inflación?
  • Interceptar el botón de menú de Android en un PopupWindow
  • Cargar imágenes en GridView con Universal Image Loader
  • Detectar clics largos en una vista personalizada?
  • Android: textisselectable no funciona en la ventana TYPE_SYSTEM_ALERT
  • Android: LinearLayout addView Animación
  • Cómo alinear el texto en CheckedTextView con casilla de verificación
  • ¿Hay una manera de localizar de forma programática todas las ventanas dentro de una aplicación determinada?
  • Cómo deshabilitar cualquier evento en una vista en Android?
  • Establecer el margen negativo en la vista programáticamente
  • Agregar vista a disposición relativa detrás de una vista existente provoca parpadeo de la pantalla
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.