如何使用Garmin ConnectIQ SDK格式化和显示长文本



我试图显示一条可能比屏幕宽度长的消息。格式化消息以将其显示为多行的最佳方式是什么?

注意,消息来自服务器,所以它不是硬编码的资源字符串。

我看不到任何工具,Toybox::WatchUi::Text drawable和Dc.drawText似乎都不支持段落格式。

Dc.getTextDimensions允许确定文本的宽度和高度,因此这可能很有帮助,但本地应用程序(例如消息通知程序)确实显示格式正确的段落,所以我觉得我错过了一些东西。

自从API 3.1.0级以来,有一个非常吸引人的fitTextToArea(),可以用来获得适合指定区域的文本字符串。

参数:

  • text-(Lang.String)--要放入给定区域的文本,其中可能包括换行符
  • font--(Graphics.FontType)--确定换行位置时使用的字体
  • width--(Lang.Number)--要容纳的区域的宽度
  • height--(Lang.Number)--要容纳的区域的高度
  • truncate——(Lang.Boolean)——如果为true,则可以使用所提供的字体截断得到的字符串以适应所提供的区域

退货:

返回适用于在给定区域中显示的String。如果truncate参数为true,并且String无法放入指定区域,则String将被截断。否则,将返回null

例如:

//! Draw the item's label and bitmap
//! @param dc Device context
public function draw(dc as Dc) as Void {
    var font = Graphics.FONT_XTINY;
    dc.setColor(Graphics.COLOR_DK_GRAY, Graphics.COLOR_TRANSPARENT);
    dc.drawText(dc.getWidth() / 2,
                dc.getHeight() / 2,
                font,
                Graphics.fitTextToArea(_description, font, dc.getWidth()-10, dc.getHeight(), true),
                Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER);
}

参考

  • https://developer.garmin.com/connect-iq/api-docs/Toybox/Graphics.html#fitTextToArea-instance_function

我最终使用启发式算法来计算适合该行的最大字符数,并在必要时换行:

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;
            }
        }
    }
}

这可能不是最漂亮或最有效的解决方案,但它确实有效!

我想您必须使用https://developer.garmin.com/downloads/connect-iq/monkey-c/doc/Toybox/Graphics/Dc.html#getTextWidthInPixels-实例方法

我面临着几乎相同的问题,尽管对于我的解决方案,我会剪掉不适合屏幕宽度/文本框宽度的字符

我正在制作一个实用函数来计算我可以放入特定宽度的字符串,如下所示:

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

相关内容

  • 没有找到相关文章

最新更新