Search code examples
javauser-interfacelibgdxposition

LibGDX How do I update Actor positions after resizing window?


I'm trying to stick toolbar buttons to the top-right of my screen, but whenever I resize the window, the buttons stay in the same absolute position (relative to the bottom-left).

Before resize: before resize

After resize: after resize

This is the method that generates the UI button (Which is currently only called in the Screen's constructor):

private void generateUiToolbar(){
    // Toolbar Table
    Table table = new Table();
    table.setFillParent(true);
    table.top();
    table.right();

    // Menu button
    table.row();
    Texture myTexture = new Texture(Gdx.files.internal("ui/stamp.png"));
    TextureRegion myTextureRegion = new TextureRegion(myTexture);
    TextureRegionDrawable myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion);
    ImageButton menuButton = new ImageButton(myTexRegionDrawable);
    menuButton.addListener( new ClickListener() {
        @Override
        public void clicked(InputEvent event, float x, float y) {
            stage.clear();
            generateUiMenu();
        }
    });
    table.add(menuButton).size(60,60).padTop(10).padRight(10);

    stage.addActor(table);
}

This is the resize() method:

public void resize(int width, int height) {
    stage.getViewport().update(width, height, true);
    stage.getCamera().viewportWidth = width;
    stage.getCamera().viewportHeight = height;
    stage.getCamera().position.set(stage.getCamera().viewportWidth / 2, stage.getCamera().viewportHeight / 2, 0);
    stage.getCamera().update();
}

The variable stage is initiated in the constructor with stage = new Stage();

For some reason stage.getViewport().update(width, height, true); doesn't do anything. When I print stage.getWidth() after resizing, it will return the same number. What's a good way to update the location of the button or Actors in general? Simply clearing the stage and generating the UI again won't work for me, because sometimes when you resize, there are different actors currently displayed. If I missed any information, please let me know.

EDIT 1: Added table.setFillParent(true); as mentioned in an answer, but that didn't fix it either.

EDIT 2: After reading the answers and comments, I deleted the stage.getCamera() manipulation, but I'm still not getting the correct result. This is what happens when I resize with just the line of code stage.getViewport().update(width, height, true);: after resize with just viewport manipulation


Solution

  • I think you misunderstand the usage of Viewport. In your resize method you do:

    stage.getViewport().update(width, height, true);
    stage.getCamera().viewportWidth = width;
    stage.getCamera().viewportHeight = height;
    stage.getCamera().position.set(stage.getCamera().viewportWidth / 2, stage.getCamera().viewportHeight / 2, 0);
    stage.getCamera().update();
    

    But stage.getViewport().update(width, height, true); already does what you do in the next four lines.

    viewport.update(width, height) set the new width and height to the camera and updates the camera. So:

    viewport.update(width, height)
    
    is equal to
    
    camera.viewportWidth = width;
    camera.viewportHeight = height;
    camera.update();
    

    The only difference is that the viewport looks to the aspect ratio depending on which Viewport you use.

    And the third parameter: stage.getViewport().update(width, height, true); is a boolean value which says should the camera be centered. So if the third parameter is true the viewport will do:

    camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
    

    In your resize method you override the work of the viewport because with viewport.update(width, height, true) you already have done all of the resize and you don't need the four other lines.

    In the resize method this is enough:

    public void resize(int width, int height) {
        stage.getViewport().update(width, height, true);
    }
    

    You can read this for a better understanding of Viewport: How Camera works in Libgdx and together with Viewport