3
\$\begingroup\$

I want to create an Inputfield from Scratch in Java and LibGDX, my Question is: How can I display only certain Parts of a String in a specific width?

For example: My Input field GUI is 200 pixels wide. But I can write like 500 Letters maximum in my Input field. When I display this 500 letters all at once. It would be bigger than the GUI. So I want when I wrote down the first 100 letters and then write the next one that the first one disappears and the displayed text starts from the 2 Letter and then goes to the 101. And so on. Much like the Minecraft Chat Input field.

\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

One way to achieve this is to measure on-screen width the string contained by the control and compare that to the width of the control. If it is too wide, skip the first character and try again.

custom Actor

The GlyphLayout class in libGDX can help you here.

A naive implementation may look like this:

package com.bornander.playground3d;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;

public class CustomInput extends Actor {

    private static final String TEMPLATE = "The quick red fox jumps over the lazy brown dog. ";

    private int index = 0;
    private float elapsed;
    private BitmapFont font;
    private StringBuilder text = new StringBuilder();

    public CustomInput(Skin skin) {
        font = skin.getFont("default-font");
        setWidth(100);
        setHeight(font.getLineHeight());
    }

    @Override
    public void act(float delta) {
        // Just pretend a character is typed every .2 second
        elapsed += delta;
        if (elapsed > 0.2f) {
            elapsed = 0;
            text.append(TEMPLATE.charAt((index++) % TEMPLATE.length()));
        }
    }



    @Override
    public void draw(Batch batch, float parentAlpha) {
        font.setColor(Color.WHITE);

        // Try to fit the full text, if after measuring it it turns out to be too long, 
        // skip the first character and try again
        String textToDisplay = text.toString();
        for(int i = 0; i < text.toString().length(); ++i) {
            textToDisplay = text.toString().substring(i);

            GlyphLayout glyphLayout = new GlyphLayout(font, textToDisplay);
            if (glyphLayout.width < getWidth()) {
                break;
            }
        }

        font.draw(batch, textToDisplay, getX(), getY() + font.getLineHeight());
    }
}

In the above example I have ignored the task of attaching a key listener and the control simply adds a character every .2 seconds, also no consideration has been given to performance.

\$\endgroup\$
1
  • \$\begingroup\$ Glad you liked it @GentleXD, consider marking the answer as accepted if it solved your issue. \$\endgroup\$
    – bornander
    Jul 18, 2018 at 16:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .