77 votes

Comment utiliser le canevas Android pour dessiner un rectangle dont seuls les coins supérieur gauche et supérieur droit sont arrondis ?

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

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) ?

5voto

Chris Craik Points 184

Une façon simple et efficace de dessiner un côté solide est d'utiliser l'écrêtage - l'écrêtage de rectangle est essentiellement gratuit, et beaucoup moins de code à écrire qu'un chemin personnalisé.

Si je veux un rectangle de 300x300, avec les parties supérieures gauche et droite arrondies de 50 pixels, c'est possible :

canvas.save();
canvas.clipRect(0, 0, 300, 300);
canvas.drawRoundRect(new RectF(0, 0, 300, 350), 50, 50, paint);
canvas.restore();

Cette approche ne fonctionnera que pour l'arrondi de 2 ou 3 coins adjacents, elle est donc un peu moins configurable qu'une approche basée sur le chemin, mais l'utilisation de rectangles ronds est plus efficace, puisque drawRoundRect() est entièrement accéléré par le matériel (c'est-à-dire, tessellé en triangles) alors que drawPath() revient toujours au rendu logiciel (le logiciel dessine un bitmap de chemin, et le télécharge pour être mis en cache sur le GPU).

Ce n'est pas un gros problème de performance pour les petits dessins peu fréquents, mais si vous animez des chemins, le coût du dessin logiciel peut allonger le temps de trame et augmenter le risque de perte de trames. Le masque de chemin coûte également de la mémoire.

Si vous souhaitez adopter une approche basée sur les chemins, je vous recommande d'utiliser GradientDrawable pour simplifier les lignes de code (en supposant que vous n'ayez pas besoin de définir un shader personnalisé, par exemple pour dessiner un bitmap).

mGradient.setBounds(0, 0, 300, 300);
mGradient.setCornerRadii(new int[] {50,50, 50,50, 0,0, 0,0});

Avec GradientDrawable#setCornerRadii() vous pouvez définir n'importe quel coin pour qu'il soit arrondi, et animer raisonnablement entre les états.

0 votes

C

4voto

M. Ashish Points 104

Voici ma réponse à la question ci-dessus. Ici, j'ai créé une fonction d'extension Kotlin qui utilise les éléments suivants Path ainsi que le quadTo qui peut également être utilisée dans les API de niveau inférieur.

fun Canvas.drawRoundRectPath(
rectF: RectF,
radius: Float,
roundTopLeft: Boolean,
roundTopRight: Boolean,
roundBottomLeft: Boolean,
roundBottomRight: Boolean,
paint: Paint) {

val path = Path()

//Move path cursor to start point
if (roundBottomLeft) {
    path.moveTo(rectF.left, rectF.bottom - radius)
} else {
    path.moveTo(rectF.left, rectF.bottom)
}

// drawing line and rounding top left curve
if (roundTopLeft) {
    path.lineTo(rectF.left, rectF.top + radius)
    path.quadTo(rectF.left, rectF.top, rectF.left + radius, rectF.top)
} else {
    path.lineTo(rectF.left, rectF.top)
}

// drawing line an rounding top right curve
if (roundTopRight) {
    path.lineTo(rectF.right - radius, rectF.top)
    path.quadTo(rectF.right, rectF.top, rectF.right, rectF.top + radius)
} else {
    path.lineTo(rectF.right, rectF.top)
}

// drawing line an rounding bottom right curve
if (roundBottomRight) {
    path.lineTo(rectF.right, rectF.bottom - radius)
    path.quadTo(rectF.right, rectF.bottom, rectF.right - radius, rectF.bottom)
} else {
    path.lineTo(rectF.right, rectF.bottom)
}

// drawing line an rounding bottom left curve
if (roundBottomLeft) {
    path.lineTo(rectF.left + radius, rectF.bottom)
    path.quadTo(rectF.left, rectF.bottom, rectF.left, rectF.bottom - radius)
} else {
    path.lineTo(rectF.left, rectF.bottom)
}
path.close()

drawPath(path, paint)
}

Nous pouvons appeler la fonction avec l'objet canvas et passer l'objet RectF avec la dimension sur laquelle on veut appliquer la courbe.

Nous pouvons également passer le booléen pour les coins que nous voulons arrondir. Cette réponse peut encore être personnalisée pour accepter le rayon des coins individuels.

3voto

Zelimir Points 6851

Vous pouvez le dessiner morceau par morceau en utilisant drawLine() y drawArc() des fonctions de l Canvas .

1 votes

B

0 votes

T

2voto

GreatC Points 181

Utilisez PaintDrawable pourrait être meilleur :

    val topLeftRadius = 10
    val topRightRadius = 10
    val bottomLeftRadius = 0
    val bottomRightRadius = 0
    val rect = Rect(0, 0, 100, 100)
    val paintDrawable = PaintDrawable(Color.RED)
    val outter = floatArrayOf(topLeftRadius, topLeftRadius, topRightRadius, topRightRadius,
            bottomLeftRadius, bottomLeftRadius, bottomRightRadius, bottomRightRadius)
    paintDrawable.setCornerRadii(outter)
    paintDrawable.bounds = rect
    paintDrawable.draw(canvas)

1voto

georgehardcore Points 877

Dessine un rectangle avec des coins arrondis à gauche

  private void drawRoundRect(float left, float top, float right, float bottom, Paint paint, Canvas canvas) {
        Path path = new Path();
        path.moveTo(left, top);
        path.lineTo(right, top);
        path.lineTo(right, bottom);
        path.lineTo(left + radius, bottom);
        path.quadTo(left, bottom, left, bottom - radius);
        path.lineTo(left, top + radius);
        path.quadTo(left, top, left + radius, top);
        canvas.drawPath(path, onlinePaint);
    }

0 votes

T

1 votes

Y

Prograide.com

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.

Powered by:

X