简体   繁体   中英

How to output text with a justify alignment

I am trying to create a component for libgdx which can output text in a manner equal to what html would do with a <p align=”justify”> ... </p> .

My idea was to add some custom component which can achieve this by adjusting the relative x and y coordinations of the components.

import java.util.ArrayList;
import java.util.List;

import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
import com.badlogic.gdx.utils.Align;

public class Paragraph extends WidgetGroup {

    private Label space;

    public Paragraph(String text, float width, LabelStyle style) {

        super();
        setWidth(width);

        this.space = new Label(" ", style);
        this.space.pack();

        String[] words = text.split(" ");
        for (String word : words) {

            Label label = new Label(word, style);
            label.pack();

            addActor(label);
        }    
    }

    public void layout () {

        float size = 0;
        List<Actor> elements = new ArrayList<Actor>();

        float x = getX(Align.topLeft);
        float y = getY(Align.topLeft);

        for (Actor actor : this.getChildren().items) {

            if (actor != null) {
                if (elements.isEmpty()) {
                    elements.add(actor);
                    size = actor.getWidth();

                } else {

                    if (size + space.getWidth() + actor.getWidth() <= this.getWidth()) {

                        elements.add(actor);
                        size += (space.getWidth() + actor.getWidth());

                    } else {

                        float spacing = space.getWidth() + ((getWidth() - size) / elements.size());

                        Actor element = elements.get(0);
                        element.setPosition(x, y, Align.topLeft);

                        x += element.getWidth();

                        for (int i = 1; i < elements.size(); i++) {
                            element = elements.get(i);
                            element.setPosition(x + spacing, y, Align.topLeft);

                            x += (spacing + element.getWidth());
                        }

                        // new line
                        elements.clear();
                        x = getX(Align.topLeft);
                        y += (this.space.getHeight() * 1.5);

                        elements.add(actor);
                        size = actor.getWidth();
                    }
                }
            }
        }

        if (elements.isEmpty() == false) {

            float spacing = space.getWidth();

            Actor element = elements.get(0);
            element.setPosition(x, y, Align.topLeft);

            x += element.getWidth();

            for (int i = 1; i < elements.size(); i++) {
                element = elements.get(i);
                element.setPosition(x + spacing, y, Align.topLeft);

                x += (spacing + element.getWidth());
            }
        }
    }
}

My problem is that the x and y coordinate I retrieve with getX(Align.topLeft) & getY(Align.topLeft) always returns (0,0) instead of the real coordinates on the stage.

Component structure looks like this:

Stage
+ Container
  + Table
    + ScrollPane
      + Table
        + Table
          + Paragraph
          + Paragraph
          + Paragraph
          + Paragraph
        + Image

So the end result is that all the text contained in the different paragraphs is drawn on top of each other. Not on position (0,0), but on the same position inside of the surrounding table.

I figured it out myself.

Seems it was a bad idea to override the layout method for that. I now call a different method from the constructor.

Also I messed up with the x and y coordinates, so I had to rewrite that method.

Ps.: I adjusted the question as well, as I figured out the solution, it was not really about the x and y coodinates of the widget group.

import java.util.ArrayList;
import java.util.List;

import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
import com.badlogic.gdx.utils.Align;

public class Paragraph extends WidgetGroup {

    private static final class RowData {

        final List<Actor> elements;
        final float size;
        final boolean lastRow;

        RowData(List<Actor> elements, float size, boolean lastRow) {
            this.elements = elements;
            this.size = size;
            this.lastRow = lastRow;
        }

        static RowData createNewRow(List<Actor> elements, float size) {
            return new RowData(elements, size, false);
        }

        static RowData createLastRow(List<Actor> elements, float size) {
            return new RowData(elements, size, true);
        }
    }

    private Label space;

    public Paragraph(String text, float width, LabelStyle style) {

        super();
        setWidth(width);

        this.space = new Label(" ", style);
        this.space.pack();

        String[] words = text.split(" ");
        for (String word : words) {

            Label label = new Label(word, style);
            label.pack();

            addActor(label);
        }

        arrangeActors();
    }

    private void arrangeActors() {

        float size = 0;
        float height = space.getHeight();

        List<RowData> rows = new ArrayList<RowData>(); 
        List<Actor> elements = new ArrayList<Actor>();

        Actor[] actors = this.getChildren().begin();

        for (Actor actor : actors) {

            if (actor != null) {
                if (elements.isEmpty()) {

                    elements.add(actor);
                    size = actor.getWidth();

                } else if (size + space.getWidth() + actor.getWidth() <= this.getWidth()) {

                    elements.add(actor);
                    size += (space.getWidth() + actor.getWidth());

                } else {

                    rows.add(RowData.createNewRow(elements, size));

                    elements = new ArrayList<Actor>();
                    height += space.getHeight();

                    elements.add(actor);
                    size = actor.getWidth();
                }
            }
        }

        this.getChildren().end();

        rows.add(RowData.createLastRow(elements, size));

        height += space.getHeight();
        setHeight(height);

        float y = height;

        for (RowData data : rows) {

            float spacing = space.getWidth();
            if (data.lastRow == false) {
                spacing += ((getWidth() - data.size) / data.elements.size()); 
            }

            Actor element = data.elements.get(0);
            element.setPosition(0, y, Align.topLeft);

            float x = element.getWidth();

            for (int i = 1; i < data.elements.size(); i++) {

                element = data.elements.get(i);                
                element.setPosition(x + spacing, y, Align.topLeft);
                x += (spacing + element.getWidth());
            }

            y -= this.space.getHeight();
        }
    }

    @Override
    public float getPrefWidth () {
        return getWidth();
    }

    @Override
    public float getPrefHeight () {
        return getHeight();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM