如何在Xamarin iOS中绘制文本?
我想在自定义View
的Draw
方法的给定点(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
时,都会执行ScaleCTM
和TranslateCTM
- 你不考虑当你
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(); }
请注意, FormattedText
和Point
是我制作的用于封装要绘制的文本的定制类以及绘制它的点。 他们的属性就像你看到的那样简单:)
重要: @ SushiHangover的版本的修改是在那里
避免副作用 (如果我在调用DrawText方法后绘制了一个Rectangle,则坐标被搞乱了)。 它也有一个X坐标的问题:
context.TranslateCTM(-x, -(y + textHeight))
应该
context.TranslateCTM(x, -(y + textHeight))
谢谢,@SushiHangover。 我用你真正有价值的帮助做到了!