Partager via


Affichage segmenté des bitmaps SkiaSharp

L’objet SkiaSharp SKCanvas définit une méthode nommée DrawBitmapNinePatch et deux méthodes nommées DrawBitmapLattice qui sont très similaires. Ces deux méthodes restituent une bitmap à la taille d’un rectangle de destination, mais au lieu d’étirer uniformément la bitmap, elles affichent des parties de la bitmap dans ses dimensions de pixels et étendent d’autres parties de la bitmap afin qu’elle corresponde au rectangle :

Exemples segmentés

Ces méthodes sont généralement utilisées pour le rendu des bitmaps qui font partie d’objets d’interface utilisateur tels que des boutons. Lors de la conception d’un bouton, vous souhaitez généralement que la taille d’un bouton soit basée sur le contenu du bouton, mais vous souhaitez probablement que la bordure du bouton soit la même largeur, quel que soit le contenu du bouton. C’est une application idéale de DrawBitmapNinePatch.

DrawBitmapNinePatch est un cas particulier, DrawBitmapLattice mais c’est plus facile des deux méthodes à utiliser et à comprendre.

Affichage de neuf correctifs

Conceptuellement, DrawBitmapNinePatch divise une bitmap en neuf rectangles :

Neuf correctifs

Les rectangles aux quatre coins sont affichés dans leurs tailles de pixels. Comme l’indiquent les flèches, les autres zones situées sur les bords de la bitmap sont étirées horizontalement ou verticalement vers la zone du rectangle de destination. Le rectangle au centre est étiré horizontalement et verticalement.

S’il n’y a pas suffisamment d’espace dans le rectangle de destination pour afficher les quatre angles de leurs dimensions de pixels, ils sont réduits à la taille disponible et rien, mais les quatre angles sont affichés.

Pour diviser une bitmap en ces neuf rectangles, il est uniquement nécessaire de spécifier le rectangle dans le centre. Voici la syntaxe de la DrawBitmapNinePatch méthode :

canvas.DrawBitmapNinePatch(bitmap, centerRectangle, destRectangle, paint);

Le rectangle central est relatif à la bitmap. Il s’agit d’une SKRectI valeur (la version entière de SKRect) et toutes les coordonnées et tailles sont exprimées en unités de pixels. Le rectangle de destination est relatif à l’aire d’affichage. L'argument paint est obligatoire.

La page Nine Patch Display dans l’exemple utilise d’abord un constructeur statique pour créer une propriété statique publique de type SKBitmap:

public partial class NinePatchDisplayPage : ContentPage
{
    static NinePatchDisplayPage()
    {
        using (SKCanvas canvas = new SKCanvas(FiveByFiveBitmap))
        using (SKPaint paint = new SKPaint
        {
            Style = SKPaintStyle.Stroke,
            Color = SKColors.Red,
            StrokeWidth = 10
        })
        {
            for (int x = 50; x < 500; x += 100)
                for (int y = 50; y < 500; y += 100)
                {
                    canvas.DrawCircle(x, y, 40, paint);
                }
        }
    }

    public static SKBitmap FiveByFiveBitmap { get; } = new SKBitmap(500, 500);
    ···
}

Deux autres pages de cet article utilisent cette même bitmap. La bitmap est carrée de 500 pixels et se compose d’un tableau de 25 cercles, de la même taille, chacun occupant une zone carrée de 100 pixels :

Grille circulaire

Le constructeur d’instance du programme crée un SKCanvasViewPaintSurface gestionnaire qui utilise DrawBitmapNinePatch pour afficher l’image bitmap étirée sur toute sa surface d’affichage :

public class NinePatchDisplayPage : ContentPage
{
    ···
    public NinePatchDisplayPage()
    {
        Title = "Nine-Patch Display";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        SKRectI centerRect = new SKRectI(100, 100, 400, 400);
        canvas.DrawBitmapNinePatch(FiveByFiveBitmap, centerRect, info.Rect);
    }
}

Le centerRect rectangle englobe le tableau central de 16 cercles. Les cercles dans les coins sont affichés dans leurs dimensions de pixels, et tout le reste est étiré en conséquence :

Affichage de neuf correctifs

La page UWP se trouve à 500 pixels de large, et affiche donc les lignes supérieures et inférieures sous la forme d’une série de cercles de même taille. Sinon, tous les cercles qui ne se trouvent pas dans les coins sont étirés pour former des points de suspension.

Pour un affichage étrange d’objets constitués d’une combinaison de cercles et de points de suspension, essayez de définir le rectangle central afin qu’il chevauche les lignes et les colonnes de cercles :

SKRectI centerRect = new SKRectI(150, 150, 350, 350);

Affichage en treillis

Les deux DrawBitmapLattice méthodes sont similaires à DrawBitmapNinePatch, mais elles sont généralisées pour un nombre quelconque de divisions horizontales ou verticales. Ces divisions sont définies par des tableaux d’entiers correspondant aux pixels.

La DrawBitmapLattice méthode avec des paramètres pour ces tableaux d’entiers ne semble pas fonctionner. La DrawBitmapLattice méthode avec un paramètre de type SKLattice fonctionne, et c’est celle utilisée dans les exemples présentés ci-dessous.

La SKLattice structure définit quatre propriétés :

  • XDivs, tableau d’entiers
  • YDivs, tableau d’entiers
  • Flags, tableau de , type d’énumération SKLatticeFlags
  • Bounds de type Nullable<SKRectI> pour spécifier un rectangle source facultatif dans la bitmap

Le XDivs tableau divise la largeur de la bitmap en bandes verticales. La première bande s’étend de pixel 0 à gauche à XDivs[0]. Cette bande est rendue dans sa largeur de pixels. La deuxième bande s’étend de XDivs[0] jusqu’à XDivs[1], et est étirée. La troisième bande s’étend de XDivs[1] vers XDivs[2] et est rendue dans sa largeur de pixels. La dernière bande s’étend du dernier élément du tableau au bord droit de la bitmap. Si le tableau a un nombre pair d’éléments, il est affiché dans sa largeur de pixels. Sinon, c’est étiré. Le nombre total de bandes verticales est un plus que le nombre d’éléments du tableau.

Le YDivs tableau est similaire. Elle divise la hauteur du tableau en bandes horizontales.

Ensemble, le tableau et YDivs le XDivs tableau divisent la bitmap en rectangles. Le nombre de rectangles est égal au produit du nombre de bandes horizontales et du nombre de bandes verticales.

Selon la documentation Skia, le Flags tableau contient un élément pour chaque rectangle, d’abord la ligne supérieure des rectangles, puis la deuxième ligne, etc. Le Flags tableau est de type SKLatticeFlags, énumération avec les membres suivants :

  • Default avec la valeur 0
  • Transparent avec la valeur 1

Toutefois, ces drapeaux ne semblent pas fonctionner comme ils sont censés, et il est préférable de les ignorer. Mais ne définissez pas la Flags propriété sur null. Définissez-le sur un tableau de SKLatticeFlags valeurs suffisamment grand pour englober le nombre total de rectangles.

La page Lattice Nine Patch utilise DrawBitmapLattice pour imiter DrawBitmapNinePatch. Il utilise la même bitmap créée dans NinePatchDisplayPage:

public class LatticeNinePatchPage : ContentPage
{
    SKBitmap bitmap = NinePatchDisplayPage.FiveByFiveBitmap;

    public LatticeNinePatchPage ()
    {
        Title = "Lattice Nine-Patch";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }
    `
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        SKLattice lattice = new SKLattice();
        lattice.XDivs = new int[] { 100, 400 };
        lattice.YDivs = new int[] { 100, 400 };
        lattice.Flags = new SKLatticeFlags[9];

        canvas.DrawBitmapLattice(bitmap, lattice, info.Rect);
    }
}

Les propriétés et YDivs les XDivs propriétés sont définies sur des tableaux de seulement deux entiers, en divisant l’image bitmap en trois bandes horizontalement et verticalement : de pixel 0 à pixel 100 (rendu dans la taille des pixels), de pixel 100 à pixel 400 (étiré) et de pixel 400 à pixel 500 (taille de pixel). Ensemble, XDivs et YDivs définissez un total de 9 rectangles, qui correspond à la taille du Flags tableau. Il suffit de créer le tableau pour créer un tableau de SKLatticeFlags.Default valeurs.

L’affichage est identique au programme précédent :

Lattice Nine-Patch

La page Affichage de lattice divise la bitmap en 16 rectangles :

public class LatticeDisplayPage : ContentPage
{
    SKBitmap bitmap = NinePatchDisplayPage.FiveByFiveBitmap;

    public LatticeDisplayPage()
    {
        Title = "Lattice Display";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        SKLattice lattice = new SKLattice();
        lattice.XDivs = new int[] { 100, 200, 400 };
        lattice.YDivs = new int[] { 100, 300, 400 };

        int count = (lattice.XDivs.Length + 1) * (lattice.YDivs.Length + 1);
        lattice.Flags = new SKLatticeFlags[count];

        canvas.DrawBitmapLattice(bitmap, lattice, info.Rect);
    }
}

Les XDivs tableaux et YDivs les tableaux sont légèrement différents, ce qui rend l’affichage moins symétrique que les exemples précédents :

Affichage de lattice

Dans les images iOS et Android sur la gauche, seuls les plus petits cercles sont rendus dans leurs tailles de pixels. Tout le reste est étiré.

La page Affichage de lattice généralise la création du Flags tableau, ce qui vous permet d’expérimenter XDivs et YDivs plus facilement. En particulier, vous souhaiterez voir ce qui se passe lorsque vous définissez le premier élément du XDivs tableau sur YDivs 0.