Esto no funciona como ha establecido, es el fondo, por lo que el contenido anula las esquinas redondeadas, y si tiene contenido que se dibuja en las esquinas, no verá que estén redondeadas.
Desarrollador de Android
22
Casi siempre, mi contenido nunca cubre las esquinas. Esto funciona perfectamente
David JY Tang
2
¿Cómo evitas el error Element shape doesn't have the required attribute android:layout_height?
Lorenz
2
Element shape doesn't have the required attribute android:layout_heightLa razón por la que se mostró el error porque layout_bg.xml no estaba dentro de la carpeta de dibujo
Atul
8
@ nhouser9: en realidad es más como "Funciona, pero ten en cuenta que tu primer plano / contenido podría dibujar en las esquinas". Entonces, dependiendo del caso de uso, podría funcionar al 100%. Me alegra que la respuesta no tenga tantos votos negativos porque es útil, y me alegra que el comentario tenga cien votos positivos porque es fácil detectar la limitación con esta solución. Lo mejor de ambos mundos.
Benoit Duffez
125
Para API 21+, use vistas de clip
El recorte de contorno redondeado se agregó a la Viewclase en API 21. Consulte este documento de capacitación o esta referencia para obtener más información.
Esta característica incorporada hace que las esquinas redondeadas sean muy fáciles de implementar. Funciona en cualquier vista o diseño y admite el recorte adecuado.
Esto es lo que debe hacer:
Cree una forma redondeada dibujable y configúrela como fondo de su vista:
android:background="@drawable/round_outline"
De acuerdo con la documentación, todo lo que necesita hacer es esto: android:clipToOutline="true"
Desafortunadamente, parece haber un error y este atributo XML actualmente no se reconoce. Afortunadamente, podemos establecer el recorte en Java:
En su actividad o fragmento: View.setClipToOutline(true)
Cómo se ve:
Nota especial sobre ImageViews
setClipToOutline()solo funciona cuando el fondo de la Vista está configurado en una forma dibujable. Si existe esta forma de fondo, Ver trata el contorno del fondo como los bordes con fines de recorte y sombreado.
Esto significa que si desea redondear las esquinas en un ImageView con setClipToOutline(), su imagen debe venir en android:srclugar de android:background(ya que el fondo se utiliza para la forma redondeada). Si DEBE usar el fondo para configurar su imagen en lugar de src, puede usar esta solución alternativa de vistas anidadas:
Cree un diseño exterior con su fondo establecido en su forma dibujable
Envuelva ese diseño alrededor de su ImageView (sin relleno)
El ImageView (incluyendo cualquier otra cosa en el diseño) ahora se recortará a la forma redondeada del diseño exterior.
No funciona en API menos de 21. No puedo esperar hasta que solo pueda soportar API 21.
startoftext
El uso de 'setClipToOutline' funciona, pero también elimina el marco en sí (el dibujo que utiliza para el fondo). Hay alguna manera de evitar esto?
Desarrollador de Android
¿Leíste mi nota sobre el uso en src=@drawable...lugar de background=@drawable? Puede hacer eso o anidar su ImageView dentro de una vista de contenedor que contiene el contorno de la forma.
hungryghost
99
Todos comentan sobre ese error --- tiene casi tres años y no muestra signos de ser reparado en cualquier momento de esta década. Pongamos un poco de presión.
Josh Hansen
¿Cómo no se puede solucionar este error todavía?
P Fuster
74
Aquí hay una copia de un archivo XML para crear un dibujo con fondo blanco, borde negro y esquinas redondeadas:
guárdelo como un archivo xml en el directorio dibujable, úselo como si fuera cualquier fondo dibujable (icono o archivo de recursos) usando su nombre de recurso (R.drawable.your_xml_name)
Me encantó la posibilidad de redondear esquinas específicas
Mercury
1
Esta respuesta es más o menos la respuesta anterior. El único cambio real aquí es la definición de cada radio de esquina, y dado su mismo valor para cada esquina, lo habría escrito en una línea: <corners android:radius="7dp" />:)
ZooMagic
esta es la MEJOR respuesta para mí, ya que cubre la disponibilidad de redondear esquinas específicas ... buen trabajo, funciona al 100%
Mahmoud Ayman
Las esquinas de ImageView no están redondeadas (recortadas), ¿cómo resuelvo esto?
Primož Kralj
Todavía funciona en septiembre de 2019. Agradable.
Nikolas Rieble
36
Utilice CardView en la biblioteca de soporte de Android v7. Aunque es un poco pesado, resuelve todos los problemas y es bastante fácil. No como el método de fondo dibujable establecido, podría recortar subvistas con éxito.
Mucho mejor para todos los que pueden "pagar" que cualquier otra cosa. Me desconcierta que algo tan básico no sea parte de las vistas estándar de Android, ya que es un elemento básico en CSS para casi cualquier navegador web
Ben Philipp
29
He hecho de esta manera:
Comprobar captura de pantalla:
Cree un archivo dibujable nombrado con custom_rectangle.xmlen la carpeta dibujable :
Esto no funciona como ha establecido, es el fondo, por lo que el contenido anula las esquinas redondeadas, y si tiene contenido que se dibuja en las esquinas, no verá que estén redondeadas.
Desarrollador de Android
25
Creo que una mejor manera de hacerlo es fusionar 2 cosas:
haga un mapa de bits del diseño, como se muestra aquí .
hacer un dibujo redondeado desde el mapa de bits, como se muestra aquí
establecer el dibujable en una imageView.
Esto manejará casos que otras soluciones no han podido resolver, como tener contenido que tiene esquinas.
Creo que también es un poco más amigable con la GPU, ya que muestra una sola capa en lugar de 2.
La única mejor manera es hacer una vista totalmente personalizada, pero eso es mucho código y puede llevar mucho tiempo. Creo que lo que sugerí aquí es lo mejor de ambos mundos.
Aquí hay un fragmento de cómo se puede hacer:
RoundedCornersDrawable.java
/**
* shows a bitmap as if it had rounded corners. based on :
* http://rahulswackyworld.blogspot.co.il/2013/04/android-drawables-with-rounded_7.html
* easy alternative from support library: RoundedBitmapDrawableFactory.create( ...) ;
*/
public class RoundedCornersDrawable extends BitmapDrawable {
private final BitmapShader bitmapShader;
private final Paint p;
private final RectF rect;
private final float borderRadius;
public RoundedCornersDrawable(final Resources resources, final Bitmap bitmap, final float borderRadius) {
super(resources, bitmap);
bitmapShader = new BitmapShader(getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
final Bitmap b = getBitmap();
p = getPaint();
p.setAntiAlias(true);
p.setShader(bitmapShader);
final int w = b.getWidth(), h = b.getHeight();
rect = new RectF(0, 0, w, h);
this.borderRadius = borderRadius < 0 ? 0.15f * Math.min(w, h) : borderRadius;
}
@Override
public void draw(final Canvas canvas) {
canvas.drawRoundRect(rect, borderRadius, borderRadius, p);
}
}
CustomView.java
public class CustomView extends ImageView {
private View mMainContainer;
private boolean mIsDirty=false;
// TODO for each change of views/content, set mIsDirty to true and call invalidate
@Override
protected void onDraw(final Canvas canvas) {
if (mIsDirty) {
mIsDirty = false;
drawContent();
return;
}
super.onDraw(canvas);
}
/**
* draws the view's content to a bitmap. code based on :
* http://nadavfima.com/android-snippet-inflate-a-layout-draw-to-a-bitmap/
*/
public static Bitmap drawToBitmap(final View viewToDrawFrom, final int width, final int height) {
// Create a new bitmap and a new canvas using that bitmap
final Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bmp);
viewToDrawFrom.setDrawingCacheEnabled(true);
// Supply measurements
viewToDrawFrom.measure(MeasureSpec.makeMeasureSpec(canvas.getWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(canvas.getHeight(), MeasureSpec.EXACTLY));
// Apply the measures so the layout would resize before drawing.
viewToDrawFrom.layout(0, 0, viewToDrawFrom.getMeasuredWidth(), viewToDrawFrom.getMeasuredHeight());
// and now the bmp object will actually contain the requested layout
canvas.drawBitmap(viewToDrawFrom.getDrawingCache(), 0, 0, new Paint());
return bmp;
}
private void drawContent() {
if (getMeasuredWidth() <= 0 || getMeasuredHeight() <= 0)
return;
final Bitmap bitmap = drawToBitmap(mMainContainer, getMeasuredWidth(), getMeasuredHeight());
final RoundedCornersDrawable drawable = new RoundedCornersDrawable(getResources(), bitmap, 15);
setImageDrawable(drawable);
}
}
EDITAR: encontró una buena alternativa, basada en la biblioteca "RoundKornersLayouts" . Tenga una clase que se utilizará para todas las clases de diseño que desea extender, que se redondeará:
//based on https://github.com/JcMinarro/RoundKornerLayouts
class CanvasRounder(cornerRadius: Float, cornerStrokeColor: Int = 0, cornerStrokeWidth: Float = 0F) {
private val path = android.graphics.Path()
private lateinit var rectF: RectF
private var strokePaint: Paint?
var cornerRadius: Float = cornerRadius
set(value) {
field = value
resetPath()
}
init {
if (cornerStrokeWidth <= 0)
strokePaint = null
else {
strokePaint = Paint()
strokePaint!!.style = Paint.Style.STROKE
strokePaint!!.isAntiAlias = true
strokePaint!!.color = cornerStrokeColor
strokePaint!!.strokeWidth = cornerStrokeWidth
}
}
fun round(canvas: Canvas, drawFunction: (Canvas) -> Unit) {
val save = canvas.save()
canvas.clipPath(path)
drawFunction(canvas)
if (strokePaint != null)
canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, strokePaint)
canvas.restoreToCount(save)
}
fun updateSize(currentWidth: Int, currentHeight: Int) {
rectF = android.graphics.RectF(0f, 0f, currentWidth.toFloat(), currentHeight.toFloat())
resetPath()
}
private fun resetPath() {
path.reset()
path.addRoundRect(rectF, cornerRadius, cornerRadius, Path.Direction.CW)
path.close()
}
}
Luego, en cada una de sus clases de diseño personalizadas, agregue un código similar a este:
Otra alternativa, que podría ser más fácil para la mayoría de los usos: usar MaterialCardView. Permite personalizar las esquinas redondeadas, el color y el ancho del trazo y la elevación.
Tenga en cuenta que hay un pequeño problema con los artefactos en los bordes del trazo (deja algunos píxeles del contenido allí), si lo usa. Puede notarlo si hace zoom. He informado sobre este problema aquí .
EDITAR: parece estar arreglado, pero no en el IDE. Reportado aquí .
Gracias por reunir esta asombrosa respuesta. Me ayudó a avanzar en la dirección correcta, pero podría necesitar ayuda con un problema muy relacionado aquí stackoverflow.com/questions/25877515/…
Will Thomson
Esto da error ya que no hay un constructor predeterminado disponible en ImageView.
Anuj
Esta debe ser la respuesta aceptada. En lugar de una lógica plana, bajó y encontró una solución increíble. Además, esto resuelve los problemas que mencionó en los comentarios a otras respuestas. Gracias por su esfuerzo y tal vez pueda corregir una clase completamente funcional y compartirla a través de github. Creo que podría ayudar a demasiadas personas.
Tal como escribí anteriormente sobre una solución similar: esto no funciona. como ha establecido, es el fondo, por lo que el contenido anula las esquinas redondeadas, y si tiene contenido que se dibuja en las esquinas, no verá que estén redondeadas.
desarrollador de Android
9
Si desea redondear su diseño, es mejor usar CardView, ya que proporciona muchas funciones para que el diseño sea hermoso.
El método mejor y más simple sería hacer uso de card_background dibujable en su diseño. Esto también sigue las pautas de diseño de materiales de Google. Solo incluye esto en tu LinearLayout:
android:background="@drawable/card_background"
Agregue esto a su directorio dibujable y asígnele el nombre card_background.xml :
Use CardView para obtener bordes redondeados para cualquier diseño. Use card_view: cardCornerRadius = "5dp" para cardview para obtener bordes de diseño redondeados.
Esto funcionará debajo de API 21 también, y le dará algo como esto:
Si está dispuesto a hacer un poco más de esfuerzo para tener un mejor control, utilícelo android.support.v7.widget.CardViewcon su cardCornerRadiusatributo (y establezca el elevationatributo en 0dppara deshacerse de cualquier sombra paralela que acompañe a cardView). Además, esto funcionará desde un nivel API tan bajo como 15.
Si el contenido se ajusta al fondo, lo anulará. Realmente no se ajusta a la forma que ha establecido.
Desarrollador de Android
¿Te refieres a otra vista? ¿Puede actualizar el código para mostrar lo que quiere decir? La idea es que las esquinas redondeadas no pondrían área negra. Alrededor de las esquinas, debe haber un color transparente.
Desarrollador de Android
Oh, ahora tengo tu pregunta. Supongo que puede hacerlo con un pequeño margen fijo en su contenido
Abdul Wasae
Pero entonces, el contenido no se cortará a la forma que elija, porque los márgenes fijos son rectangulares y no de acuerdo con la forma que elija.
desarrollador de Android
5
Función para establecer el radio de la esquina mediante programación
He tomado la respuesta de @gauravsapiens con mis comentarios dentro para darle una comprensión razonable de lo que afectarán los parámetros.
<?xml version="1.0" encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"><!-- Background color --><solidandroid:color="@color/white"/><!-- Stroke around the background, width and color --><strokeandroid:width="4dp"android:color="@color/drop_shadow"/><!-- The corners of the shape --><cornersandroid:radius="4dp"/><!-- Padding for the background, e.g the Text inside a TextView will be
located differently --><paddingandroid:left="10dp"android:right="10dp"android:bottom="10dp"android:top="10dp"/></shape>
Si solo está buscando crear una forma que redondee las esquinas, eliminará el relleno y el trazo funcionará. Si elimina el sólido también, en efecto, habrá creado esquinas redondeadas en un fondo transparente.
En aras de ser flojo, he creado una forma debajo, que es solo un fondo blanco sólido con esquinas redondeadas, ¡disfruta! :)
<?xml version="1.0" encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"><!-- Background color --><solidandroid:color="@color/white"/><!-- The corners of the shape --><cornersandroid:radius="4dp"/></shape>
<?xml version="1.0" encoding="utf-8"?><shapexmlns:android="http://schemas.android.com/apk/res/android"><solidandroid:color="@color/your_colour"/><strokeandroid:width="2dp"android:color="@color/your_colour"/><cornersandroid:radius="10dp"/></shape>
<--width, color, radius should be as per your requirement-->
Luego, en su código, puede aplicar a ShapeAppearanceModel. Algo como:
float radius = getResources().getDimension(R.dimen.default_corner_radius);
LinearLayout linearLayout= findViewById(R.id.linear_rounded);
ShapeAppearanceModel shapeAppearanceModel = new ShapeAppearanceModel()
.toBuilder()
.setAllCorners(CornerFamily.ROUNDED,radius)
.build();
MaterialShapeDrawable shapeDrawable = new MaterialShapeDrawable(shapeAppearanceModel);
//Fill the LinearLayout with your color
shapeDrawable.setFillColor(ContextCompat.getColorStateList(this,R.color.secondaryLightColor));
ViewCompat.setBackground(linearLayout,shapeDrawable);
Nota :: requiere la versión 1.1.0 de la biblioteca de componentes de material.
Respuestas:
1: Definir layout_bg.xml en elementos dibujables :
2: Agregar
layout_bg.xml
como fondo a su diseñofuente
Element shape doesn't have the required attribute android:layout_height
?Element shape doesn't have the required attribute android:layout_height
La razón por la que se mostró el error porque layout_bg.xml no estaba dentro de la carpeta de dibujoPara API 21+, use vistas de clip
El recorte de contorno redondeado se agregó a la
View
clase en API 21. Consulte este documento de capacitación o esta referencia para obtener más información.Esta característica incorporada hace que las esquinas redondeadas sean muy fáciles de implementar. Funciona en cualquier vista o diseño y admite el recorte adecuado.
Esto es lo que debe hacer:
android:background="@drawable/round_outline"
android:clipToOutline="true"
Desafortunadamente, parece haber un error y este atributo XML actualmente no se reconoce. Afortunadamente, podemos establecer el recorte en Java:
View.setClipToOutline(true)
Cómo se ve:
Nota especial sobre ImageViews
setClipToOutline()
solo funciona cuando el fondo de la Vista está configurado en una forma dibujable. Si existe esta forma de fondo, Ver trata el contorno del fondo como los bordes con fines de recorte y sombreado.Esto significa que si desea redondear las esquinas en un ImageView con
setClipToOutline()
, su imagen debe venir enandroid:src
lugar deandroid:background
(ya que el fondo se utiliza para la forma redondeada). Si DEBE usar el fondo para configurar su imagen en lugar de src, puede usar esta solución alternativa de vistas anidadas:fuente
src=@drawable...
lugar debackground=@drawable
? Puede hacer eso o anidar su ImageView dentro de una vista de contenedor que contiene el contorno de la forma.Aquí hay una copia de un archivo XML para crear un dibujo con fondo blanco, borde negro y esquinas redondeadas:
guárdelo como un archivo xml en el directorio dibujable, úselo como si fuera cualquier fondo dibujable (icono o archivo de recursos) usando su nombre de recurso (R.drawable.your_xml_name)
fuente
<corners android:radius="7dp" />
:)Utilice CardView en la biblioteca de soporte de Android v7. Aunque es un poco pesado, resuelve todos los problemas y es bastante fácil. No como el método de fondo dibujable establecido, podría recortar subvistas con éxito.
fuente
He hecho de esta manera:
Comprobar captura de pantalla:
Cree un archivo dibujable nombrado con
custom_rectangle.xml
en la carpeta dibujable :Ahora aplique el fondo Rectángulo en la Vista :
Hecho
fuente
Creo que una mejor manera de hacerlo es fusionar 2 cosas:
haga un mapa de bits del diseño, como se muestra aquí .
hacer un dibujo redondeado desde el mapa de bits, como se muestra aquí
establecer el dibujable en una imageView.
Esto manejará casos que otras soluciones no han podido resolver, como tener contenido que tiene esquinas.
Creo que también es un poco más amigable con la GPU, ya que muestra una sola capa en lugar de 2.
La única mejor manera es hacer una vista totalmente personalizada, pero eso es mucho código y puede llevar mucho tiempo. Creo que lo que sugerí aquí es lo mejor de ambos mundos.
Aquí hay un fragmento de cómo se puede hacer:
RoundedCornersDrawable.java
CustomView.java
EDITAR: encontró una buena alternativa, basada en la biblioteca "RoundKornersLayouts" . Tenga una clase que se utilizará para todas las clases de diseño que desea extender, que se redondeará:
Luego, en cada una de sus clases de diseño personalizadas, agregue un código similar a este:
Si desea admitir atributos, use esto como está escrito en la biblioteca:
Otra alternativa, que podría ser más fácil para la mayoría de los usos: usar MaterialCardView. Permite personalizar las esquinas redondeadas, el color y el ancho del trazo y la elevación.
Ejemplo:
Y el resultado:
Tenga en cuenta que hay un pequeño problema con los artefactos en los bordes del trazo (deja algunos píxeles del contenido allí), si lo usa. Puede notarlo si hace zoom. He informado sobre este problema aquí .
EDITAR: parece estar arreglado, pero no en el IDE. Reportado aquí .
fuente
Prueba esto...
1.crear xml dibujable (custom_layout.xml):
2.agregue su fondo de vista
fuente
Si desea redondear su diseño, es mejor usar CardView, ya que proporciona muchas funciones para que el diseño sea hermoso.
Con este card_view: cardCornerRadius = "5dp", puede cambiar el radio.
fuente
El método mejor y más simple sería hacer uso de card_background dibujable en su diseño. Esto también sigue las pautas de diseño de materiales de Google. Solo incluye esto en tu LinearLayout:
Agregue esto a su directorio dibujable y asígnele el nombre card_background.xml :
fuente
Use CardView para obtener bordes redondeados para cualquier diseño. Use card_view: cardCornerRadius = "5dp" para cardview para obtener bordes de diseño redondeados.
fuente
Una mejor manera de hacerlo sería:
background_activity.xml
Esto funcionará debajo de API 21 también, y le dará algo como esto:
Si está dispuesto a hacer un poco más de esfuerzo para tener un mejor control, utilícelo
android.support.v7.widget.CardView
con sucardCornerRadius
atributo (y establezca elelevation
atributo en0dp
para deshacerse de cualquier sombra paralela que acompañe a cardView). Además, esto funcionará desde un nivel API tan bajo como 15.fuente
Función para establecer el radio de la esquina mediante programación
Utilizando
fuente
@David, solo ponga el mismo valor de relleno que el trazo, para que el borde pueda ser visible, independientemente del tamaño de la imagen
fuente
He tomado la respuesta de @gauravsapiens con mis comentarios dentro para darle una comprensión razonable de lo que afectarán los parámetros.
Si solo está buscando crear una forma que redondee las esquinas, eliminará el relleno y el trazo funcionará. Si elimina el sólido también, en efecto, habrá creado esquinas redondeadas en un fondo transparente.
En aras de ser flojo, he creado una forma debajo, que es solo un fondo blanco sólido con esquinas redondeadas, ¡disfruta! :)
fuente
Crea tu xml en dibujable,
layout_background.xml
y luego, agregue esto en su
layout.xml
fuente
Con la Biblioteca de componentes de material puede usar
MaterialShapeDrawable
para dibujar formas personalizadas .Simplemente coloque LinearLayout en su diseño xml:
Luego, en su código, puede aplicar a
ShapeAppearanceModel
. Algo como:Nota :: requiere la versión 1.1.0 de la biblioteca de componentes de material.
fuente
fuente