My app provides two buttons in a table row. Each image has a width of 300 pixel (source). The app shows all parts of both buttons if I provide an initial window width which is greater than 600. Even resizing the window to a smaller size works smoothly. Both buttons are shown fully and they get scaled down if needed when resizing the window. The buttons are cut off once I provide an initial window size which is smaller than 600 pixel. How can I show the whole buttons on small screens by default?
Screenshots:
My code looks like this:
public class LevelChooserState extends GameState {
private Stage stage;
private Texture bgTexture;
private Pixmap bgPixmap;
private Viewport viewportStage;
private Container<Table> container;
private Table table;
public LevelChooserState(final GameStateController gsc) {
super(gsc);
Gdx.app.log(TAG, "Setup Level Chooser State.");
// Setup Background Color
bgPixmap = new Pixmap(1, 1, Pixmap.Format.RGB565);
bgPixmap.setColor(Color.WHITE);
bgPixmap.fill();
bgTexture = new Texture(bgPixmap);
TextureRegionDrawable textureRegionDrawableBg = new TextureRegionDrawable(new TextureRegion(bgTexture));
// Setup viewports
viewportStage = new ExtendViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
viewportStage.setScreenBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
// Setup stage
stage = new Stage(viewportStage);
Gdx.input.setInputProcessor(stage);
// Setup font
int Help_Guides = 12;
int row_height = Gdx.graphics.getWidth() / 12;
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/PatrickHand-Regular.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.size = 30;
parameter.borderWidth = 1;
parameter.color = Color.BLACK;
BitmapFont myFont = generator.generateFont(parameter);
generator.dispose();
// Setup background pictures
TextureAtlas textureAtlas = new TextureAtlas("atlas/onoff.atlas");
TextureRegion backgroundTR1 = textureAtlas.findRegion("onoff_off");
TextureRegion backgroundTR2 = textureAtlas.findRegion("onoff_on");
// Setup TextButtons
TextureRegionDrawable up1= new TextureRegionDrawable(backgroundTR1);
TextureRegionDrawable down1= new TextureRegionDrawable(backgroundTR2);
TextureRegionDrawable checked1= new TextureRegionDrawable(backgroundTR2);
String text1 = "Deceptive dance in the poultry house.";
ClickListener clickListner1 = new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(Constants.TAG, "Button click received.");
gsc.setState(GameStateController.State.PLAY);
}
};
TextButton textButton1 = createTextButton(myFont, text1, up1, down1, checked1, clickListner1);
// ... created some more buttons at this point
// Setup Layout
container = new Container<Table>();
container.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
container.setBackground(textureRegionDrawableBg);
container.align(Align.bottomLeft);
table = new Table();
table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
table.setTouchable(Touchable.enabled);
table.setDebug(true);
table.debugAll();
table.setBackground(textureRegionDrawableBg);
table.setFillParent(true);
table.align(Align.top);
// TODO take care of scaling too when setting padding
float padding = 10;
table.row();
table.add(textButton1).expandX().pad(padding);
table.add(textButton2).expandX().pad(padding);
table.row();
table.add(textButton3).expandX().pad(padding);
table.add(textButton4).expandX().pad(padding);
table.row();
container.setActor(table);
stage.addActor(container);
}
private TextButton createTextButton(BitmapFont font, String text, TextureRegionDrawable up, TextureRegionDrawable down, TextureRegionDrawable checked, ClickListener clickListener) {
Label.LabelStyle labelStyle = new Label.LabelStyle();
labelStyle.font = font;
Label label = new Label(text,labelStyle);
label.setWrap(true);
TextButton.TextButtonStyle style = new TextButton.TextButtonStyle();
style.up = up;
style.down = down;
style.checked = checked;
style.font = font;
TextButton button = new TextButton(label.toString(), style);
//button.setSize(50,100);
button.setLabel(label);
button.getLabelCell().pad(20f);
button.getLabel().setAlignment(Align.topLeft);
button.setPosition(0,0);
button.addListener(clickListener);
return button;
}
@Override
public void update(float delta) {
}
@Override
public void render() {
Gdx.gl.glClearColor(1f,1f,1f,1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
stage.getViewport().apply();
stage.draw();
stage.act();
batch.end();
}
@Override
public void dispose() {
Gdx.app.log(TAG, "dispose(); Level Chooser");
stage.dispose();
bgPixmap.dispose();
bgTexture.dispose();
}
@Override
public void resize(int w, int h) {
Gdx.app.log(TAG, "resize() LevelChooserState;");
stage.getViewport().update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
container.setFillParent(true); // makes sure the container will expand on resize
}
}

LibGDX uses real-pixel-to-screen-pixel mapping. You're using an ExtendViewport to initialize the game, which takes its minimum height and width from the actual window size in
Gdx.graphics.getWidth(), Gdx.graphics.getHeight(). This means that the 'fake screen' you have, which you can then resize as much as you want, is actually determined by the size of the window.I would advise you start with a fixed size for the ExtendViewport - say, 600 width, 400 height - and later you can change this to suit different sizes if necessary.
ExtendViewport with fixed sizes works fantastically well, even when displaying on extremely large screens.