如何在Xamarin iOS中绘制文本?

我想在自定义ViewDraw方法的给定点(x,y)处绘制文本。

我从Xamarin站点跟踪了这个示例 。

这是我创build的视图:

 public class MyView : UIView { public override void Draw(CGRect rect) { using (var context = UIGraphics.GetCurrentContext()) { DrawText(context, "hello", 20, new CGPoint(0, 0)); DrawText(context, "how are you", 20, new CGPoint(0, 40)); } } private void DrawText(CGContext context, string text, int textHeight, CGPoint point) { var x = point.X; var y = point.Y + textHeight; context.TranslateCTM(x, y); context.ScaleCTM(1, -1); context.SetFillColor(UIColor.Red.CGColor); var attributedString = new NSAttributedString(text, new CTStringAttributes { ForegroundColorFromContext = true, Font = new CTFont("Arial", 16) }); using (var textLine = new CTLine(attributedString)) { textLine.Draw(context); } } } 

问题是DrawText方法只能正常工作一次 。 第一次调用它时,文本被绘制,但是它不能在连续的调用中工作 (它什么都不画,或者它所画的是不可见的)。

我究竟做错了什么?

十分感谢!

所以你的代码有两个基本的东西是错误的。

  • 每次调用DrawText时,都会执行ScaleCTMTranslateCTM
  • 你不考虑当你CTLine.Draw ,“光标”移动到该文本的末尾。

所以,调用ScaleCTM来翻转整个文本,这样文本就会被绘制到左边,然后调用DrawText并将其转换为您想要绘制文本的位置,然后在下一次您处于相同位置时再回到您开始的位置。

示例绘制覆盖:

 public override void Draw(CGRect rect) { var context = UIGraphics.GetCurrentContext(); context.ScaleCTM(1, -1); // you flipped the context, now you must use negative Y values to draw "into" the view var textHeight = new CTFont("Arial", 16).CapHeightMetric; // lets use the actaul height of the font captials. DrawText(context, "Hello", textHeight, 0, 0); DrawText(context, "How are you?", textHeight, 0, 20); DrawText(context, "Sincerely,", textHeight, 0, 40); DrawText(context, "StackOverflow,", textHeight, 0, 60); } void DrawText(CGContext context, string text, nfloat textHeight, nfloat x, nfloat y) { context.TranslateCTM(-x, -(y + textHeight)); context.SetFillColor(UIColor.Red.CGColor); var attributedString = new NSAttributedString(text, new CTStringAttributes { ForegroundColorFromContext = true, Font = new CTFont("Arial", 16) }); CGRect sizeOfText; using (var textLine = new CTLine(attributedString)) { textLine.Draw(context); sizeOfText = textLine.GetBounds(CTLineBoundsOptions.UseOpticalBounds); } // Reset the origin back to where is was context.TranslateCTM(x - sizeOfText.Width, y + sizeOfText.Height); } 

结果是:

在这里输入图像说明

使用NSMutableParagraphStyle和NSString.DrawString

 var context = UIGraphics.GetCurrentContext(); CGRect textRect = new CGRect(0.0f, 0.0f, 200.0f, 100.0f); { var textContent = "Hello\nHow are you?\nSincerely,\nStackOverflow"; UIColor.Red.SetFill(); var textStyle = new NSMutableParagraphStyle (); textStyle.Alignment = UITextAlignment.Left; var textFontAttributes = new UIStringAttributes () {Font = UIFont.FromName("ArialMT", 16.0f), ForegroundColor = UIColor.Red, ParagraphStyle = textStyle}; var textTextHeight = new NSString(textContent).GetBoundingRect(new CGSize(textRect.Width, nfloat.MaxValue), NSStringDrawingOptions.UsesLineFragmentOrigin, textFontAttributes, null).Height; context.SaveState(); context.ClipToRect(textRect); new NSString(textContent).DrawString(new CGRect(textRect.GetMinX(), textRect.GetMinY() + (textRect.Height - textTextHeight) / 2.0f, textRect.Width, textTextHeight), UIFont.FromName("ArialMT", 16.0f), UILineBreakMode.WordWrap, UITextAlignment.Left); context.RestoreState(); } 

我拿了@ SushiHangover的代码,并修改它为我工作,因为他们的版本(第一次在他的职位)有一些问题(阅读下面的通知):

 public void DrawText(FormattedText formattedText, Point point) { context.SaveState(); context.ScaleCTM(1, -1); context.SetFillColor(formattedText.Brush.Color.ToiOS()); var sizeOfText = formattedText.DesiredSize; var ctFont = new CTFont(formattedText.FontName, formattedText.FontSize); var attributedString = new NSAttributedString(formattedText.Text, new CTStringAttributes { ForegroundColor = formattedText.Brush.Color.ToiOS(), Font = ctFont }); context.TextPosition = new CGPoint(point.X, -(point.Y + sizeOfText.Height - ctFont.DescentMetric)); using (var textLine = new CTLine(attributedString)) { textLine.Draw(context); } context.RestoreState(); } 

请注意, FormattedTextPoint是我制作的用于封装要绘制的文本的定制类以及绘制它的点。 他们的属性就像你看到的那样简单:)

重要: @ SushiHangover的版本的修改是在那里

避免副作用 (如果我在调用DrawText方法后绘制了一个Rectangle,则坐标被搞乱了)。 它也有一个X坐标的问题:

 context.TranslateCTM(-x, -(y + textHeight)) 

应该

 context.TranslateCTM(x, -(y + textHeight)) 

谢谢,@SushiHangover。 我用你真正有价值的帮助做到了!