Základní grafika v Xamarin. iOS

Tento článek popisuje základní grafické architektury pro iOS. Ukazuje, jak používat základní grafiku k vykreslování geometrie, obrázků a souborů PDF.

iOS obsahuje základní architekturu grafiky , která poskytuje podporu vykreslování na nižší úrovni. Tyto architektury jsou ty, které umožňují bohatě grafické možnosti v rámci UIKit.

Základní grafika je architektura 2D grafiky nižší úrovně, která umožňuje kreslení nezávislé grafiky zařízení. Všechny 2D kresby v UIKit používají interně základní grafiku.

Základní grafika podporuje vykreslování v několika scénářích, včetně:

Geometrický prostor

Bez ohledu na to, jak se jedná o scénář, se všechny kresby provedené s základní grafikou provádí v geometrickém prostoru, což znamená, že funguje v abstraktních bodech místo pixelů. Popíšete, co se má vykreslovat z hlediska geometrie a stavu kreslení, jako jsou barvy, styly čar atd., a základní grafika zpracovává všechna data na pixely. Tento stav se přidá do grafického kontextu, který si můžete představit jako plátno pro malíře.

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

  • Vykreslování kódu se změní na dynamický a může následně upravovat grafiky za běhu.
  • Omezení nutnosti statických imagí v sadě prostředků aplikace může snížit velikost aplikace.
  • Grafika se v různých zařízeních stane pružnější změnami rozlišení.

Kreslení v podtřídě UIView

Každý UIViewDraw metodu, která je volána systémem, když je nutné ji vykreslit. Chcete-li přidat kód pro vykreslení do zobrazení, podtřídy UIView a přepsání Draw :

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

Metoda draw by nikdy neměla být volána přímo. Je volána systémem během zpracování smyčky spuštění. Při prvním spuštění smyčky po přidání zobrazení do hierarchie zobrazení je jeho Draw metoda volána. Následná volání, která se mají Draw provést, když je zobrazení označeno jako nutné vykreslit buď SetNeedsDisplay nebo SetNeedsDisplayInRect v zobrazení.

Vzor pro kód grafiky

Kód v Draw implementaci by měl popsat, co chce vykreslit. Kód pro kreslení sleduje vzor, ve kterém nastaví určitý stav kreslení a volá metodu, která vyžádá vykreslit. Tento model se dá zobecnit takto:

  1. Získá kontext grafiky.

  2. Nastavení atributů kreslení

  3. Vytvořte některé geometrie z vykreslování primitiv.

  4. Zavolejte metodu Draw nebo Stroke.

Základní příklad vykreslování

Zvažte 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 tento kód rozdělit:

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

S tímto řádkem nejprve získá aktuální kontext grafiky, který bude použit pro kreslení. Můžete si představit kontext grafiky jako plátno, na kterém se kreslení děje, obsahující všechny stavy vykreslování, jako jsou barvy tahů a výplní, a také geometrii, která se má vykreslit.

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

Po získání kontextu grafiky kód nastaví některé atributy, které se mají použít při vykreslování, zobrazené výše. V tomto případě jsou nastaveny barvy čáry, tahu a výplně. Všechny následné kresby pak tyto atributy použijí, protože jsou zachovány ve stavu grafického kontextu.

Chcete-li vytvořit geometrii, používá kód CGPath , který umožňuje popsat cestu grafiky z čar a křivek. V takovém případě cesta přidá čáry spojující pole bodů a vytvoří tak trojúhelník. Jak je zobrazeno níže základní grafika, používá systém souřadnic pro vykreslování zobrazení, kde počátek je v levém horním rohu, s kladným x-rovnou vpravo a kladným směrem y 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 je tato cesta přidána do kontextu grafiky, aby ji voláním AddPath a DrawPath v uvedeném pořadí mohli vykreslit.

Výsledné zobrazení je zobrazeno níže:

Vzorový výstupní trojúhelník

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

K dispozici jsou také bohatší formy vykreslování. Základní grafika například umožňuje vytváření přechodových výplní a aplikování ořezových cest. Chcete-li nakreslit přechodovou výplň uvnitř cesty z předchozího příkladu, je třeba nejprve nastavit cestu k ořezové cestě:

// 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 ořezové cesty omezuje všechny následné vykreslování v geometrii cesty, jako je 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í

Změna vzorů čáry

Atributy kreslení čar lze také upravovat pomocí základních grafických objektů. To zahrnuje změnu tloušťky čáry a tahu a také vzor čáry samotného, 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ýsledkem operací kreslení je přerušované tahy o 10 jednotkách dlouhé a 4 jednotky mezery mezi pomlčkami, jak je znázorněno níže:

Přidání tohoto kódu před výsledkem operací kreslení na přerušované tahy

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

Kreslení obrázků a textu

Kromě vykreslování cest v grafickém kontextu zobrazení základní grafika také podporuje vykreslování obrázků a textu. Chcete-li nakreslit obrázek, jednoduše vytvořte CGImage a předejte ho 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);
    }
}

Tím se ale vytvoří obrázek vykreslený v dolní části, jak je znázorněno níže:

Obrázek nakreslený po rozložení

Důvodem pro vykreslování obrázku je základní zdroj grafiky, zatímco zobrazení má počátek v levém horním rohu. Proto pokud chcete obrázek správně zobrazit, je nutné upravit počátek, což lze provést úpravou aktuální matice transformace(CTM). CTM definuje, kde jsou body v provozu, označované také jako prostor uživatele. Invertování CTM ve směru y a jeho posunutí podle výšky hranice v nezáporném směru y může překlopit obrázek.

Kontext grafiky obsahuje pomocné metody pro transformaci CTM. V takovém případě ScaleCTM "Překlopí" výkres a TranslateCTM posune ho vlevo 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í vzhůru:

Vzorový obrázek zobrazený vzhůru

Důležité

Změny v kontextu grafiky se vztahují na všechny následující operace kreslení. Proto při transformaci CTM bude mít vliv na jakékoli další výkresy. Pokud jste například nakreslili trojúhelník po transformaci CTM, zobrazí se v něm.

Přidání textu do obrázku

Stejně jako u cest a obrázků zahrnuje vykreslování textu s základní grafikou stejný základní vzor pro nastavení některých stavů grafiky a volání metody pro vykreslení. V případě textu je metoda zobrazení textu ShowText . Po přidání do příkladu vykreslování obrázku následující kód nakreslí 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í stavu grafiky pro kreslení textu se podobá geometrii vykreslování. Pro kreslení textu se ale aplikuje i režim kreslení textu a písmo. V tomto případě se používá i stín, i když aplikování stínů funguje stejně jako vykreslování cesty.

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

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

Memory-Backed image

Kromě vykreslování do grafického kontextu zobrazení podporuje základní grafika vykreslování imagí v paměti, které se také označují jako při vykreslování mimo obrazovku. K tomu je potřeba:

  • Vytvoření grafického kontextu, který je zálohovaný v paměti rastrového obrázku
  • Nastavení stavů kreslení a vystavování příkazů kreslení
  • Získávání obrázku z kontextu
  • Odebrání kontextu

Na rozdíl od Draw metody, kde je kontext dodán 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é CGBitmapContextInstance

CGBitmapContextInstance je užitečné, když pracujete přímo s bitovými kopiemi imagí, jako jsou například případy, kdy používáte vlastní algoritmus manipulace s obrázkem. 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 pro kreslení je stejně jako v UIView podtřídě. Například příklad kódu, který jste použili dříve k nakreslení trojúhelníku, lze použít k vykreslení na obrázek v paměti místo v 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 vykreslování do rastrového obrázku, který je zálohovaný do paměti, je zachycení obrázku z libovolného UIView . Například následující kód vykreslí vrstvu zobrazení do kontextu rastrového obrázku 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 základní grafika vykreslování PDF. Podobně jako obrázky můžete vykreslit PDF v paměti a také si přečíst PDF pro vykreslování v UIView .

PDF v UIView

Základní grafika také podporuje čtení PDF ze souboru a jeho vykreslování v zobrazení pomocí CGPDFDocument třídy. CGPDFDocumentTřída 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ě přeč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)
    {
        ...
    }
}

DrawMetoda pak může použít CGPDFDocument k načtení stránky do CGPDFPage a jejímu vygenerování 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);
        }
    }
}

Memory-Backed PDF

V případě PDF v paměti je třeba vytvořit kontext PDF voláním BeginPDFContext . Vykreslování do PDF je podrobné 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 v. Stejně jako u vykreslování obrázků používá vykreslování PDF na paměť zálohovanou v levém dolním rohu počátek, který je možné přidružit úpravou CTM stejně jako u obrázků.

Následující kód ukazuje, jak nakreslit text do souboru 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 vykreslí do PDF, který je pak obsažený v souboru NSData , který se dá uložit, nahrát, poslat e-mailem atd.

Souhrn

V tomto článku jsme se podívali na grafické možnosti poskytované prostřednictvím základní grafické architektury. Zjistili jsme, jak používat základní grafiku k vykreslování geometrie, obrázků a souborů PDF v kontextu a také s kontexty objektů, které jsou v UIView, paměti.