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:
- aracılığıyla
UIView
ekrana çizim. - Görüntüleri belleğe veya ekrana çizme.
- PDF oluşturma ve PDF'ye çizme.
- Mevcut PDF'yi okuma ve çizme.
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 SetNeedsDisplay
SetNeedsDisplayInRect
ç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:
Grafik bağlamı alın.
Çizim özniteliklerini ayarlayın.
Temel öğeler çizerek bazı geometriler oluşturun.
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:
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:
Ç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:
Xamarin.iOS'ta Birleşik API kullanılırken dizi türünün bir nfloat
olması 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:
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:
Ö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:
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:
(veya
BeginImageContextWithOptions
) öğesini çağırarakUIGraphics.BeginImageContext
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 BeginImageContextWithOptions
kullanmanı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 UIView
gö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 UIView
bir 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 UIView
iç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 CGPDFDocument
PDF'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 DrawPDFPage
iş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 BeginPDFContext
bir 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 EndPDFContent
tamamlanı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.