Sdílet prostřednictvím


Základní grafika v Xamarin.iOS

Tento článek popisuje architektury základní grafiky pro iOS. Ukazuje, jak pomocí základní grafiky kreslit geometrii, obrázky a soubory PDF.

iOS obsahuje architekturu Core Graphics , která poskytuje podporu kreslení na nízké úrovni. Tyto architektury umožňují bohaté grafické funkce v uiKitu.

Základní grafika je 2D grafická architektura nízké úrovně, která umožňuje kreslit nezávislou grafiku zařízení. Všechny 2D výkresy v UIKitu interně používají základní grafiku.

Základní grafika podporuje kreslení v řadě scénářů, mezi které patří:

Geometrický prostor

Bez ohledu na scénář se všechny kresby provedené pomocí grafické karty Core provádí v geometrickém prostoru, což znamená, že funguje v abstraktních bodech místo pixelů. Popíšete, co chcete nakreslit z hlediska geometrie a stavu kreslení, jako jsou barvy, styly čar atd. a základní grafika překládá všechno na pixely. Takový stav se přidá do grafického kontextu, který si můžete představit jako plátno malíře.

Tento přístup má několik výhod:

  • Kód výkresu se stane dynamickým a následně může upravovat grafiku za běhu.
  • Snížení potřeby statických imagí v sadě aplikací může snížit velikost aplikace.
  • Grafika je odolnější vůči změnám rozlišení na různých zařízeních.

Kreslení v podtřídě UIView

Každá UIView má metodu Draw , která je volána systémem, když je třeba nakreslit. Přidání kódu výkresu do zobrazení, podtřídy UIView a přepsání Draw:

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

Kreslení by nikdy nemělo být volána přímo. Systém ho volá během zpracování smyčky spuštění. Při prvním procházení smyčky spuštění po přidání zobrazení do hierarchie zobrazení je volána jeho Draw metoda. Následná volání, ke kterým dojde Draw , když je zobrazení označeno jako nutné kreslit voláním buď SetNeedsDisplay nebo SetNeedsDisplayInRect v zobrazení.

Vzor grafického kódu

Kód v implementaci Draw by měl popsat, co chce nakreslit. Kód výkresu se řídí vzorem, ve kterém nastavuje určitý stav výkresu a volá metodu, která požaduje, aby byla vykreslena. Tento model lze zobecnit následujícím způsobem:

  1. Získejte kontext grafiky.

  2. Nastavte atributy kreslení.

  3. Vytvořte určitou geometrii z primitiv výkresu.

  4. Volání metody Draw nebo Stroke

Příklad základního výkresu

Představte si například následující fragment kódu:

//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);
}

Pojďme si tento kód rozdělit:

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

S touto čárou nejprve získá aktuální kontext grafiky, který se použije pro kreslení. Kontext grafiky si můžete představit jako kreslicí plátno, které se děje, včetně veškerého stavu výkresu, jako jsou barvy tahu a výplně, a také geometrii, na které se má kreslit.

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

Po získání grafického kontextu kód nastaví některé atributy, které se použijí při kreslení, viz výše. V tomto případě se nastaví šířka čáry, barva tahu a výplně. Všechny následné výkresy pak budou tyto atributy používat, protože jsou zachovány ve stavu grafického kontextu.

Chcete-li vytvořit geometrii, kód používá CGPath, což umožňuje, aby grafická cesta byla popsána z čar a křivek. V tomto případě cesta přidá čáry spojující matici bodů, které tvoří trojúhelník. Jak je znázorněno pod základní grafikou, používá souřadnicový systém pro výkres zobrazení, kde je původ v levém horním rohu, s kladným x přímým směrem doprava a kladným směrem dolů:

var path = new CGPath ();

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

path.CloseSubpath ();

Po vytvoření cesty se přidá do grafického kontextu, aby volání AddPath a DrawPath v uvedeném pořadí ho mohlo nakreslit.

Výsledné zobrazení je znázorněno níže:

Ukázkový výstupní trojúhelník

Vytváření přechodových výplní

K dispozici jsou také bohatší formy výkresu. Základní grafika například umožňuje vytvářet přechodové výplně a používat cesty výřezu. Pokud chcete nakreslit přechodovou výplň v cestě z předchozího příkladu, musíte nejprve nastavit cestu výřezu:

// 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 ();

Nastavení aktuální cesty jako cesty výřezu omezuje všechny následné výkresy v rámci geometrie dráhy, například následující kód, který nakreslí lineární přechod:

// 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);
    }

Tyto změny vytvoří přechodovou výplň, jak je znázorněno níže:

Příklad s přechodovou výplní

Úprava vzorů čar

Atributy výkresu čar lze také upravit pomocí základní grafiky. To zahrnuje změnu šířky čáry a barvy tahu i samotného vzoru čáry, jak je vidět v následujícím kódu:

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

Přidání tohoto kódu před všechny operace kreslení vede k přerušovaným tahům o délce 10 jednotek s 4 jednotkami mezer mezi pomlčkami, jak je znázorněno níže:

Přidání tohoto kódu před všechny operace kreslení způsobí přerušované tahy.

Všimněte si, že při použití sjednoceného rozhraní API v Xamarin.iOS musí být typ pole a nfloattaké musí být explicitně přetypován na Math.PI.

Kreslení obrázků a textu

Kromě kreslení cest v grafickém kontextu zobrazení podporuje základní grafika také obrázky a text. Pokud chcete nakreslit obrázek, jednoduše ho CGImage vytvořte a předejte mu DrawImage volání:

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

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

Výsledkem je ale obrázek nakreslený vzhůru nohama, jak je znázorněno níže:

Obrázek nakreslený vzhůru nohama

Důvodem je původ základní grafiky pro kreslení obrázků v levém dolním rohu, zatímco zobrazení má jeho původ v levém horním rohu. Aby bylo možné obrázek správně zobrazit, musí být původ změněn, což lze provést úpravou aktuální matice transformace (CTM). CTM definuje, kde jsou body živé, označované také jako uživatelské místo. Převrácení CTM ve směru y a jeho posunutí o výšku hranic v záporném směru y může překlopit obrázek.

Kontext grafiky má pomocné metody transformace CTM. V tomto případě ScaleCTM výkres překlopíte a TranslateCTM posunete ho doleva nahoře, jak je znázorněno níže:

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);
}

Výsledný obrázek se pak zobrazí přímo:

Ukázkový obrázek zobrazený přímo na obrázku

Důležité

Změny v kontextu grafiky platí pro všechny následné operace kreslení. Proto při transformaci CTM ovlivní jakýkoli další výkres. Pokud jste například nakreslili trojúhelník po transformaci CTM, zobrazí se vzhůru nohama.

Přidání textu do obrázku

Stejně jako u cest a obrázků zahrnuje kreslení textu s grafikou Core Graphics stejný základní vzor nastavení stavu grafiky a volání metody pro kreslení. V případě textu je metoda zobrazení textu ShowText. Při přidání do příkladu výkresu obrázku nakreslí následující kód nějaký text pomocí základní grafiky:

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");
}

Jak vidíte, nastavení grafického stavu pro kreslení textu je podobné geometrii kreslení. U kreslení textu se ale použije i režim kreslení textu a písmo. V tomto případě se použije také stín, i když použití stínů funguje stejně pro výkres cesty.

Výsledný text se zobrazí s obrázkem, jak je znázorněno níže:

Výsledný text se zobrazí s obrázkem.

Image založené na paměti

Kromě kreslení do grafického kontextu zobrazení podporuje základní grafika obrázky s podporou kreslení paměti, označované také jako kreslení mimo obrazovku. To vyžaduje:

  • Vytvoření grafického kontextu, který je podporován rastrovým obrázkem v paměti
  • Nastavení stavu výkresu a vydávání příkazů výkresu
  • Získání obrázku z kontextu
  • Odebrání kontextu

Draw Na rozdíl od metody, kde je kontext zadaný zobrazením, v tomto případě vytvoříte kontext jedním ze dvou způsobů:

  1. Voláním UIGraphics.BeginImageContext (nebo BeginImageContextWithOptions)

  2. Vytvořením nového CGBitmapContextInstance

CGBitmapContextInstance je užitečné, když pracujete přímo s bity obrázků, například v případech, kdy používáte vlastní algoritmus manipulace s obrázky. Ve všech ostatních případech byste měli použít BeginImageContext nebo BeginImageContextWithOptions.

Jakmile máte kontext obrázku, přidání kódu výkresu je stejně jako v UIView podtřídě. Například příklad kódu použitý dříve k vykreslení trojúhelníku lze použít k vykreslení obrázku v paměti místo v paměti UIView, jak je znázorněno níže:

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;
}

Běžným použitím výkresu na rastrový obrázek založený na paměti je zachycení obrázku z libovolného UIViewobrázku . Například následující kód vykreslí vrstvu zobrazení do rastrového kontextu a vytvoří UIImage z něj:

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 ();

Kreslení souborů PDF

Kromě obrázků podporuje Core Graphics také kreslení PDF. Stejně jako obrázky můžete vykreslit PDF v paměti a také číst PDF pro vykreslování v souboru UIView.

PDF v uživatelském rozhraníView

Základní grafika podporuje také čtení PDF ze souboru a jeho vykreslení v zobrazení pomocí CGPDFDocument třídy. Třída CGPDFDocument představuje PDF v kódu a lze ji použít ke čtení a kreslení stránek.

Například následující kód v UIView podtřídě načte SOUBOR PDF ze souboru do 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)
    {
        ...
    }
}

Metoda Draw pak může použít CGPDFDocument ke čtení a vykreslení stránky CGPDFPage voláním DrawPDFPage, jak je znázorněno níže:

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);
        }
    }
}

Formát PDF s podporou paměti

V případě PDF v paměti musíte vytvořit kontext PDF voláním BeginPDFContext. Kreslení do PDF je odstupňované na stránky. Každá stránka je spuštěna voláním BeginPDFPage a dokončením voláním EndPDFContent, s grafickým kódem mezi. Stejně jako u výkresu obrázku používá výkres PDF založený na paměti původ v levém dolním rohu, který lze zohlednit úpravou CTM stejně jako s obrázky.

Následující kód ukazuje, jak nakreslit text do PDF:

//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 ();

Výsledný text se nakreslí do SOUBORU PDF, který je pak obsažen v NSData souboru, který lze uložit, nahrát, odeslat e-mailem atd.

Shrnutí

V tomto článku jsme se podívali na možnosti grafiky poskytované prostřednictvím architektury Core Graphics . Viděli jsme, jak pomocí základní grafiky kreslit geometrii, obrázky a soubory PDF v kontextu UIView, i kontexty grafiky založené na paměti.