在 xamarin 中沿圆形路径绘制文本 ios

Draw text along circular path in xamarin ios

我在下面 link 中找到了答案:

我觉得还不错。现在,我只是想在 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();
    }
}

一些评论显示原始行,可能翻译不正确...对我来说它只显示黑色视图

将 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();
        }

像这样工作正常: