Visualizzazione segmentata delle bitmap SkiaSharp
L'oggetto SkiaSharp SKCanvas
definisce un metodo denominato DrawBitmapNinePatch
e due metodi denominati DrawBitmapLattice
molto simili. Entrambi questi metodi eseguono il rendering di una bitmap alle dimensioni di un rettangolo di destinazione, ma invece di estendere la bitmap in modo uniforme, visualizzano parti della bitmap nelle dimensioni in pixel e estendono altre parti della bitmap in modo che si adatti al rettangolo:
Questi metodi vengono in genere usati per il rendering di bitmap che fanno parte di oggetti dell'interfaccia utente, ad esempio pulsanti. Durante la progettazione di un pulsante, in genere vuoi che le dimensioni di un pulsante siano basate sul contenuto del pulsante, ma probabilmente vuoi che il bordo del pulsante sia la stessa larghezza indipendentemente dal contenuto del pulsante. Si tratta di un'applicazione ideale di DrawBitmapNinePatch
.
DrawBitmapNinePatch
è un caso speciale, DrawBitmapLattice
ma è più facile dei due metodi da usare e comprendere.
Visualizzazione a nove patch
Concettualmente, DrawBitmapNinePatch
divide una bitmap in nove rettangoli:
I rettangoli in corrispondenza dei quattro angoli vengono visualizzati nelle dimensioni dei pixel. Come indicano le frecce, le altre aree sui bordi della bitmap vengono estese orizzontalmente o verticalmente all'area del rettangolo di destinazione. Il rettangolo al centro è allungato sia orizzontalmente che verticalmente.
Se non c'è spazio sufficiente nel rettangolo di destinazione per visualizzare anche i quattro angoli nelle dimensioni dei pixel, vengono ridimensionati fino alle dimensioni disponibili e non vengono visualizzati i quattro angoli.
Per dividere una bitmap in questi nove rettangoli, è necessario specificare solo il rettangolo al centro. Questa è la sintassi del DrawBitmapNinePatch
metodo :
canvas.DrawBitmapNinePatch(bitmap, centerRectangle, destRectangle, paint);
Il rettangolo centrale è relativo alla bitmap. Si tratta di un SKRectI
valore (la versione integer di SKRect
) e tutte le coordinate e le dimensioni sono in unità di pixel. Il rettangolo di destinazione è relativo alla superficie di visualizzazione. L'argomento paint
è facoltativo.
La pagina Nine Patch Display nell'esempio usa innanzitutto un costruttore statico per creare una proprietà statica pubblica di tipo 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);
···
}
Altre due pagine di questo articolo usano la stessa bitmap. La bitmap è quadrata di 500 pixel ed è costituita da una matrice di 25 cerchi, tutte le stesse dimensioni, ognuna che occupa un'area quadrata di 100 pixel:
Il costruttore dell'istanza del programma crea un oggetto SKCanvasView
con un PaintSurface
gestore che usa DrawBitmapNinePatch
per visualizzare la bitmap estesa all'intera superficie di visualizzazione:
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);
}
}
Il centerRect
rettangolo comprende la matrice centrale di 16 cerchi. I cerchi negli angoli vengono visualizzati nelle dimensioni dei pixel e tutto il resto viene esteso di conseguenza:
La pagina UWP ha una larghezza di 500 pixel e quindi visualizza le righe superiore e inferiore come una serie di cerchi della stessa dimensione. In caso contrario, tutti i cerchi che non si trovano negli angoli vengono estesi per formare puntini di sospensione.
Per una strana visualizzazione di oggetti costituiti da una combinazione di cerchi e puntini di sospensione, provare a definire il rettangolo centrale in modo che si sovrapponga a righe e colonne di cerchi:
SKRectI centerRect = new SKRectI(150, 150, 350, 350);
Display reticolare
I due DrawBitmapLattice
metodi sono simili a DrawBitmapNinePatch
, ma sono generalizzati per qualsiasi numero di divisioni orizzontali o verticali. Queste divisioni sono definite da matrici di interi corrispondenti ai pixel.
Il DrawBitmapLattice
metodo con parametri per queste matrici di numeri interi non sembra funzionare. Il DrawBitmapLattice
metodo con un parametro di tipo SKLattice
funziona ed è quello usato negli esempi illustrati di seguito.
La SKLattice
struttura definisce quattro proprietà:
XDivs
, una matrice di numeri interiYDivs
, una matrice di numeri interiFlags
, una matrice di , un tipo diSKLatticeFlags
enumerazioneBounds
di tipoNullable<SKRectI>
per specificare un rettangolo di origine facoltativo all'interno della bitmap
La XDivs
matrice divide la larghezza della bitmap in strisce verticali. La prima striscia si estende da pixel 0 a sinistra a XDivs[0]
. Viene eseguito il rendering di questa striscia nella larghezza del pixel. La seconda striscia si estende da XDivs[0]
a XDivs[1]
e viene allungata. La terza striscia si estende da XDivs[1]
a XDivs[2]
e viene eseguito il rendering nella larghezza dei pixel. L'ultima striscia si estende dall'ultimo elemento della matrice al bordo destro della bitmap. Se la matrice ha un numero pari di elementi, viene visualizzata nella larghezza dei pixel. In caso contrario, è allungato. Il numero totale di strip verticali è uno più del numero di elementi nella matrice.
La YDivs
matrice è simile. Divide l'altezza della matrice in strisce orizzontali.
Insieme, la XDivs
matrice e YDivs
divide la bitmap in rettangoli. Il numero di rettangoli è uguale al prodotto del numero di strisce orizzontali e del numero di strisce verticali.
Secondo la documentazione di Skia, la Flags
matrice contiene un elemento per ogni rettangolo, prima la riga superiore dei rettangoli, la seconda riga e così via. La Flags
matrice è di tipo SKLatticeFlags
, un'enumerazione con i membri seguenti:
Default
con valore 0Transparent
con valore 1
Tuttavia, questi flag non sembrano funzionare come dovrebbero, ed è meglio ignorarli. Ma non impostare la Flags
proprietà su null
. Impostarlo su una matrice di SKLatticeFlags
valori sufficientemente grandi da includere il numero totale di rettangoli.
La pagina Reticolare Nine Patch usa DrawBitmapLattice
per simulare DrawBitmapNinePatch
. Usa la stessa bitmap creata in 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);
}
}
Entrambe le XDivs
proprietà e YDivs
sono impostate su matrici di soli due numeri interi, dividendo la bitmap in tre strisce sia orizzontalmente che verticalmente: da pixel 0 a pixel 100 (di cui viene eseguito il rendering nelle dimensioni del pixel), da pixel 100 a pixel 400 (esteso) e da pixel 400 a pixel 500 (dimensioni pixel). XDivs
Insieme e YDivs
definire un totale di 9 rettangoli, ovvero le dimensioni della Flags
matrice. La semplice creazione della matrice è sufficiente per creare una matrice di SKLatticeFlags.Default
valori.
Lo schermo è identico al programma precedente:
La pagina Visualizzazione reticolare divide la bitmap in 16 rettangoli:
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);
}
}
Le XDivs
matrici e YDivs
sono leggermente diverse, causando la visualizzazione non abbastanza simmetrica come gli esempi precedenti:
Nelle immagini iOS e Android a sinistra vengono visualizzati solo i cerchi più piccoli nelle dimensioni dei pixel. Tutto il resto è allungato.
La pagina Visualizzazione reticolare generalizza la creazione della Flags
matrice, consentendo di sperimentare XDivs
e YDivs
più facilmente. In particolare, è necessario vedere cosa accade quando si imposta il primo elemento della XDivs
matrice o YDivs
su 0.