J'ai trouvé une fonction pour les rectangles dont les 4 coins sont arrondis, mais je veux que seuls les 2 coins supérieurs soient arrondis. Que puis-je faire ?
canvas.drawRoundRect(new RectF(0, 100, 100, 300), 6, 6, paint);
J'ai trouvé une fonction pour les rectangles dont les 4 coins sont arrondis, mais je veux que seuls les 2 coins supérieurs soient arrondis. Que puis-je faire ?
canvas.drawRoundRect(new RectF(0, 100, 100, 300), 6, 6, paint);
Pour les API 21 et supérieures, la classe Path a ajouté une nouvelle méthode addRoundRect()
que vous pouvez utiliser comme ceci.
corners = new float[]{
80, 80, // Top left radius in px
80, 80, // Top right radius in px
0, 0, // Bottom right radius in px
0, 0 // Bottom left radius in px
};
final Path path = new Path();
path.addRoundRect(rect, corners, Path.Direction.CW);
canvas.drawPath(path, mPaint);
en Kotlin
val corners = floatArrayOf(
80f, 80f, // Top left radius in px
80f, 80f, // Top right radius in px
0f, 0f, // Bottom right radius in px
0f, 0f // Bottom left radius in px
)
val path = Path()
path.addRoundRect(rect, corners, Path.Direction.CW)
canvas.drawPath(path, mPaint)
Utilisez un chemin. Il a l'avantage de fonctionner pour les API inférieures à 21 (l'Arc est également limité de cette manière, c'est pourquoi je suis quad). Ce qui est un problème car tout le monde n'a pas encore Lollipop. Vous pouvez cependant spécifier un RectF et définir les valeurs avec cela et utiliser Arc pour revenir à l'API 1, mais alors vous ne pourriez pas utiliser un static (sans déclarer un nouvel objet pour construire l'objet).
Dessiner un rectangle arrondi :
path.moveTo(right, top + ry);
path.rQuadTo(0, -ry, -rx, -ry);
path.rLineTo(-(width - (2 * rx)), 0);
path.rQuadTo(-rx, 0, -rx, ry);
path.rLineTo(0, (height - (2 * ry)));
path.rQuadTo(0, ry, rx, ry);
path.rLineTo((width - (2 * rx)), 0);
path.rQuadTo(rx, 0, rx, -ry);
path.rLineTo(0, -(height - (2 * ry)));
path.close();
Comme une fonction complète :
static public Path RoundedRect(float left, float top, float right, float bottom, float rx, float ry, boolean conformToOriginalPost) {
Path path = new Path();
if (rx < 0) rx = 0;
if (ry < 0) ry = 0;
float width = right - left;
float height = bottom - top;
if (rx > width/2) rx = width/2;
if (ry > height/2) ry = height/2;
float widthMinusCorners = (width - (2 * rx));
float heightMinusCorners = (height - (2 * ry));
path.moveTo(right, top + ry);
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
path.rLineTo(-widthMinusCorners, 0);
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
path.rLineTo(0, heightMinusCorners);
if (conformToOriginalPost) {
path.rLineTo(0, ry);
path.rLineTo(width, 0);
path.rLineTo(0, -ry);
}
else {
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
path.rLineTo(widthMinusCorners, 0);
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
return path;
}
Vous devriez aligner jusqu'à ces coins, plutôt que de les traverser. C'est ce que fait le paramètre true de conformToOriginalPost. Il suffit d'aligner jusqu'au point de contrôle.
Si vous voulez faire tout cela mais que vous ne vous souciez pas des trucs pré-Lollipop, et que vous insistez pour que si votre rx et votre ry sont suffisamment élevés, cela devrait dessiner un cercle.
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
static public Path RoundedRect(float left, float top, float right, float bottom, float rx, float ry, boolean conformToOriginalPost) {
Path path = new Path();
if (rx < 0) rx = 0;
if (ry < 0) ry = 0;
float width = right - left;
float height = bottom - top;
if (rx > width/2) rx = width/2;
if (ry > height/2) ry = height/2;
float widthMinusCorners = (width - (2 * rx));
float heightMinusCorners = (height - (2 * ry));
path.moveTo(right, top + ry);
path.arcTo(right - 2*rx, top, right, top + 2*ry, 0, -90, false); //top-right-corner
path.rLineTo(-widthMinusCorners, 0);
path.arcTo(left, top, left + 2*rx, top + 2*ry, 270, -90, false);//top-left corner.
path.rLineTo(0, heightMinusCorners);
if (conformToOriginalPost) {
path.rLineTo(0, ry);
path.rLineTo(width, 0);
path.rLineTo(0, -ry);
}
else {
path.arcTo(left, bottom - 2 * ry, left + 2 * rx, bottom, 180, -90, false); //bottom-left corner
path.rLineTo(widthMinusCorners, 0);
path.arcTo(right - 2 * rx, bottom - 2 * ry, right, bottom, 90, -90, false); //bottom-right corner
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
return path;
}
Ainsi , conformToOriginalPost dessine en fait un rectangle arrondi sans les deux bits inférieurs arrondis.
À mon avis, les fonctions de chemin relatif sont bien meilleures, car vous ne devez vous préoccuper que du seul point où le chemin sera tracé.
@chx101 oui, ok, je l'ai refait en relatif et j'ai commencé sur une courbe pour que la close() puisse couvrir la ligne.
Je dessinerais deux rectangles :
canvas.drawRect(new RectF(0, 110, 100, 290), paint);
canvas.drawRoundRect(new RectF(0, 100, 100, 200), 6, 6, paint);
Ou quelque chose comme ça, il suffit de les superposer pour que les coins supérieurs soient ronds. De préférence, vous devriez écrire une méthode pour cela
Et si j'ai besoin de définir l'alpha pour l'ensemble du rectangle, la section de chevauchement aura une valeur alpha différente des autres.
@V.Kalyuzhnyu la signature de la méthode utilisée dans la réponse est disponible depuis API 1, vous devez parler de drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint)
qui est disponible auprès de l'API 21.
J'ai changé este répondre afin de pouvoir définir le coin que vous voulez rond et celui que vous voulez pointu. fonctionne également sur pré-lolipop
Exemple d'utilisation :
seuls les coins en haut à droite et en bas à droite sont arrondis.
Path path = RoundedRect(0, 0, fwidth , fheight , 5,5,
false, true, true, false);
canvas.drawPath(path,myPaint);
public static Path RoundedRect(
float left, float top, float right, float bottom, float rx, float ry,
boolean tl, boolean tr, boolean br, boolean bl
){
Path path = new Path();
if (rx < 0) rx = 0;
if (ry < 0) ry = 0;
float width = right - left;
float height = bottom - top;
if (rx > width / 2) rx = width / 2;
if (ry > height / 2) ry = height / 2;
float widthMinusCorners = (width - (2 * rx));
float heightMinusCorners = (height - (2 * ry));
path.moveTo(right, top + ry);
if (tr)
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
else{
path.rLineTo(0, -ry);
path.rLineTo(-rx,0);
}
path.rLineTo(-widthMinusCorners, 0);
if (tl)
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
else{
path.rLineTo(-rx, 0);
path.rLineTo(0,ry);
}
path.rLineTo(0, heightMinusCorners);
if (bl)
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
else{
path.rLineTo(0, ry);
path.rLineTo(rx,0);
}
path.rLineTo(widthMinusCorners, 0);
if (br)
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
else{
path.rLineTo(rx,0);
path.rLineTo(0, -ry);
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
return path;
}
Vous devriez corriger ma réponse en ajoutant un arc de Bézier approprié pour l'approximation des angles. spencermortensen.com/articles/bezier-circle Et convertir en utilisant un truc bitwise de style C pour les coins plutôt qu'un tas de booléens. static final int SHARP_TOP_RIGHT = 0b0001, static final int SHARP_TOP_LEFT = 0b0010 ; -- alors vous pouvez l'appeler, getRoundRect(0, 0, fwidth , fheight , 5, 5, SHARP_TOP_LEFT | SHARP_BOTTOM_LEFT) ; avec les ifs étant (if ((SHARP_TOP_LEFT & cornerflag
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
1 votes
Ne pouvez-vous pas simplement dessiner un rectangle arrondi puis un rectangle ordinaire sur la moitié inférieure (en remplaçant les coins arrondis par des coins normaux) ?