XNA имеет класс Spritefont, который имеет метод MeasureString, который может возвращать ширину и высоту string
. Я пытаюсь понять, как создать метод, который будет эффективно возвращать строку с Environment.Newline
, вставленным в нужные места, так что если она соответствует определенной ширине и высоте (для этого используется Rectangle).Как реализовать перенос слов?
ответ
Я нашел следующий код: 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();
}
Чтобы добавить ответ Алины, здесь является расширенной версией этой функции, которая будет также LineBreak отдельных слов, которые больше, чем 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();
}
Чтобы обработать блок текста с возвратом каретки, вам необходимо изменить код, как показано ниже:
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();
}
Спасибо за модификацию, он работает очень хорошо, но почему '' 'sb.Append (" \ r \ r ");' '' part? он просто добавляет двойные пробелы между словами, почему это не '' 'sb.Append (" \ r ");' '' (работает одинаково без лишних пробелов, по крайней мере, в примерах, которые я проверил). –
Я нашел это [XNA Word Wrapping] (http://www.xnawiki.com/index.php/Basic_Word_Wrapping). Другой поток с некоторым [кодом] (http://xboxforums.create.msdn.com/forums/p/10536/55295.aspx). –
@AlinaB. Спасибо, что на самом деле решил мою проблему! Вы должны опубликовать код с этой страницы в качестве ответа, если вики исчезнут. И ответ принадлежит вам. – user1306322