Ça ne marche pas. comme vous l'avez défini, c'est l'arrière-plan, donc le contenu remplace les coins arrondis, et si vous avez du contenu qui dessine sur les coins, vous ne les verrez pas être arrondis.
développeur Android
22
Presque toujours, mon contenu ne couvre jamais les coins. Cela fonctionne parfaitement.
David JY Tang
2
Comment éviter l'erreur Element shape doesn't have the required attribute android:layout_height?
Lorenz
2
Element shape doesn't have the required attribute android:layout_heightLa raison pour laquelle l'erreur a été affichée car layout_bg.xml n'était pas dans le dossier dessinable.
Atul
8
@ nhouser9: en fait, cela ressemble plus à "Cela fonctionne, mais soyez averti que votre premier plan / contenu pourrait dessiner dans les coins". Ainsi, selon le cas d'utilisation, cela pourrait fonctionner à 100%. Je suis content que la réponse n'ait pas autant de downvotes car elle est utile, et je suis content que le commentaire ait une centaine de upvotes car il est facile de repérer les limites de cette solution. Le meilleur des deux mondes.
Benoit Duffez
125
Pour API 21+, utilisez les vues de clip
Un découpage de contour arrondi a été ajouté à la Viewclasse dans l'API 21. Consultez ce document de formation ou cette référence pour plus d'informations.
Cette fonction intégrée rend les coins arrondis très faciles à mettre en œuvre. Il fonctionne sur n'importe quelle vue ou disposition et prend en charge un découpage approprié.
Voici ce qu'il faut faire:
Créez une forme arrondie dessinable et définissez-la comme arrière-plan de votre vue:
android:background="@drawable/round_outline"
Selon la documentation, alors tout ce que vous devez faire est le suivant: android:clipToOutline="true"
Malheureusement, il semble y avoir un bogue et cet attribut XML n'est actuellement pas reconnu. Heureusement, nous pouvons définir l'écrêtage en Java:
Dans votre activité ou fragment: View.setClipToOutline(true)
À quoi il ressemble:
Note spéciale sur ImageViews
setClipToOutline()ne fonctionne que lorsque l'arrière-plan de la vue est défini sur une forme dessinable. Si cette forme d'arrière-plan existe, View traite le contour de l'arrière-plan comme des bordures à des fins de découpe et d'observation.
Cela signifie que si vous souhaitez arrondir les coins d'une ImageView avec setClipToOutline(), votre image doit provenir de la android:srcplace de android:background(puisque l'arrière-plan est utilisé pour la forme arrondie). Si vous DEVEZ utiliser l'arrière-plan pour définir votre image au lieu de src, vous pouvez utiliser cette solution de vues imbriquées:
Créez une disposition extérieure avec son arrière-plan défini à votre forme
Enveloppez cette disposition autour de votre ImageView (sans rembourrage)
ImageView (y compris tout autre élément de la mise en page) sera désormais coupé à la forme arrondie de la mise en page extérieure.
Ne fonctionne pas sur l'API moins de 21. Je ne peux pas attendre que je ne puisse prendre en charge que l'API 21.
startoftext
L'utilisation de 'setClipToOutline' fonctionne, mais elle supprime également le cadre lui-même (le dessin que vous utilisez pour l'arrière-plan). y-a-t-il un moyen d'éviter ça?
développeur android
Avez-vous lu ma note sur l'utilisation src=@drawable...au lieu de background=@drawable? Vous pouvez le faire ou imbriquer votre ImageView dans une vue conteneur qui contient le contour de la forme.
hungryghost
9
Tout le monde commente ce bug --- il a presque trois ans et ne montre aucun signe de correction à tout moment de cette décennie. Mettons un peu de pression.
Josh Hansen
Comment ce bug ne peut-il pas encore être corrigé
P Fuster
74
Voici une copie d'un fichier XML pour créer un dessinable avec un fond blanc, une bordure noire et des coins arrondis:
enregistrez-le en tant que fichier xml dans le répertoire drawable, utilisez-le comme vous utiliseriez n'importe quel arrière-plan drawable (icône ou fichier de ressources) en utilisant son nom de ressource (R.drawable.your_xml_name)
J'ai adoré la possibilité d'arrondir des coins spécifiques
Mercury
1
Cette réponse est à peu près la réponse ci-dessus. Le seul vrai changement ici est la définition de chaque rayon de coin, et étant donné la même valeur pour chaque coin, je l'aurais écrit sur une seule ligne: <corners android:radius="7dp" />:)
ZooMagic
c'est la MEILLEURE réponse pour moi, car elle couvre la disponibilité d'arrondir des coins spécifiques ... bon travail, fonctionne à 100%
Mahmoud Ayman
Les coins de l'ImageView ne sont pas arrondis (coupés), comment résoudre ce problème?
Primož Kralj
Fonctionne toujours en septembre 2019. Nice.
Nikolas Rieble
36
Utilisez CardView dans la bibliothèque de support Android v7. Bien qu'il soit un peu lourd, il résout tous les problèmes et assez facilement. Contrairement à la méthode d'arrière-plan configurable, elle peut réussir à découper les sous-vues.
Beaucoup mieux pour tous ceux qui peuvent «se le permettre» qu'autre chose. Cela me déconcerte qu'une telle chose de base ne fasse pas partie des vues Android standard, étant un aliment de base en CSS pour presque tous les navigateurs Web
Ben Philipp
29
J'ai fait comme ça:
Vérifiez la capture d'écran:
Créez un fichier dessinable nommé avec custom_rectangle.xmldans le dossier dessinable :
Ça ne marche pas. comme vous l'avez défini, c'est l'arrière-plan, donc le contenu remplace les coins arrondis, et si vous avez du contenu qui dessine sur les coins, vous ne les verrez pas être arrondis.
développeur Android
25
Je pense qu'une meilleure façon de le faire est de fusionner 2 choses:
faire une image bitmap de la mise en page, comme indiqué ici .
faire un arrondi dessinable à partir du bitmap, comme indiqué ici
définir le dessin sur une imageView.
Cela traitera les cas que d'autres solutions n'ont pas réussi à résoudre, tels que le contenu comportant des coins.
Je pense que c'est aussi un peu plus convivial pour le GPU, car il montre une seule couche au lieu de 2.
La seule meilleure façon est de créer une vue totalement personnalisée, mais cela représente beaucoup de code et peut prendre beaucoup de temps. Je pense que ce que j'ai suggéré ici est le meilleur des deux mondes.
Voici un extrait de la façon dont cela peut être fait:
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);
}
}
EDIT: a trouvé une alternative intéressante, basée sur la bibliothèque "RoundKornersLayouts" . Avoir une classe qui sera utilisée pour toutes les classes de mise en page que vous souhaitez étendre, à arrondir:
//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()
}
}
Ensuite, dans chacune de vos classes de mise en page personnalisées, ajoutez un code similaire à celui-ci:
Une autre alternative, qui pourrait être plus facile pour la plupart des utilisations: utilisez MaterialCardView. Il permet de personnaliser les coins arrondis, la couleur et la largeur du trait et l'élévation.
Notez qu'il y a un léger problème d'artefacts sur les bords du trait (laisse quelques pixels du contenu là-bas), si vous l'utilisez. Vous pouvez le remarquer si vous zoomez. J'ai signalé ce problème ici .
EDIT: semble être corrigé, mais pas sur l'IDE. Rapporté ici .
Merci d'avoir assemblé cette réponse géniale, cela m'a fait avancer dans la bonne direction, mais je pourrais utiliser de l'aide pour un problème très connexe ici stackoverflow.com/questions/25877515/…
Will Thomson
Cela donne une erreur car aucun constructeur par défaut n'est disponible dans ImageView.
Anuj
Cette réponse devrait être acceptée. Au lieu d'une logique plate, vous êtes tombé et avez trouvé une solution géniale. Cela résout également les problèmes que vous avez mentionnés dans les commentaires d'autres réponses. Merci pour vos efforts et peut-être pouvez-vous redresser une classe entièrement fonctionnelle et la partager via github. Je pense que cela pourrait aider trop de gens.
Tout comme j'ai écrit ci-dessus d'une solution similaire: cela ne fonctionne pas. comme vous l'avez défini, c'est l'arrière-plan, donc le contenu remplace les coins arrondis, et si vous avez du contenu qui dessine sur les coins, vous ne les verrez pas être arrondis.
développeur Android
9
Si vous souhaitez arrondir votre mise en page, il est préférable d'utiliser le CardView, il a fourni de nombreuses fonctionnalités pour rendre le design magnifique.
La méthode la meilleure et la plus simple consisterait à utiliser card_background drawable dans votre mise en page. Cela suit également les directives de conception matérielle de Google. Incluez simplement ceci dans votre LinearLayout:
android:background="@drawable/card_background"
Ajoutez ceci à votre répertoire dessinable et nommez-le card_background.xml :
Utilisez CardView pour obtenir des bords arrondis pour toutes les mises en page. Utilisez card_view: cardCornerRadius = "5dp" pour cardview pour obtenir des bords de mise en page arrondis.
Cela fonctionnera également sous l'API 21 et vous donnera quelque chose comme ceci:
Si vous êtes prêt à faire un peu plus d'efforts pour un meilleur contrôle, utilisez-le android.support.v7.widget.CardViewavec son cardCornerRadiusattribut (et définissez l' elevationattribut sur 0dppour vous débarrasser de toute ombre portée qui l'accompagne avec cardView). En outre, cela fonctionnera à partir du niveau API aussi bas que 15.
Si le contenu correspond à l'arrière-plan, il le remplacera. Il ne se clipse pas vraiment à la forme que vous avez définie.
développeur Android
Tu veux dire une autre vue? Pouvez-vous mettre à jour le code pour montrer ce que vous voulez dire? L'idée est que les coins arrondis ne mettraient pas de zone noire. Dans les coins, il devrait y avoir une couleur transparente.
développeur Android
Oh, je comprends votre question maintenant. Je suppose que pour cela, vous pouvez vous contenter d'une petite marge fixe sur votre contenu
Abdul Wasae
Mais ensuite, le contenu ne sera pas coupé à la forme que vous choisissez, car les marges fixes sont rectangulaires, et non selon la forme que vous choisissez.
développeur Android
5
Fonction pour définir le rayon d'angle par programme
J'ai pris la réponse de @gauravsapiens avec mes commentaires à l'intérieur pour vous donner une compréhension raisonnable de l'effet des paramètres.
<?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 vous cherchez simplement à créer une forme qui arrondit les coins, supprimez le rembourrage et le trait fera l'affaire. Si vous supprimez également le solide, vous aurez en effet créé des coins arrondis sur un fond transparent.
Pour être paresseux, j'ai créé une forme en dessous, qui est juste un fond blanc uni avec des coins arrondis - profitez-en! :)
<?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>
Créez votre xml en dessinable, layout_background.xml
<?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-->
Ensuite, dans votre code, vous pouvez appliquer un ShapeAppearanceModel. Quelque chose comme:
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);
Remarque: il nécessite la version 1.1.0 de la bibliothèque de composants matériels.
Réponses:
1: Définissez layout_bg.xml dans drawables:
2: Ajoutez
layout_bg.xml
comme arrière-plan à votre mise en pagela source
Element shape doesn't have the required attribute android:layout_height
?Element shape doesn't have the required attribute android:layout_height
La raison pour laquelle l'erreur a été affichée car layout_bg.xml n'était pas dans le dossier dessinable.Pour API 21+, utilisez les vues de clip
Un découpage de contour arrondi a été ajouté à la
View
classe dans l'API 21. Consultez ce document de formation ou cette référence pour plus d'informations.Cette fonction intégrée rend les coins arrondis très faciles à mettre en œuvre. Il fonctionne sur n'importe quelle vue ou disposition et prend en charge un découpage approprié.
Voici ce qu'il faut faire:
android:background="@drawable/round_outline"
android:clipToOutline="true"
Malheureusement, il semble y avoir un bogue et cet attribut XML n'est actuellement pas reconnu. Heureusement, nous pouvons définir l'écrêtage en Java:
View.setClipToOutline(true)
À quoi il ressemble:
Note spéciale sur ImageViews
setClipToOutline()
ne fonctionne que lorsque l'arrière-plan de la vue est défini sur une forme dessinable. Si cette forme d'arrière-plan existe, View traite le contour de l'arrière-plan comme des bordures à des fins de découpe et d'observation.Cela signifie que si vous souhaitez arrondir les coins d'une ImageView avec
setClipToOutline()
, votre image doit provenir de laandroid:src
place deandroid:background
(puisque l'arrière-plan est utilisé pour la forme arrondie). Si vous DEVEZ utiliser l'arrière-plan pour définir votre image au lieu de src, vous pouvez utiliser cette solution de vues imbriquées:la source
src=@drawable...
au lieu debackground=@drawable
? Vous pouvez le faire ou imbriquer votre ImageView dans une vue conteneur qui contient le contour de la forme.Voici une copie d'un fichier XML pour créer un dessinable avec un fond blanc, une bordure noire et des coins arrondis:
enregistrez-le en tant que fichier xml dans le répertoire drawable, utilisez-le comme vous utiliseriez n'importe quel arrière-plan drawable (icône ou fichier de ressources) en utilisant son nom de ressource (R.drawable.your_xml_name)
la source
<corners android:radius="7dp" />
:)Utilisez CardView dans la bibliothèque de support Android v7. Bien qu'il soit un peu lourd, il résout tous les problèmes et assez facilement. Contrairement à la méthode d'arrière-plan configurable, elle peut réussir à découper les sous-vues.
la source
J'ai fait comme ça:
Vérifiez la capture d'écran:
Créez un fichier dessinable nommé avec
custom_rectangle.xml
dans le dossier dessinable :Appliquez maintenant l' arrière-plan du rectangle sur la vue :
Terminé
la source
Je pense qu'une meilleure façon de le faire est de fusionner 2 choses:
faire une image bitmap de la mise en page, comme indiqué ici .
faire un arrondi dessinable à partir du bitmap, comme indiqué ici
définir le dessin sur une imageView.
Cela traitera les cas que d'autres solutions n'ont pas réussi à résoudre, tels que le contenu comportant des coins.
Je pense que c'est aussi un peu plus convivial pour le GPU, car il montre une seule couche au lieu de 2.
La seule meilleure façon est de créer une vue totalement personnalisée, mais cela représente beaucoup de code et peut prendre beaucoup de temps. Je pense que ce que j'ai suggéré ici est le meilleur des deux mondes.
Voici un extrait de la façon dont cela peut être fait:
RoundedCornersDrawable.java
CustomView.java
EDIT: a trouvé une alternative intéressante, basée sur la bibliothèque "RoundKornersLayouts" . Avoir une classe qui sera utilisée pour toutes les classes de mise en page que vous souhaitez étendre, à arrondir:
Ensuite, dans chacune de vos classes de mise en page personnalisées, ajoutez un code similaire à celui-ci:
Si vous souhaitez prendre en charge les attributs, utilisez-les tels qu'ils sont écrits sur la bibliothèque:
Une autre alternative, qui pourrait être plus facile pour la plupart des utilisations: utilisez MaterialCardView. Il permet de personnaliser les coins arrondis, la couleur et la largeur du trait et l'élévation.
Exemple:
Et le résultat:
Notez qu'il y a un léger problème d'artefacts sur les bords du trait (laisse quelques pixels du contenu là-bas), si vous l'utilisez. Vous pouvez le remarquer si vous zoomez. J'ai signalé ce problème ici .
EDIT: semble être corrigé, mais pas sur l'IDE. Rapporté ici .
la source
Essaye ça...
1. créer du xml dessinable (custom_layout.xml):
2. ajoutez votre arrière-plan de vue
la source
Si vous souhaitez arrondir votre mise en page, il est préférable d'utiliser le CardView, il a fourni de nombreuses fonctionnalités pour rendre le design magnifique.
Avec cette card_view: cardCornerRadius = "5dp", vous pouvez changer le rayon.
la source
La méthode la meilleure et la plus simple consisterait à utiliser card_background drawable dans votre mise en page. Cela suit également les directives de conception matérielle de Google. Incluez simplement ceci dans votre LinearLayout:
Ajoutez ceci à votre répertoire dessinable et nommez-le card_background.xml :
la source
Utilisez CardView pour obtenir des bords arrondis pour toutes les mises en page. Utilisez card_view: cardCornerRadius = "5dp" pour cardview pour obtenir des bords de mise en page arrondis.
la source
Une meilleure façon de procéder serait:
background_activity.xml
Cela fonctionnera également sous l'API 21 et vous donnera quelque chose comme ceci:
Si vous êtes prêt à faire un peu plus d'efforts pour un meilleur contrôle, utilisez-le
android.support.v7.widget.CardView
avec soncardCornerRadius
attribut (et définissez l'elevation
attribut sur0dp
pour vous débarrasser de toute ombre portée qui l'accompagne avec cardView). En outre, cela fonctionnera à partir du niveau API aussi bas que 15.la source
Fonction pour définir le rayon d'angle par programme
En utilisant
la source
@David, placez simplement la même valeur de remplissage que le trait pour que la bordure soit visible, quelle que soit la taille de l'image
la source
J'ai pris la réponse de @gauravsapiens avec mes commentaires à l'intérieur pour vous donner une compréhension raisonnable de l'effet des paramètres.
Si vous cherchez simplement à créer une forme qui arrondit les coins, supprimez le rembourrage et le trait fera l'affaire. Si vous supprimez également le solide, vous aurez en effet créé des coins arrondis sur un fond transparent.
Pour être paresseux, j'ai créé une forme en dessous, qui est juste un fond blanc uni avec des coins arrondis - profitez-en! :)
la source
Créez votre xml en dessinable,
layout_background.xml
puis ajoutez ceci dans votre
layout.xml
la source
Avec la bibliothèque de composants de matériaux, vous pouvez utiliser le
MaterialShapeDrawable
pour dessiner des formes personnalisées .Mettez simplement le LinearLayout dans votre mise en page XML:
Ensuite, dans votre code, vous pouvez appliquer un
ShapeAppearanceModel
. Quelque chose comme:Remarque: il nécessite la version 1.1.0 de la bibliothèque de composants matériels.
la source
la source