XNA has Spritefont class, which has a MeasureString method, which can return the Width and Height of a string. I'm trying to understand how to create a method that will efficiently return a string with Environment.Newline inserted in the right places, so that if fits a certain Width and Height (Rectangle is used as a parameter for that).

有帮助吗?

解决方案

I found following code: XNA - Basic Word Wrapping

public string WrapText(SpriteFont spriteFont, string text, float maxLineWidth)
{
    string[] words = text.Split(' ');
    StringBuilder sb = new StringBuilder();
    float lineWidth = 0f;
    float spaceWidth = spriteFont.MeasureString(" ").X;

    foreach (string word in words)
    {
        Vector2 size = spriteFont.MeasureString(word);

        if (lineWidth + size.X < maxLineWidth)
        {
            sb.Append(word + " ");
            lineWidth += size.X + spaceWidth;
        }
        else
        {
            sb.Append("\n" + word + " ");
            lineWidth = size.X + spaceWidth;
        }
    }

    return sb.ToString();
}

其他提示

To add to Alina's answer, here is an extended version of that function, that will also linebreak single words that are longer than maxLineWidth

    public static string WrapText(SpriteFont font, string text, float maxLineWidth)
    {
        string[] words = text.Split(' ');
        StringBuilder sb = new StringBuilder();
        float lineWidth = 0f;
        float spaceWidth = font.MeasureString(" ").X;

        foreach (string word in words)
        {
            Vector2 size = font.MeasureString(word);

            if (lineWidth + size.X < maxLineWidth)
            {
                sb.Append(word + " ");
                lineWidth += size.X + spaceWidth;
            }
            else
            {
                if (size.X > maxLineWidth)
                {
                    if (sb.ToString() == "")
                    {
                        sb.Append(WrapText(font, word.Insert(word.Length / 2, " ") + " ", maxLineWidth));
                    }
                    else
                    {
                        sb.Append("\n" + WrapText(font, word.Insert(word.Length / 2, " ") + " ", maxLineWidth));
                    }
                }
                else
                {
                    sb.Append("\n" + word + " ");
                    lineWidth = size.X + spaceWidth;
                }
            }
        }

        return sb.ToString();
    }

To handle a block of text with carriage returns you need to modify the code as below:

  public static string WrapText(SpriteFont font, string text, float maxLineWidth)
    {
        string[] words = text.Split(' ');
        StringBuilder sb = new StringBuilder();
        float lineWidth = 0f;
        float spaceWidth = font.MeasureString(" ").X;

        foreach (string word in words)
        {
            Vector2 size = font.MeasureString(word);

            if (word.Contains("\r"))
            {
                lineWidth = 0f;
                sb.Append("\r \r" );
            }

            if (lineWidth + size.X < maxLineWidth )
            {
                sb.Append(word + " ");
                lineWidth += size.X + spaceWidth;
            }

            else
            {
                if (size.X > maxLineWidth )
                {
                    if (sb.ToString() == " ")
                    {
                        sb.Append(WrapText(font, word.Insert(word.Length / 2, " ") + " ", maxLineWidth));
                    }
                    else
                    {
                        sb.Append("\n" + WrapText(font, word.Insert(word.Length / 2, " ") + " ", maxLineWidth));
                    }
                }
                else
                {
                    sb.Append("\n" + word + " ");
                    lineWidth = size.X + spaceWidth;
                }
            }
        }

        return sb.ToString();
    }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top