我在以下链接中找到了答案: Draw text along circular path in Swift for iOS
对我来说似乎没问题。现在,我只想尝试在xamarin ios中转换相同的代码,但还没有成功。
public class CircularText : UIView
{
public override void Draw(CoreGraphics.CGRect rect)
{
base.Draw(rect);
this.BackgroundColor = UIColor.Clear;
var context = UIGraphics.GetCurrentContext();
var size = this.Bounds.Size;
context.TranslateCTM(size.Width / 2, size.Height / 2);
context.ScaleCTM(1, -1);
CentreArcPerpendicular(str: "Hello round world", context: context, radius: 100, angle: 0, color: UIColor.Red, font: UIFont.SystemFontOfSize(16), clockwise: true);
CentreArcPerpendicular(str: "Anticlockwise", context: context, radius: 100, angle: (System.nfloat)(-Math.PI / 2), color: UIColor.Red, font: UIFont.SystemFontOfSize(16), clockwise: false);
centre(str: "Hello flat world", context: context, radius: 0, angle: 0, color: UIColor.Yellow, font: UIFont.SystemFontOfSize(16), slantAngle: (System.nfloat)(Math.PI / 4));
}
void CentreArcPerpendicular(String str, CGContext context, nfloat radius, nfloat angle, UIColor color, UIFont font, bool clockwise)
{
var l = str.Length;
char[] characters = str.ToCharArray();
nfloat[] arcs = new nfloat[l];
nfloat totalArc = 0;
for (int i = 0; i < l; i++)
{
arcs[i] = chordToArc(1, radius);
}
var direction = clockwise ? -1 : 1;
var slantCorrection = clockwise ? -Math.PI / 2 : Math.PI;
var thetaI = angle - direction * totalArc / 2;
for (int i = 0; i < l; i++)
{
thetaI += direction * arcs[i] / 2;
centre(str: characters[i].ToString(), context: context, radius: radius, angle: angle, color: color, font: font, slantAngle: (System.nfloat)(angle + slantCorrection));
thetaI += direction * arcs[i] / 2;
}
}
nfloat chordToArc(nfloat chord, nfloat radius)
{
return (nfloat)(2 * Math.Asin(chord / (2 * radius)));
}
void centre(String str, CGContext context, nfloat radius, nfloat angle, UIColor color, UIFont font, nfloat slantAngle)
{
//var attributes = [NSForegroundColorAttributeName: color,
//NSFontAttributeName: font]
context.SaveState();
// // Undo the inversion of the Y-axis (or the text goes backwards!)
context.ScaleCTM(1, -1);
// Move the origin to the centre of the text (negating the y-axis manually)
context.TranslateCTM((System.nfloat)(radius * Math.Cos(angle)), (System.nfloat)(-(radius * Math.Sin(angle))));
// Rotate the coordinate system
context.RotateCTM(-slantAngle);
// Calculate the width of the text
var offset = str.Length;
// Move the origin by half the size of the text
//CGContextTranslateCTM(context, -offset.width / 2, -offset.height / 2)
context.TranslateCTM(-20 / 2, 20 / 2); // Move the origin to the centre of the text (negating the y-axis manually)
// Draw the text
str.DrawString(new CGPoint(x: 0, y: 0), font);
// Restore the context
context.RestoreState();
}
}
有些评论显示原始线条,它可能无法正确翻译...它只显示黑色视图
答案 0 :(得分:2)
将swift代码转换为C#时出现了几个错误,我已经在下面的代码片段中更正了它们。它是黑色的原因是你没有为文本设置颜色。您可以使用NSString.DrawString
来实现这一目标。
它应该是这样的:
public override void Draw(CoreGraphics.CGRect rect)
{
base.Draw(rect);
this.BackgroundColor = UIColor.Clear;
var context = UIGraphics.GetCurrentContext();
var size = this.Bounds.Size;
context.TranslateCTM(size.Width / 2, size.Height / 2);
context.ScaleCTM(1, -1);
CentreArcPerpendicular(str: "Hello round world", context: context, radius: 100, angle: 0, color: UIColor.Red, font: UIFont.SystemFontOfSize(16), clockwise: true);
CentreArcPerpendicular(str: "Anticlockwise", context: context, radius: 100, angle: (System.nfloat)(-Math.PI / 2), color: UIColor.Red, font: UIFont.SystemFontOfSize(16), clockwise: false);
centre(str: "Hello flat world", context: context, radius: 0, angle: 0, color: UIColor.Yellow, font: UIFont.SystemFontOfSize(16), slantAngle: (System.nfloat)(Math.PI / 4));
}
void CentreArcPerpendicular(String str, CGContext context, nfloat radius, nfloat angle, UIColor color, UIFont font, bool clockwise)
{
var l = str.Length;
char[] characters = str.ToCharArray();
nfloat[] arcs = new nfloat[l];
nfloat totalArc = 0;
for (int i = 0; i < l; i++)
{
//Get the Size of the Char(Transfer to string to get the width)
NSString s = new NSString(Char.ToString(characters[i]));
CGSize size = s.GetSizeUsingAttributes(new UIStringAttributes(new NSDictionary(UIStringAttributeKey.Font, font)));
arcs[i] = chordToArc(size.Width, radius);
totalArc += arcs[i];
}
var direction = clockwise ? -1 : 1;
var slantCorrection = clockwise ? -Math.PI / 2 : Math.PI / 2 ; //You lose the /2
var thetaI = angle - direction * totalArc / 2;
for (int i = 0; i < l; i++)
{
thetaI += direction * arcs[i] / 2;
centre(str: characters[i].ToString(), context: context, radius: radius, angle: thetaI, color: color, font: font, slantAngle: (System.nfloat)(thetaI + slantCorrection)); // USe thetaI not angle !
thetaI += direction * arcs[i] / 2;
}
}
nfloat chordToArc(nfloat chord, nfloat radius)
{
return (nfloat)(2 * Math.Asin(chord / (2 * radius)));
}
void centre(String str, CGContext context, nfloat radius, nfloat angle, UIColor color, UIFont font, nfloat slantAngle)
{
// Set the text attributes
UIStringAttributes attribute = new UIStringAttributes()
{
Font = font,
ForegroundColor = color
};
NSString s = new NSString(str);
// Save the context
context.SaveState();
// Undo the inversion of the Y-axis (or the text goes backwards!)
context.ScaleCTM(1, -1);
// Move the origin to the centre of the text (negating the y-axis manually)
context.TranslateCTM((System.nfloat)(radius * Math.Cos(angle)), (System.nfloat)(-(radius * Math.Sin(angle))));
// Rotate the coordinate system
context.RotateCTM(-slantAngle);
// Calculate the width of the text
var offset = s.GetSizeUsingAttributes(attribute);
// Move the origin by half the size of the text
context.TranslateCTM(-offset.Width / 2, -offset.Height / 2); // Move the origin to the centre of the text (negating the y-axis manually)
// Draw the text
s.DrawString(new CGPoint(0, 0), attribute);//use NSString.DrawString, then it can add attribute parameter.
// Restore the context
context.RestoreState();
}
它的工作原理如下: