Reputation: 2729
I have found the answer in following link : Draw text along circular path in Swift for iOS
It seems fine for me. Now , I'm just trying to convert the same code in xamarin ios, but haven't succeeded yet.
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();
}
}
Some comments shows original lines, what it maybe not translated correctly... It shows just black view for me
Upvotes: 1
Views: 576
Reputation: 2258
There're several mistakes when you convert the swift code to C#, I have corrected them in the below code snippet. The reason why it's black is that you didn't set the color for the text. You can use NSString.DrawString
instead to achieve that.
It should like this:
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();
}
It works fine like this:
Upvotes: 3