5

我正在寻找一种使用 libgdx 逐步显示文本的方法,但我找不到完全按照我想要的方式进行操作的方法。这是我所做的:

  • 我有一个文本标签,它会定期更新以显示不同的文本。标签设置为setWrap(true);setAlignment(Align.center);
  • 每次我更改标签的文本时,我都会使用我这样构建的自定义操作

    public class DisplayTextAction extends TemporalAction{
        private CharSequence completeText;
    
        @Override
        protected void update(float percent) {
            ((Label)actor).setText(
                completeText.subSequence(
                    0,
                    (int)Math.round(completeText.length()*percent));
        }
    
        public void setText(String newText){
            completeText = newText;
        }
    }
    
  • 每次文本更新,我都会从池中调用操作,更改文本并将操作添加到标签中。

这是我的问题:对于居中和换行的文本,这不能按照我想要的方式工作。

当文本不居中时会发生这种情况(点代表空格):

|h........|
|hel......|
|hello....|

(按预期工作)

这是文本居中时发生的情况:

|....h....|
|...hel...|
|..hello..|

这就是我希望它的行为方式:

|..h......|
|..hel....|
|..hello..|

我解决这个问题的最初想法是使用两组字符串,一组是可见文本,一组是不可见的充当“填充”。我想出了这样的事情:

CharSequence visibleText = completeText.subSequence(
    0,
    (int)Math.round(completeText.length()*percent));
CharSequence invisibleText = completeText.subSequence(
    (int)Math.round(completeText.length()*percent),
    completeText.length());

所以我有两组字符串,但我找不到一种方法来显示两种不同的字体(一种是可见的,另一种是相同的,但 alpha 为 0)或与 Libgdx 相同的标签中的样式。

我被困住了,我不知道我的方法是否正确,或者我是否应该研究一些完全不同的东西,如果我的方法是正确的,我不知道如何使用 libgdx 工具跟进它。

编辑:

我按照 Jyro117 的说明进行操作,我可以取得很大的进步,但我无法使其与多行居中的文本一起工作。

想象一下这段文字:

|all those lines are|
|..for a very long..|
|........text.......|

它必须像这样显示

|all th.............|
|...................|
|...................|

|all those line.....|
|...................|
|...................|

|all those lines are|
|..for a ve.........|
|...................|

|all those lines are|
|..for a very long..|
|........text.......|

Jyro117 的解决方案给

|all those lines are|
|for a very long....|
|text...............|

正确显示。

或者

|...................|
|......all tho......|
|...................|

|...................|
|...all those lin...|
|...................|

|all those lines are|
|......for a v......|
|...................|
4

1 回答 1

4

您使解决方案过于复杂。您真正需要的是在添加所有文本时确定标签的大小。一旦确定了这一点,将标签尺寸锁定为这些尺寸,将其放在一个可扩展以填充其周围区域的表格内,然后使用操作更新您的标签。(您可以根据需要使用池等,但为简单起见,我将其排除在下面的代码之外)。

您显然必须使代码适应您的代码,但这为您提供了对我的意思的代码参考。

这是一种方法的代码片段:

stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
Gdx.input.setInputProcessor(stage);

uiSkin = new Skin(Gdx.files.internal("skin/uiskin.json"));

Table fullScreenTable = new Table();
fullScreenTable.setFillParent(true);

final String message = "hello";
final Label progressLabel = new Label(message, this.uiSkin);
final TextBounds bounds = progressLabel.getTextBounds(); // Get libgdx to calc the bounds
final float width = bounds.width;
final float height = bounds.height;
progressLabel.setText(""); // clear the text since we want to fill it later
progressLabel.setAlignment(Align.CENTER | Align.TOP); // Center the text

Table progressTable = new Table();
progressTable.add(progressLabel).expand().size(width, height).pad(10);

final float duration = 3.0f;

final TextButton button = new TextButton("Go!", this.uiSkin);
button.addListener(new ClickListener() {
    @Override public void clicked(InputEvent event, float x, float y) {
        progressLabel.addAction(new TemporalAction(duration){
            LabelFormatter formatter = new LabelFormatter(message);                 
            @Override protected void update(float percent) {
                progressLabel.setText(formatter.getText(percent));
            }
        }); 
    }
});
stage.addActor(button);

fullScreenTable.add(progressTable);
fullScreenTable.row();
fullScreenTable.add(button);

stage.addActor(fullScreenTable);

编辑:

添加了代码以使标签中的文本居中和顶部对齐。还添加了代码以填充末尾的空格以允许正确对齐。注意:仅对等宽字体有用。

class LabelFormatter {
    private final int textLength;
    private final String[] data;
    private final StringBuilder textBuilder;

    LabelFormatter(String text) {
        this.textBuilder = new StringBuilder();
        this.data = text.split("\n");
        int temp = 0;
        for (int i = 0 ; i < data.length; i++) {
            temp += data[i].length();
        }
        textLength = temp;
    }

    String getText(float percent) {
        textBuilder.delete(0, textBuilder.length());
        int current = Math.round(percent * textLength);

        for (final String row : data) {
            current -= row.length();
            if (current >= 0) {
                textBuilder.append(row);
                if (current != 0) {
                    textBuilder.append('\n');
                }
            } else {
                textBuilder.append(row.substring(0, row.length() + current));

                // Back fill spaces for partial line
                for (int i = 0; i < -current; i++) {
                    textBuilder.append(' ');
                }
            }

            if (current <= 0) {
                break;
            }
        }

        return textBuilder.toString();
    }
}
于 2013-08-16T17:45:39.040 回答