我正在尝试显示一条可能比屏幕宽度长的消息。格式化消息以将其显示为多行的最佳方法是什么?
请注意,消息来自服务器,因此它不是硬编码的资源字符串。
我看不到任何工具,而且Toybox::WatchUi::Text drawable 和Dc.drawText似乎都不支持段落格式。
Dc.getTextDimensions 允许确定文本的宽度和高度,因此这可能会有所帮助,但本机应用程序(例如消息通知程序)确实显示格式正确的段落,所以我觉得我错过了一些东西。
我正在尝试显示一条可能比屏幕宽度长的消息。格式化消息以将其显示为多行的最佳方法是什么?
请注意,消息来自服务器,因此它不是硬编码的资源字符串。
我看不到任何工具,而且Toybox::WatchUi::Text drawable 和Dc.drawText似乎都不支持段落格式。
Dc.getTextDimensions 允许确定文本的宽度和高度,因此这可能会有所帮助,但本机应用程序(例如消息通知程序)确实显示格式正确的段落,所以我觉得我错过了一些东西。
我最终使用启发式方法来计算适合该行的最大字符数,并在必要时换行:
function formatText(dc, text, width, font) {
// characters below worked better than "EeeTtaAooiNshRdlcum "
// which I used initially and is based on frequency of characters
// in English words
var chars = "AbCdEfGhIj";
var oneCharWidth = dc.getTextWidthInPixels(chars, font) / chars.length();
var charPerLine = mListWidth / oneCharWidth;
if (text.length() > charPerLine) {
var result = text.substring(0, charPerLine);
result += "\n";
result += text.substring(charPerLine, text.length());
return [result, 0];
} else {
return [text, 1];
}
}
我的开源IQ Connect Garminello应用程序中的实际功能在这里。
我想出了一个很好的递归解决方案,它考虑了很多可能性(在字符串中有“\n”或“”,如果一个词太长,它会拆分这个词):
function convertTextToMultiline(dc, text){
var extraRoom = 0.8;
var oneCharWidth = dc.getTextWidthInPixels("EtaoiNshrd",Graphics.FONT_SMALL)/10;
var charPerLine = extraRoom * dc.getWidth()/oneCharWidth;
return convertTextToMultilineHelper(text, charPerLine);
}
function convertTextToMultilineHelper(text, charPerLine) {
if (text.length() <= charPerLine) {
return text;
} else {
var i = charPerLine + 1;
for (; i >= 0; i--) {
if (text.substring(i, i + 1).equals("\n")) {
break;
}
}
if (i >= 0) {
var line = text.substring(0, i);
var textLeft = text.substring(i + 1, text.length());
var otherLines = convertTextToMultilineHelper(textLeft, charPerLine);
return line + "\n" + otherLines;
} else {
var lastChar = charPerLine + 1;
while (!(text.substring(lastChar, lastChar + 1).equals(" ") || text.substring(lastChar, lastChar + 1).equals("\n"))&& lastChar >= charPerLine/2) {
lastChar--;
}
if (lastChar >= charPerLine/2) {
var line = text.substring(0, lastChar + 1);
var textLeft = text.substring(lastChar + 1, text.length());
var otherLines = convertTextToMultilineHelper(textLeft, charPerLine);
return line + "\n" + otherLines;
} else {
var line = text.substring(0, charPerLine) + "-";
var textLeft = text.substring(charPerLine, text.length());
var otherLines = convertTextToMultilineHelper(textLeft, charPerLine);
return line + "\n" + otherLines;
}
}
}
}
它可能不是最漂亮或最有效的解决方案,但它确实有效!
我面临着几乎相同的问题,尽管对于我的解决方案,我将切断不适合屏幕宽度/文本框宽度的字符
我正在制作一个实用函数来计算我可以适合特定宽度的字符串,如下所示:
function getTextWidthMaxWidth(dc, text, font, maxWidth) {
var dispText = text;
//chunk off a char until it fits maxWidth
while (dc.getTextWidthInPixels(dispText, font) > maxWidth) {
dispText = dispText.subString(0, dispText.Length() - 1);
}
return dispText;
}
如今,这就是TextArea的用途。
using Toybox.WatchUi;
using Toybox.Graphics as Gfx;
class ErrorView extends WatchUi.View {
hidden var _message;
hidden var _textArea;
function initialize(message) {
_message = message;
View.initialize();
}
function onLayout(dc) {
_textArea = new WatchUi.TextArea({
:text=>_message.toString(),
:color=>Graphics.COLOR_WHITE,
:font=>[Graphics.FONT_XTINY],
:locX =>WatchUi.LAYOUT_HALIGN_CENTER,
:locY=>WatchUi.LAYOUT_VALIGN_CENTER,
:width=>dc.getWidth()* 2/3,
:height=>dc.getHeight() * 2/3
});
}
function onUpdate(dc) {
dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_BLACK);
dc.clear();
_textArea.draw(dc);
}
}