Canvas
Bas niveau
Engine\Native\Canvas est la cible de peinture du moteur de layout : chaque appel de Widget::paint() y empile des commandes de dessin plates en coordonnées pixel absolues (le layout a déjà résolu chaque position au moment où paint() s'exécute), puis toJson() livre ce tableau à NativeCanvasView.kt pour rejeu contre un vrai Canvas Android. C'est un surensemble du protocole NativeDrawCommand de la Phase 0 (rect/text) : il ajoute des champs de bordure optionnels sur rect et laisse text porter une baseline explicite, entre autres. On n'instancie quasiment jamais Canvas soi-même dans un écran applicatif classique — c'est l'objet que le moteur crée et passe à paint() ; l'endroit où on l'utilise directement, c'est en écrivant un Widget personnalisé (voir Widget) ou un CustomPaint.
Exemple
<?php
use Engine\Native\Widget;
use Engine\Native\Canvas;
use Engine\Native\Constraints;
use Engine\Native\Size;
final class Gauge implements Widget
{
private Size $size;
public function __construct(private readonly float $percent)
{
$this->size = Size::zero();
}
public function layout(Constraints $constraints): Size
{
$this->size = $constraints->constrain(new Size(120.0, 24.0));
return $this->size;
}
public function paint(Canvas $canvas, float $x, float $y): void
{
// La cible de peinture : deux rectangles empilés directement,
// sans passer par des Widget enfants.
$canvas->rect($x, $y, $this->size->width, $this->size->height, '#E5E7EB', radius: 12.0);
$canvas->rect($x, $y, $this->size->width * $this->percent, $this->size->height, '#4F46E5', radius: 12.0);
}
}Dans paint() d'un Widget personnalisé, $canvas est reçu en paramètre — jamais construit à la main — et chaque commande (rect, ici) s'accumule dans son tableau interne, exactement comme le fait CustomPaint en interne.
Commandes principales
| Méthode | Description |
|---|---|
rect(x, y, width, height, color = null, radius = 0.0, borderColor = null, borderWidth = 0.0, elevation = 0.0, gradientFrom = null, gradientTo = null) | Rectangle plein/bordé/dégradé, coins arrondis optionnels. |
text(x, y, text, color = '#000000', size = 16.0, bold = false, letterSpacing = 0.0) | Texte à une ligne ; y est la baseline. |
icon(x, y, size, codepoint, color = '#111827') | Glyphe Material Icons (voir MaterialIcons::codepoint()). |
circle(cx, cy, radius, color = null, borderColor = null, borderWidth = 0.0) | Cercle plein/bordé, indépendant d'une boîte englobante. |
line(x1, y1, x2, y2, color, width = 1.0) | Segment de droite. |
arc(cx, cy, radius, startDegrees, sweepDegrees, color, strokeWidth) | Arc tracé, base de CircularProgress. |
hitRegion(x, y, width, height, action, meta = null) | Zone tactile associée à une action (base de Tappable). |
toJson() | Sérialise commandes + zones tactiles + régions hero/dismiss/reorder/lottie + hash stable. |
À savoir.
toJson()inclut unstableHash()calculé sur tout ce qui décide réellement de ce qui est à l'écran (commandes, zones tactiles, régions spéciales) —index.phple compare au dernier hash appliqué côté client et saute l'envoi du payload complet si rien n'a changé, un peu comme le diffing de React/Flutter, mais appliqué au niveau du transport plutôt qu'à un arbre de widgets.