Segmentierte Anzeige von SkiaSharp-Bitmaps
Das SkiaSharp SKCanvas
-Objekt definiert eine Methode mit dem Namen DrawBitmapNinePatch
und zwei Methoden, DrawBitmapLattice
die sehr ähnlich sind. Beide Methoden rendern eine Bitmap auf die Größe eines Zielrechtecks, aber anstatt die Bitmap einheitlich zu strecken, zeigen sie Teile der Bitmap in ihren Pixelabmessungen an und strecken andere Teile der Bitmap so, dass es zum Rechteck passt:
Diese Methoden werden in der Regel zum Rendern von Bitmaps verwendet, die Teil von Benutzeroberflächenobjekten wie Schaltflächen sind. Beim Entwerfen einer Schaltfläche möchten Sie im Allgemeinen, dass die Größe einer Schaltfläche auf dem Inhalt der Schaltfläche basiert, der Rahmen der Schaltfläche jedoch wahrscheinlich die gleiche Breite aufweisen soll, unabhängig vom Inhalt der Schaltfläche. Das ist eine ideale Anwendung von DrawBitmapNinePatch
.
DrawBitmapNinePatch
ist ein Sonderfall, DrawBitmapLattice
aber es ist die einfachere der beiden Methoden zu verwenden und zu verstehen.
Die Neun-Patch-Anzeige
Dividiert eine Bitmap konzeptionell DrawBitmapNinePatch
in neun Rechtecke:
Die Rechtecke an den vier Ecken werden in ihren Pixelgrößen angezeigt. Wie die Pfeile angeben, werden die anderen Bereiche an den Rändern der Bitmap horizontal oder vertikal auf den Bereich des Zielrechtecks gestreckt. Das Rechteck in der Mitte wird horizontal und vertikal gestreckt.
Wenn nicht genügend Platz im Zielrechteck vorhanden ist, um sogar die vier Ecken in ihren Pixelabmessungen anzuzeigen, werden sie auf die verfügbare Größe skaliert, und nichts, sondern die vier Ecken werden angezeigt.
Um eine Bitmap in diese neun Rechtecke zu unterteilen, ist es nur erforderlich, das Rechteck in der Mitte anzugeben. Dies ist die Syntax der DrawBitmapNinePatch
Methode:
canvas.DrawBitmapNinePatch(bitmap, centerRectangle, destRectangle, paint);
Das mittlere Rechteck ist relativ zur Bitmap. Es handelt sich um einen SKRectI
Wert (die ganzzahlige Version von SKRect
) und alle Koordinaten und Größen in Pixeleinheiten. Das Zielrechteck ist relativ zur Anzeigeoberfläche. Das paint
-Argument ist optional.
Die Seite "Neun Patchanzeige" im Beispiel verwendet zunächst einen statischen Konstruktor, um eine öffentliche statische Eigenschaft vom Typ SKBitmap
zu erstellen:
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);
···
}
Zwei andere Seiten in diesem Artikel verwenden dieselbe Bitmap. Die Bitmap ist 500 Pixel quadratisch und besteht aus einem Array von 25 Kreisen, die alle dieselbe Größe aufweisen und jeweils einen Quadratbereich von 100 Pixeln belegen:
Der Instanzkonstruktor des Programms erstellt einen SKCanvasView
mit einem PaintSurface
Handler, DrawBitmapNinePatch
der zum Anzeigen der Bitmap auf die gesamte Anzeigeoberfläche gestreckt wird:
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);
}
}
Das centerRect
Rechteck umfasst das zentrale Array von 16 Kreisen. Die Kreise in den Ecken werden in ihren Pixelabmessungen angezeigt, und alles andere wird entsprechend gestreckt:
Die UWP-Seite ist 500 Pixel breit und zeigt daher die obersten und unteren Zeilen als eine Reihe von Kreisen derselben Größe an. Andernfalls werden alle Kreise, die sich nicht in den Ecken befinden, gestreckt, um Auslassungspunkte zu bilden.
Für eine seltsame Anzeige von Objekten, die aus einer Kombination aus Kreisen und Auslassungspunkten bestehen, versuchen Sie, das mittlere Rechteck so zu definieren, dass es Zeilen und Spalten von Kreisen überlappt:
SKRectI centerRect = new SKRectI(150, 150, 350, 350);
Die Gitteranzeige
Die beiden DrawBitmapLattice
Methoden ähneln DrawBitmapNinePatch
, aber sie werden für eine beliebige Anzahl horizontaler oder vertikaler Divisionen generalisiert. Diese Divisionen werden durch Arrays ganzzahliger Zahlen definiert, die Pixeln entsprechen.
Die DrawBitmapLattice
Methode mit Parametern für diese Arrays ganzzahliger Zahlen scheint nicht zu funktionieren. Die DrawBitmapLattice
Methode mit einem Parameter vom Typ SKLattice
funktioniert, und das ist die Methode, die in den unten gezeigten Beispielen verwendet wird.
Die SKLattice
Struktur definiert vier Eigenschaften:
XDivs
, ein Array ganzzahliger ZahlenYDivs
, ein Array ganzzahliger ZahlenFlags
, ein Array vonSKLatticeFlags
, ein EnumerationstypBounds
vom TypNullable<SKRectI>
zum Angeben eines optionalen Quellrechtecks innerhalb der Bitmap
Das XDivs
Array teilt die Breite der Bitmap in vertikale Streifen auf. Der erste Streifen erstreckt sich von Pixel 0 links nach XDivs[0]
. Dieser Streifen wird in seiner Pixelbreite gerendert. Der zweite Streifen erstreckt sich von XDivs[0]
zu XDivs[1]
, und wird gestreckt. Der dritte Streifen erstreckt sich von XDivs[1]
zu und XDivs[2]
wird in seiner Pixelbreite gerendert. Der letzte Streifen erstreckt sich vom letzten Element des Arrays bis zum rechten Rand der Bitmap. Wenn das Array über eine gerade Anzahl von Elementen verfügt, wird es in seiner Pixelbreite angezeigt. Andernfalls wird sie gestreckt. Die Gesamtzahl der vertikalen Streifen ist eins mehr als die Anzahl der Elemente im Array.
Das YDivs
Array ist ähnlich. Sie teilt die Höhe des Arrays in horizontale Streifen auf.
Zusammen dividieren die XDivs
Bitmap und YDivs
das Array in Rechtecke. Die Anzahl der Rechtecke entspricht dem Produkt der Anzahl der horizontalen Streifen und der Anzahl der vertikalen Streifen.
Laut Skia-Dokumentation enthält das Flags
Array ein Element für jedes Rechteck, zuerst die oberste Zeile von Rechtecke, dann die zweite Zeile usw. Das Flags
Array ist vom Typ SKLatticeFlags
, eine Aufzählung mit den folgenden Membern:
Default
mit Dem Wert 0Transparent
mit Dem Wert 1
Diese Flags scheinen jedoch nicht wie vorgesehen zu funktionieren, und es ist am besten, sie zu ignorieren. Legen Sie die Flags
Eigenschaft jedoch nicht auf null
. Legen Sie es auf ein Array von SKLatticeFlags
Werten fest, das groß genug ist, um die Gesamtzahl der Rechtecke einzuschließen.
Die Lattice Nine Patch-Seite verwendet DrawBitmapLattice
, um nachzuahmen DrawBitmapNinePatch
. Es verwendet die gleiche Bitmap, die 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);
}
}
Sowohl die Eigenschaften YDivs
als auch die XDivs
Arrays von nur zwei ganzen Zahlen werden festgelegt, wobei die Bitmap sowohl horizontal als auch vertikal in drei Streifen unterteilt wird: von Pixel 0 bis Pixel 100 (gerendert in der Pixelgröße), von Pixel 100 bis Pixel 400 (gestreckt) und von Pixel 400 bis Pixel 500 (Pixelgröße). XDivs
Zusammen und YDivs
definieren Sie insgesamt 9 Rechtecke, bei denen es sich um die Größe des Flags
Arrays handelt. Das Erstellen des Arrays reicht einfach aus, um ein Array mit SKLatticeFlags.Default
Werten zu erstellen.
Die Anzeige ist identisch mit dem vorherigen Programm:
Auf der Gitteranzeigeseite wird die Bitmap in 16 Rechtecke unterteilt:
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);
}
}
Die XDivs
Arrays YDivs
sind etwas anders, was dazu führt, dass die Anzeige nicht ganz symmetrisch ist wie in den vorherigen Beispielen:
In den iOS- und Android-Bildern auf der linken Seite werden nur die kleineren Kreise in ihren Pixelgrößen gerendert. Alles andere wird gestreckt.
Die Gitteranzeigeseite generalisiert die Erstellung des Flags
Arrays, sodass Sie einfacher experimentieren XDivs
können YDivs
. Insbesondere sollten Sie sehen, was passiert, wenn Sie das erste Element des XDivs
Arrays YDivs
auf 0 festlegen.