I'm making a card game with libgdx scene2d and what I'm trying to achieve is auto arrange the cards in a way the all fit the screen. This is what it looks now when the hand is full: enter image description here

I have done that using a horizontalGroup and puting a -1/3 cardWidth space between the cards. I want the cards to spread evenly when some are removed. I think I have to change the space between the cards whenever a card is removed or added but I don't know how much.

This is my code:

    CardActor[] cards = new CardActor[14];
    HorizontalGroup hand = new HorizontalGroup();
    int width = Gdx.graphics.getWidth()/10;
    int height = width * 2;
    hand.setBounds(width/2, -height/4, stage.getWidth()-width, height);
    hand.space(width / -3f);
    hand.align(Align.bottom | Align.center);
    for (int i = 0; i < cards.length; i++) {
        cards[i] = new CardActor(new Card(MathUtils.random(3), MathUtils.random(3, 10)));

And this is the CardActor:

public class CardActor extends ImageButton {

public CardActor(Card card) {
    super(new TextureRegionDrawable(CardTextures
            .getTexture(card.getType(), card.getRank())));

    int width = Gdx.graphics.getWidth()/10;
    int height = width*2;
    getImageCell().prefSize(width, height);
    setBounds(getX(), getY(), getWidth(), getHeight());
    addListener(new ChangeListener() {
        public void changed(ChangeEvent event, Actor actor) {

2 Answers 2


I did this once, you want to start by creating a startX variable so that the first card is centred in the centre of the screen at any given y value (screenWidth / 2 - cardWidth / 2).

Then for each other card it's x value on screen is the [startX + cardWidth / 2] (overlapping the previous card by half, giving the desired effect).

But for each card > 1 the startX must move to the left by half a card (startXOffset = cardWidth / 2 * totalCards. To keep the entire hand of cards centred. So the startX must negate the startXOffset.

As you add and remove cards just recalculate.

If the hand does get larger than what can fit on the screen, you will need to change the cardWidth overlap to be a fraction of the totalCards rather than just / 2 (gets smaller with each card).

For example:

for (int i = 0; i < totalCards; i++) {
       cards[i] = new CardActor(new Card(MathUtils.random(3), MathUtils.random(3, 10)));
       cards[i].setX(startX - startXoffset * (totalCards - i));

Then have a method in the hand class called reorganise or something that loops through all the cards (if they are still there) and resets their X values.

I honestly don't know how I would actually implement it but its just something to give you an idea, I am not good with Java graphics so I can't provide much more.

  • \$\begingroup\$ It seems to be exactly what I want! Could you explain me little more 5 - 6 lines because I don't quite get it. \$\endgroup\$
    – nrallakis
    Commented Feb 20, 2016 at 16:25
  • \$\begingroup\$ @nrallakis4 I'm not sure on what more I could say, what did you need to know? \$\endgroup\$
    – Daedric
    Commented Feb 20, 2016 at 17:18
  • \$\begingroup\$ What do you mean when you say card > 1. I also do not understand how the startX will negate the startXOffset. \$\endgroup\$
    – nrallakis
    Commented Feb 21, 2016 at 16:31
  • \$\begingroup\$ @nrallakis4 just added some more info on the question, I don't know what the best way to implement as I have only done it with another language, I know Java but haven't really used the graphics side, or this library your using. \$\endgroup\$
    – Daedric
    Commented Feb 21, 2016 at 16:51

I would comment on Daedrics answer but I don't have enough rep. His detailed explanation is great and is pretty much already handled by LibGdx's HorizontalGroup() widget, most of the actual layout calculations are already taken care of using the .center() and .space() methods.

What you need to do:

  • Create a HorizontalGroup() to hold the cards in your hand
  • Add the CardActors to the HorizontalGroup hand, by default they are just positioned at the 0,0 location of the HorizontalGroup (bottom-left)
  • Simply call hand.center() to have all of the cards aligned to the center of the HorizontalGroup
  • Now they will be centered, but not overlapping at all.
  • If you set the hand.space() as some negative width like you already have, you will see that they overlap.

I'm not sure of the details of your game, but the static space in between may be enough, if not you can always keep a reference to your hand and update the .space() whenever you need to.

Using a static space - In your example picture, removing the left most 8 wouldn't change the spacing, but the positions of the cards in the group would be moved to the left by a half a card(all of them). If you only had 1 card, it would be in the center.

_ _ _ _ _ C _ _ _ _ _ .

If you had 2 cards they would be grouped in the center. (the left card will be slightly to the left of center now)

_ _ _ _ _ C C _ _ _ _ _

Using a dynamic space - In your example picture, removing the left most 8 would cause the 3 to take its place. The rightmost card 9, wouldn't move. All of the cards in between are all moved left by different amounts. So if you had 1 card in your hand it would be in the center like the previous example,

_ _ _ _ _ C _ _ _ _ _,

but if you had 2 cards depending on how you calculate your spacing it may look like

_ _ C _ _ _ _ _ _ C _ _

C _ _ _ _ _ _ _ _ _ _ C

If you want to work with a static space, but are worried about when the width of the hand would be greater than the width of the screen, you can always tell set set .wrap(true) on your hand, and then depending on how you want them to look, change .wrapSpace() to your liking. * note that when you use wrap(true) you need to set a width for the HorizontalGroup()

So you'll have a couple of options here. Good news is the HorizontalGroup() makes things pretty simple


You must log in to answer this question.

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