Aracılığıyla paylaş


Xamarin.iOS'ta Temel Grafikler

Bu makalede Temel Grafik iOS çerçeveleri ele alınmaktadır. Geometriyi, resimleri ve PDF'leri çizmek için Çekirdek Grafiklerin nasıl kullanılacağını gösterir.

iOS, düşük düzeyli çizim desteği sağlamak için Core Graphics çerçevesini içerir. Bu çerçeveler, UIKit içindeki zengin grafik özelliklerini etkinleştiren çerçevelerdir.

Çekirdek Grafikler, cihazdan bağımsız grafikler çizmeye olanak tanıyan düşük düzeyli bir 2B grafik çerçevesidir. UIKit'teki tüm 2B çizimler dahili olarak Çekirdek Grafikleri kullanır.

Çekirdek Grafikler, aşağıdakiler dahil olmak üzere çeşitli senaryolarda çizimi destekler:

Geometrik Boşluk

Senaryodan bağımsız olarak, Çekirdek Grafiklerle yapılan tüm çizimler geometrik alanda yapılır, yani pikseller yerine soyut noktalarda çalışır. Nelerin çizilmesini istediğinizi geometri ve çizim durumu açısından tanımlarsınız; örneğin renkler, çizgi stilleri vb. ve Çekirdek Grafikler her şeyi piksellere çevirir. Böyle bir durum, bir ressamın tuvali gibi düşünebileceğiniz bir grafik bağlamı eklenir.

Bu yaklaşımın birkaç avantajı vardır:

  • Çizim kodu dinamik hale gelir ve daha sonra çalışma zamanında grafikleri değiştirebilir.
  • Uygulama paketindeki statik görüntülere olan ihtiyacı azaltmak, uygulama boyutunu azaltabilir.
  • Grafikler, cihazlardaki çözüm değişikliklerine karşı daha dayanıklı hale gelir.

UIView Alt Sınıfında Çizim

Her UIView , sistem tarafından çizilmesi gerektiğinde çağrılan bir Draw yönteme sahiptir. Bir görünüme çizim kodu eklemek için alt sınıf UIView ve geçersiz kılın Draw:

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

Çizim hiçbir zaman doğrudan çağrılmamalıdır. Çalıştırma döngüsü işleme sırasında sistem tarafından çağrılır. Görünüm hiyerarşisine bir görünüm eklendikten sonra çalıştırma döngüsünde ilk kez yöntemi çağrılır Draw . Sonraki çağrılar Draw , görünüm veya görünümde çağrılarak SetNeedsDisplaySetNeedsDisplayInRect çizilmesi gerekiyor olarak işaretlendiğinde gerçekleşir.

Grafik Kodu Deseni

Uygulamadaki Draw kod, nelerin çekilmesini istediğini açıklamalıdır. Çizim kodu, çizim durumunu ayarladığı ve çizilme isteğinde bulunmak için bir yöntem çağırdığı bir deseni izler. Bu desen aşağıdaki gibi genelleştirilebilir:

  1. Grafik bağlamı alın.

  2. Çizim özniteliklerini ayarlayın.

  3. Temel öğeler çizerek bazı geometriler oluşturun.

  4. Draw veya Stroke yöntemini çağır.

Temel Çizim Örneği

Örneğin, aşağıdaki kod parçacığını göz önünde bulundurun:

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

Şimdi şu kodu ayıralım:

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

Bu çizgiyle, önce çizim için kullanılacak geçerli grafik bağlamını alır. Çizimle ilgili tüm durumu (kontur ve dolgu renkleri gibi) ve çizilmesi gereken geometriyi içeren bir grafik bağlamını, çizimin üzerinde olduğu tuval olarak düşünebilirsiniz.

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

Grafik bağlamı aldıktan sonra kod, yukarıda gösterilen çizim sırasında kullanılacak bazı öznitelikleri ayarlar. Bu durumda çizgi genişliği, kontur ve dolgu renkleri ayarlanır. Sonraki çizimlerde bu öznitelikler grafik bağlamı durumunda tutulacağı için kullanılır.

Geometri oluşturmak için kod, grafik yolunun çizgilerden ve eğrilerden açıklanması için bir kullanır CGPath. Bu durumda yol, üçgen oluşturmak için bir nokta dizisini bağlayan çizgiler ekler. Aşağıda gösterildiği gibi, Çekirdek Grafikler görünüm çizimi için bir koordinat sistemi kullanır; burada çıkış noktası sol üst taraftadır, pozitif x-doğrudan sağa ve pozitif-y yönü aşağıdır:

var path = new CGPath ();

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

path.CloseSubpath ();

Yol oluşturulduktan sonra grafik bağlamı eklenir, böylece çağrılır AddPath ve DrawPath sırasıyla çizilebilir.

Sonuçta elde edilen görünüm aşağıda gösterilmiştir:

Örnek çıkış üçgeni

Gradyan Dolguları Oluşturma

Daha zengin çizim biçimleri de mevcuttur. Örneğin, Çekirdek Grafikler gradyan dolguları oluşturmaya ve kırpma yolları uygulamaya olanak tanır. Önceki örnekten yolun içine gradyan dolgu çizmek için önce yolun kırpma yolu olarak ayarlanması gerekir:

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

Geçerli yolu kırpma yolu olarak ayarlamak, doğrusal gradyan çizen aşağıdaki kod gibi, yolun geometrisi içindeki sonraki tüm çizimi kısıtlar:

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

Bu değişiklikler aşağıda gösterildiği gibi bir gradyan dolgusu oluşturur:

Gradyan dolgulu örnek

Çizgi Desenlerini Değiştirme

Çizgilerin çizim öznitelikleri Çekirdek Grafiklerle de değiştirilebilir. Bu, aşağıdaki kodda görüldüğü gibi çizgi genişliğini ve vuruş renginin yanı sıra çizgi deseninin kendisini değiştirmeyi içerir:

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

Bu kodu herhangi bir çizim işleminden önce eklemek, aşağıda gösterildiği gibi tireler arasında 4 birim aralıkla 10 birim uzunluğunda kesikli vuruşlarla sonuçlanır:

Herhangi bir çizim işlemi öncesinde bu kodun eklenmesi kesikli vuruşlarla sonuçlanır

Xamarin.iOS'ta Birleşik API kullanılırken dizi türünün bir nfloatolması ve ayrıca math.PI'ye açıkça yayınlanması gerektiğini unutmayın.

Resim ve Metin Çizme

Çekirdek Grafikler, bir görünümün grafik bağlamında yol çizmenin yanı sıra resim ve metin çizmeyi de destekler. Resim çizmek için bir oluşturup CGImage bir çağrıya DrawImage geçirmeniz yeterlidir:

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

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

Ancak bu, aşağıda gösterildiği gibi baş aşağı çizilmiş bir görüntü oluşturur:

Baş aşağı çizilmiş bir resim

Bunun nedeni, resim çiziminin Çekirdek Grafik kaynağı sol altta, görünümün ise sol üst kısmında yer alan başlangıç noktasıdır. Bu nedenle, görüntüyü doğru görüntülemek için kaynağın değiştirilmesi gerekir; bu, Geçerli Dönüştürme Matrisi(CTM) değiştirilerek gerçekleştirilebilir. CTM, noktaların nerede yaşadığını (kullanıcı alanı olarak da bilinir) tanımlar. CTM'yi y yönünde ters çevirmek ve negatif y yönünde sınırların yüksekliğine göre kaydırmak görüntüyü çevirebilir.

Grafik bağlamı, CTM'yi dönüştürmek için yardımcı yöntemlere sahiptir. Bu durumda, ScaleCTM aşağıda gösterildiği gibi çizimi "çevirir" ve TranslateCTM sol üst tarafa kaydırr:

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

Sonuçta elde edilen görüntü daha sonra dik olarak görüntülenir:

Yukarı doğru görüntülenen örnek görüntü

Önemli

Grafik bağlamında yapılan değişiklikler sonraki tüm çizim işlemleri için geçerlidir. Bu nedenle, CTM dönüştürüldüğünde ek çizimleri etkiler. Örneğin, CTM dönüşümünden sonra üçgeni çizerseniz baş aşağı görünür.

Görüntüye Metin Ekleme

Yollarda ve görüntülerde olduğu gibi, Temel Grafikler ile metin çizmek, bazı grafik durumlarını ayarlamak ve çizmek için bir yöntem çağırmak için aynı temel deseni içerir. Metin söz konusu olduğunda, metni görüntüleme yöntemi şeklindedir ShowText. Resim çizim örneğine eklendiğinde, aşağıdaki kod Temel Grafikler'i kullanarak bazı metinler çizer:

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

Gördüğünüz gibi, metin çizimi için grafik durumunu ayarlamak, çizim geometrisine benzer. Ancak metin çizimi için metin çizim modu ve yazı tipi de uygulanır. Bu durumda, bir gölge de uygulanır, ancak gölgeleri uygulamak yol çizimi için aynı şekilde çalışır.

Sonuçta elde edilen metin aşağıda gösterildiği gibi görüntüyle birlikte görüntülenir:

Sonuçta elde edilen metin görüntüyle birlikte görüntülenir

Bellek Destekli Görüntüler

Çekirdek Grafikler, bir görünümün grafik bağlamı için çizim yapmaya ek olarak, bellek destekli görüntülerin de (ekran dışında çizim olarak da bilinir) çizimlerini destekler. Bunu yapmak için şunları yapmanız gerekir:

  • Bellekte bit eşlem tarafından yedeklenen grafik bağlamı oluşturma
  • Çizim durumunu ayarlama ve çizim komutları verme
  • Görüntüyü bağlamdan alma
  • Bağlam kaldırılıyor

Bağlamın Draw görünüm tarafından sağlandığı yöntemin aksine, bu durumda bağlamı iki yoldan biriyle oluşturursunuz:

  1. (veya BeginImageContextWithOptions) öğesini çağırarak UIGraphics.BeginImageContext

  2. Yeni bir oluşturarak CGBitmapContextInstance

CGBitmapContextInstance , özel görüntü işleme algoritması kullandığınız durumlar gibi doğrudan görüntü bitleriyle çalışırken kullanışlıdır. Diğer tüm durumlarda veya BeginImageContextWithOptionskullanmanız BeginImageContext gerekir.

Görüntü bağlamı elde ettikten sonra, çizim kodu eklemek tıpkı bir UIView alt sınıfta olduğu gibi olur. Örneğin, daha önce üçgen çizmek için kullanılan kod örneği, aşağıda gösterildiği gibi bir yerine bellekteki bir UIViewgörüntüye çizmek için kullanılabilir:

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

Bellek destekli bit eşlem çiziminin yaygın kullanımlarından biri, herhangi UIViewbir görüntü yakalamaktır. Örneğin, aşağıdaki kod bir görünümün katmanını bit eşlem bağlamı olarak işler ve bundan bir UIImage oluşturur:

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

PDF'leri çizme

Çekirdek Grafikler, görüntülere ek olarak PDF çizimlerini de destekler. Görüntülerde olduğu gibi, PDF'yi bellekte işleyebilir ve içinde işlemek UIViewiçin PDF okuyabilirsiniz.

UIView'da PDF

Core Graphics, bir dosyadan PDF okumayı ve sınıfını kullanarak bir görünümde işlemeyi CGPDFDocument de destekler. CGPDFDocument sınıfı koddaki bir PDF'yi temsil eder ve sayfaları okumak ve çizmek için kullanılabilir.

Örneğin, bir UIView alt sınıftaki aşağıdaki kod bir dosyadaki CGPDFDocumentPDF'yi dosyasına okur:

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)
    {
        ...
    }
}

Yöntemi Draw daha sonra aşağıda gösterildiği gibi içinde bir sayfayı CGPDFPage okumak ve çağırarak DrawPDFPageişlemek için kullanabilirCGPDFDocument:

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

Bellek Destekli PDF

Bellek içi PDF için çağırarak BeginPDFContextbir PDF bağlamı oluşturmanız gerekir. PDF'ye çizim sayfaları ayrıntılıdır. Her sayfa çağrılarak BeginPDFPage başlatılır ve çağrılarak EndPDFContenttamamlanır ve arada grafik kodu bulunur. Ayrıca, resim çiziminde olduğu gibi, bellek destekli PDF çizimi de sol altta bir çıkış noktası kullanır ve bu kaynak, tıpkı görüntülerde olduğu gibi CTM'nin değiştirilmesiyle hesaba katılabilir.

Aşağıdaki kod, PDF'ye metin çizmeyi gösterir:

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

Sonuçta elde edilen metin PDF'ye çizilir ve daha sonra NSData kaydedilebilen, karşıya yüklenebilen, e-postayla gönderilebilen vb.

Özet

Bu makalede Çekirdek Grafik çerçevesi aracılığıyla sağlanan grafik özelliklerine göz attık. Çekirdek Grafikleri kullanarak hem bir bağlamında UIView, geometri, görüntüler ve PDF'ler hem de bellek destekli grafik bağlamları çizmeyi gördük.