Teilen über


Kerngrafiken in Xamarin.iOS

In diesem Artikel werden die Core Graphics iOS-Frameworks erläutert. Es zeigt, wie Sie mit Core Graphics Geometrie, Bilder und PDF-Dateien zeichnen.

iOS enthält das Core Graphics Framework, um Unterstützung für Die Zeichnung auf niedriger Ebene bereitzustellen. Diese Frameworks ermöglichen die umfangreichen grafischen Funktionen in UIKit.

Core Graphics ist ein 2D-Grafikframework auf niedriger Ebene, das unabhängige Grafiken für Das Zeichnen von Geräten ermöglicht. Alle 2D-Zeichnung in UIKit verwendet Core Graphics intern.

Kerngrafiken unterstützen das Zeichnen in einer Reihe von Szenarien, einschließlich:

Geometrischer Raum

Unabhängig vom Szenario erfolgt die gesamte Zeichnung mit Core Graphics im geometrischen Raum, was bedeutet, dass sie in abstrakten Punkten und nicht in Pixeln funktioniert. Sie beschreiben, was In Bezug auf Geometrie und Zeichnungszustand gezeichnet werden soll, z. B. Farben, Linienarten usw. und Kerngrafikhandles, die alles in Pixel übersetzen. Dieser Zustand wird einem Grafikkontext hinzugefügt, den Sie sich wie die Canvas eines Malers vorstellen können.

Für diesen Ansatz gibt es einige Vorteile:

  • Zeichnungscode wird dynamisch und kann anschließend Grafiken zur Laufzeit ändern.
  • Die Verringerung der Notwendigkeit statischer Bilder im Anwendungsbundle kann die Anwendungsgröße verringern.
  • Grafiken werden widerstandsfähiger für Auflösungsänderungen auf allen Geräten.

Zeichnen in einer UIView-Unterklasse

Jedes UIView verfügt über eine Draw Methode, die vom System aufgerufen wird, wenn sie gezeichnet werden muss. So fügen Sie einer Ansicht, Unterklasse UIView und Außerkraftsetzung DrawZeichnungscode hinzu:

public class TriangleView : UIView
{
    public override void Draw (CGRect rect)
    {
        base.Draw (rect);
    }
}

Draw sollte niemals direkt aufgerufen werden. Es wird vom System während der Ausführungsschleifenverarbeitung aufgerufen. Wenn eine Ansicht der Ansichtshierarchie zum ersten Mal durch die Ausführungsschleife hinzugefügt wurde, wird die Draw Methode aufgerufen. Nachfolgende Aufrufe, die auftreten, Draw wenn die Ansicht als gezeichnet werden muss, indem sie entweder SetNeedsDisplay oder SetNeedsDisplayInRect in der Ansicht aufgerufen werden muss.

Muster für Grafikcode

Der Code in der Draw Implementierung sollte beschreiben, was gezeichnet werden soll. Der Zeichnungscode folgt einem Muster, in dem er einen Zeichnungszustand festlegt und eine Methode aufruft, um die Zeichnung anzufordern. Dieses Muster kann wie folgt generalisiert werden:

  1. Rufen Sie einen Grafikkontext ab.

  2. Einrichten von Zeichnungsattributen.

  3. Erstellen Sie einige Geometrien aus Zeichnungsgrundtypen.

  4. Rufen Sie eine Draw- oder Stroke-Methode auf.

Beispiel für einfache Zeichnung

Sehen Sie sich z. B. folgenden Codeausschnitt an:

//get graphics context
using (CGContext g = UIGraphics.GetCurrentContext ()) {

    //set up drawing attributes
    g.SetLineWidth (10);
    UIColor.Blue.SetFill ();
    UIColor.Red.SetStroke ();

    //create geometry
    var path = new CGPath ();

    path.AddLines (new CGPoint[]{
    new CGPoint (100, 200),
    new CGPoint (160, 100),
    new CGPoint (220, 200)});

    path.CloseSubpath ();

    //add geometry to graphics context and draw it
    g.AddPath (path);
    g.DrawPath (CGPathDrawingMode.FillStroke);
}

Lassen Sie uns diesen Code aufschlüsseln:

using (CGContext g = UIGraphics.GetCurrentContext ()) {
...
}

Mit dieser Linie wird zunächst der aktuelle Grafikkontext für die Zeichnung verwendet. Sie können sich einen Grafikkontext vorstellen, da der Zeichenbereich, auf dem die Zeichnung ausgeführt wird, den gesamten Zustand der Zeichnung enthält, z. B. Strich- und Füllfarben, sowie die zu zeichnende Geometrie.

g.SetLineWidth (10);
UIColor.Blue.SetFill ();
UIColor.Red.SetStroke ();

Nach dem Abrufen eines Grafikkontexts richtet der Code einige Attribute ein, die beim Zeichnen verwendet werden sollen, wie oben gezeigt. In diesem Fall werden die Linienbreite, Strich- und Füllfarben festgelegt. Jede nachfolgende Zeichnung verwendet dann diese Attribute, da sie im Zustand des Grafikkontexts beibehalten werden.

Zum Erstellen der Geometrie verwendet der Code einen CGPath, der es ermöglicht, einen Grafikpfad aus Linien und Kurven zu beschreiben. In diesem Fall fügt der Pfad Linien hinzu, die ein Array von Punkten verbinden, um ein Dreieck zu bilden. Wie unten dargestellt, verwendet Core Graphics ein Koordinatensystem für die Ansichtszeichnung, wobei sich der Ursprung oben links befindet, mit positivem x-direkt nach rechts und der positiven Richtung nach unten:

var path = new CGPath ();

path.AddLines (new CGPoint[]{
new CGPoint (100, 200),
new CGPoint (160, 100),
new CGPoint (220, 200)});

path.CloseSubpath ();

Nachdem der Pfad erstellt wurde, wird er dem Grafikkontext hinzugefügt, sodass der Aufruf AddPath bzw DrawPath . er gezeichnet werden kann.

Die resultierende Ansicht wird unten angezeigt:

Das Beispielausgabedreieck

Erstellen von Farbverlaufsfüllungen

Umfangreichere Zeichnungsarten sind ebenfalls verfügbar. Beispielsweise ermöglicht Core Graphics das Erstellen von Farbverlaufsfüllungen und das Anwenden von Clippingpfaden. Um eine Farbverlaufsfüllung innerhalb des Pfads aus dem vorherigen Beispiel zu zeichnen, muss zuerst der Pfad als Clippingpfad festgelegt werden:

// add the path back to the graphics context so that it is the current path
g.AddPath (path);
// set the current path to be the clipping path
g.Clip ();

Durch Festlegen des aktuellen Pfads als Clippingpfad wird die gesamte nachfolgende Zeichnung innerhalb der Geometrie des Pfads eingeschränkt, z. B. der folgende Code, der einen linearen Farbverlauf zeichnet:

// the color space determines how Core Graphics interprets color information
    using (CGColorSpace rgb = CGColorSpace.CreateDeviceRGB()) {
        CGGradient gradient = new CGGradient (rgb, new CGColor[] {
        UIColor.Blue.CGColor,
        UIColor.Yellow.CGColor
    });

// draw a linear gradient
    g.DrawLinearGradient (
        gradient,
        new CGPoint (path.BoundingBox.Left, path.BoundingBox.Top),
        new CGPoint (path.BoundingBox.Right, path.BoundingBox.Bottom),
        CGGradientDrawingOptions.DrawsBeforeStartLocation);
    }

Diese Änderungen erzeugen eine Farbverlaufsfüllung wie unten dargestellt:

Das Beispiel mit einer Farbverlaufsfüllung

Ändern von Linienmustern

Die Zeichnungsattribute von Linien können auch mit Core Graphics geändert werden. Dazu gehören das Ändern der Linienbreite und der Strichfarbe sowie des Linienmusters selbst, wie im folgenden Code dargestellt:

//use a dashed line
g.SetLineDash (0, new nfloat[] { 10, 4 * (nfloat)Math.PI });

Wenn Sie diesen Code hinzufügen, bevor zeichnungsvorgänge 10 Striche lang sind, mit 4 Einheiten Abstand zwischen Strichen, wie unten dargestellt:

Hinzufügen dieses Codes vor zeichnungsvorgängen führt zu gestrichelten Strichen

Beachten Sie, dass bei Verwendung der einheitlichen API in Xamarin.iOS der Arraytyp ein nfloatArraytyp sein muss und auch explizit in Math.PI umgestellt werden muss.

Zeichnungsbilder und Text

Neben Zeichnungspfaden im Grafikkontext einer Ansicht unterstützt Core Graphics auch Zeichnungsbilder und Text. Um ein Bild zu zeichnen, erstellen Sie einfach ein CGImage Bild, und übergeben Sie es an einen DrawImage Anruf:

public override void Draw (CGRect rect)
{
    base.Draw (rect);

    using(CGContext g = UIGraphics.GetCurrentContext ()){
        g.DrawImage (rect, UIImage.FromFile ("MyImage.png").CGImage);
    }
}

Dies erzeugt jedoch ein Bild, das auf dem Kopf gezeichnet wird, wie unten dargestellt:

Ein Bild, das auf dem Kopf gezeichnet wurde

Der Grund dafür ist core Graphics origin for image drawing is in the lower left, while the view has its origin in the upper left. Damit das Bild korrekt angezeigt wird, muss der Ursprung geändert werden, der durch Ändern der Current Transformation Matrix (CTM) erreicht werden kann. Das CTM definiert, wo Punkte leben, auch als Benutzerbereich bezeichnet. Das Umkehren des CTM in die y-Richtung und das Verschieben durch die Höhe der Grenzen in der negativen Y-Richtung kann das Bild kippen.

Der Grafikkontext verfügt über Hilfsmethoden zum Transformieren des CTM. In diesem Fall ScaleCTM wird die Zeichnung gedreht und TranslateCTM nach oben links verschoben, wie unten dargestellt:

public override void Draw (CGRect rect)
{
    base.Draw (rect);

    using (CGContext g = UIGraphics.GetCurrentContext ()) {

        // scale and translate the CTM so the image appears upright
        g.ScaleCTM (1, -1);
        g.TranslateCTM (0, -Bounds.Height);
        g.DrawImage (rect, UIImage.FromFile ("MyImage.png").CGImage);
}

Das resultierende Bild wird dann aufrecht angezeigt:

Das Beispielbild, das aufrecht angezeigt wird

Wichtig

Änderungen am Grafikkontext gelten für alle nachfolgenden Zeichnungsvorgänge. Wenn das CTM transformiert wird, wirkt es sich daher auf jede zusätzliche Zeichnung aus. Wenn Sie z. B. das Dreieck nach der CTM-Transformation gezeichnet haben, erscheint es auf dem Kopf.

Hinzufügen von Text zum Bild

Wie bei Pfaden und Bildern umfasst das Zeichnen von Text mit Core Graphics dasselbe grundlegende Muster zum Festlegen eines Grafikzustands und aufrufen einer Methode zum Zeichnen. Im Fall von Text lautet ShowTextdie Methode zum Anzeigen von Text . Wenn Sie dem Beispiel für die Bildzeichnung hinzugefügt werden, zeichnet der folgende Code Text mithilfe von Core Graphics:

public override void Draw (RectangleF rect)
{
    base.Draw (rect);

    // image drawing code omitted for brevity ...

    // translate the CTM by the font size so it displays on screen
    float fontSize = 35f;
    g.TranslateCTM (0, fontSize);

    // set general-purpose graphics state
    g.SetLineWidth (1.0f);
    g.SetStrokeColor (UIColor.Yellow.CGColor);
    g.SetFillColor (UIColor.Red.CGColor);
    g.SetShadow (new CGSize (5, 5), 0, UIColor.Blue.CGColor);

    // set text specific graphics state
    g.SetTextDrawingMode (CGTextDrawingMode.FillStroke);
    g.SelectFont ("Helvetica", fontSize, CGTextEncoding.MacRoman);

    // show the text
    g.ShowText ("Hello Core Graphics");
}

Wie Sie sehen können, ähnelt das Festlegen des Grafikzustands für die Textzeichnung der Zeichnungsgeometrie. Bei der Textzeichnung werden jedoch auch der Textzeichnungsmodus und die Schriftart angewendet. In diesem Fall wird auch ein Schatten angewendet, obwohl das Anwenden von Schatten für die Pfadzeichnung identisch ist.

Der resultierende Text wird wie unten dargestellt mit dem Bild angezeigt:

Der resultierende Text wird mit dem Bild angezeigt.

Speichergestützte Bilder

Neben dem Zeichnen auf den Grafikkontext einer Ansicht unterstützt Core Graphics das Zeichnen von Hintergrundbildern, auch als Offscreen-Zeichnung bezeichnet. Dazu ist Folgendes erforderlich:

  • Erstellen eines Grafikkontexts, der von einer Speicherbitmap unterstützt wird
  • Festlegen des Zeichnungszustands und Ausstellen von Zeichenbefehlen
  • Abrufen des Bilds aus dem Kontext
  • Entfernen des Kontexts

Im Gegensatz zu der Draw Methode, in der der Kontext von der Ansicht bereitgestellt wird, erstellen Sie in diesem Fall den Kontext auf eine von zwei Arten:

  1. Durch Aufrufen UIGraphics.BeginImageContext (oder BeginImageContextWithOptions)

  2. Durch Erstellen eines neuen CGBitmapContextInstance

CGBitmapContextInstance ist nützlich, wenn Sie direkt mit den Bildbits arbeiten, z. B. für Fälle, in denen Sie einen benutzerdefinierten Bildmanipulationsalgorithmus verwenden. In allen anderen Fällen sollten Sie verwenden BeginImageContext oder BeginImageContextWithOptions.

Sobald Sie einen Bildkontext haben, ist das Hinzufügen von Zeichnungscode genau wie in einer UIView Unterklasse. Das Codebeispiel, das zuvor zum Zeichnen eines Dreiecks verwendet wurde, kann z. B. zum Zeichnen auf ein Bild im Arbeitsspeicher anstelle in einem UIView, wie unten dargestellt, verwendet werden:

UIImage DrawTriangle ()
{
    UIImage triangleImage;

    //push a memory backed bitmap context on the context stack
    UIGraphics.BeginImageContext (new CGSize (200.0f, 200.0f));

    //get graphics context
    using(CGContext g = UIGraphics.GetCurrentContext ()){

        //set up drawing attributes
        g.SetLineWidth(4);
        UIColor.Purple.SetFill ();
        UIColor.Black.SetStroke ();

        //create geometry
        path = new CGPath ();

        path.AddLines(new CGPoint[]{
            new CGPoint(100,200),
            new CGPoint(160,100),
            new CGPoint(220,200)});

        path.CloseSubpath();

        //add geometry to graphics context and draw it
        g.AddPath(path);
        g.DrawPath(CGPathDrawingMode.FillStroke);

        //get a UIImage from the context
        triangleImage = UIGraphics.GetImageFromCurrentImageContext ();
    }

    return triangleImage;
}

Eine häufige Verwendung der Zeichnung auf eine speichergestützte Bitmap besteht darin, ein Bild aus einem beliebigen UIViewObjekt zu erfassen. Der folgende Code rendert z. B. die Ebene einer Ansicht in einem Bitmapkontext und erstellt daraus eine UIImage :

UIGraphics.BeginImageContext (cellView.Frame.Size);

//render the view's layer in the current context
anyView.Layer.RenderInContext (UIGraphics.GetCurrentContext ());

//get a UIImage from the context
UIImage anyViewImage = UIGraphics.GetImageFromCurrentImageContext ();
UIGraphics.EndImageContext ();

Zeichnen von PDF-Dateien

Neben Bildern unterstützt Core Graphics die PDF-Zeichnung. Wie Bilder können Sie eine PDF-Datei im Arbeitsspeicher rendern sowie eine PDF-Datei zum Rendern in einer UIViewDatei lesen.

PDF in einer UIView

Kerngrafiken unterstützen auch das Lesen einer PDF-Datei aus einer Datei und das Rendern in einer Ansicht mithilfe der CGPDFDocument Klasse. Die CGPDFDocument Klasse stellt eine PDF-Datei im Code dar und kann zum Lesen und Zeichnen von Seiten verwendet werden.

Der folgende Code in einer UIView Unterklasse liest z. B. eine PDF-Datei aus einer Datei in eine CGPDFDocument:

public class PDFView : UIView
{
    CGPDFDocument pdfDoc;

    public PDFView ()
    {
        //create a CGPDFDocument from file.pdf included in the main bundle
        pdfDoc = CGPDFDocument.FromFile ("file.pdf");
    }

     public override void Draw (Rectangle rect)
    {
        ...
    }
}

Mit Draw der CGPDFDocument Methode können Sie dann eine Seite CGPDFPage lesen und rendern, indem sie aufgerufen wird DrawPDFPage, wie unten dargestellt:

public override void Draw (CGRect rect)
{
    base.Draw (rect);

    //flip the CTM so the PDF will be drawn upright
    using (CGContext g = UIGraphics.GetCurrentContext ()) {
        g.TranslateCTM (0, Bounds.Height);
        g.ScaleCTM (1, -1);

        // render the first page of the PDF
        using (CGPDFPage pdfPage = pdfDoc.GetPage (1)) {

        //get the affine transform that defines where the PDF is drawn
        CGAffineTransform t = pdfPage.GetDrawingTransform (CGPDFBox.Crop, rect, 0, true);

        //concatenate the pdf transform with the CTM for display in the view
        g.ConcatCTM (t);

        //draw the pdf page
        g.DrawPDFPage (pdfPage);
        }
    }
}

Speichergestützte PDF-Datei

Für eine im Arbeitsspeicher gespeicherte PDF-Datei müssen Sie einen PDF-Kontext erstellen, indem Sie aufrufen BeginPDFContext. Das Zeichnen auf PDF ist für Seiten präzise. Jede Seite wird gestartet, indem sie durch Aufrufen BeginPDFPage und Abschließen des Grafikcodes dazwischen aufgerufen EndPDFContentund abgeschlossen wird. Ebenso wie bei der Bildzeichnung verwendet die zurückgesicherte PDF-Zeichnung einen Ursprung in der unteren linken Ecke, der durch Ändern des CTM wie bei Bildern berücksichtigt werden kann.

Der folgende Code zeigt, wie Text in eine PDF-Datei gezeichnet wird:

//data buffer to hold the PDF
NSMutableData data = new NSMutableData ();

//create a PDF with empty rectangle, which will configure it for 8.5x11 inches
UIGraphics.BeginPDFContext (data, CGRect.Empty, null);

//start a PDF page
UIGraphics.BeginPDFPage ();

using (CGContext g = UIGraphics.GetCurrentContext ()) {
    g.ScaleCTM (1, -1);
    g.TranslateCTM (0, -25);
    g.SelectFont ("Helvetica", 25, CGTextEncoding.MacRoman);
    g.ShowText ("Hello Core Graphics");
    }

//complete a PDF page
UIGraphics.EndPDFContent ();

Der resultierende Text wird auf die PDF-Datei gezeichnet, die dann in einer NSData gespeicherten, hochgeladenen, per E-Mail gesendeten usw. gespeichert werden kann.

Zusammenfassung

In diesem Artikel haben wir uns die Grafikfunktionen angesehen, die über das Core Graphics Framework bereitgestellt werden. Wir haben gesehen, wie Sie mit Core Graphics Geometrie, Bilder und PDF-Dateien im Kontext einer UIView, sowie speichergestützter Grafikkontexte zeichnen können.