-
Notifications
You must be signed in to change notification settings - Fork 36
SplitPane HorizontalGroup and VerticalGroup
SplitPane and Horizontal/VerticalGroup are great ways to organize widgets. SplitPane allows the user to adjust the size of two widgets by dragging a border between the two. HorizontalGroup and VerticalGroup allow the user to add multiple child widgets one after the other in a line. It is most useful for allowing elements to wrap across a span.
The "handle" drawable is the divider that users must click to make adjustments to the split value. Make sure to supply a handle with enough width to allow the user to mouse over it. 1 pixel width is not enough. A simple square that can stretch in a direction should be good enough. Use a 9patch or TenPatch to add detail.
SplitPane does not use a "default" style. Make sure to supply a "defaultHorizontal" and "defaultVertical" style if you plan to use both states of the widget. Horizontal means widgets on the left and right. Vertical means widgets on the top and bottom.
This is a simple horizontal SplitPane that attaches two TextButtons. You can add any widget you desire into the two child slots.
TextButton textButton1 = new TextButton("test1", skin);
TextButton textButton2 = new TextButton("test2", skin);
SplitPane splitPane = new SplitPane(textButton1, textButton2, false, skin);
root.add(splitPane).growX();
Notice that you can't actually make the widget smaller than the minWidth of the associated widgets. If that's important to you, stick them into ScrollPanes. ScrollPane has a minWidth of 0. This allows users to scroll the contents of the pane when you squish them beyond their minimum size.
TextButton textButton1 = new TextButton("test1", skin);
ScrollPane scrollPane1 = new ScrollPane(textButton1, skin);
scrollPane1.setFadeScrollBars(false);
TextButton textButton2 = new TextButton("test2", skin);
ScrollPane scrollPane2 = new ScrollPane(textButton2, skin);
scrollPane2.setFadeScrollBars(false);
SplitPane splitPane = new SplitPane(scrollPane1, scrollPane2, false, skin);
root.add(splitPane).growX();
If you don't care about allowing users to scroll the contents, you can just use Containers.
TextButton textButton1 = new TextButton("test1", skin);
Container container1 = new Container(textButton1);
container1.fill().minWidth(0);
TextButton textButton2 = new TextButton("test2", skin);
Container container2 = new Container(textButton2);
container2.fill().minWidth(0);
SplitPane splitPane = new SplitPane(container1, container2, false, skin);
root.add(splitPane).growX();
You can set the initial split amount and the min/max. These are values from 0 to 1 with 1 being completely full.
splitPane.setSplitAmount(.75f);
splitPane.setMinSplitAmount(.25f);
splitPane.setMaxSplitAmount(.75f);
You can use an advanced listener to apply an arrow resize mouse icon. This is compatible with the LWJGL3 backend. If the widgets you use are not Touchable.enabled by default, make sure to set it.
public class ResizeArrowListener extends DragListener {
private boolean draggingCursor;
private boolean vertical;
public ResizeArrowListener(boolean vertical) {
this.draggingCursor = false;
this.vertical = vertical;
}
@Override
public void exit(InputEvent event, float x, float y, int pointer,
Actor toActor) {
if (!draggingCursor && event.getListenerActor().equals(event.getTarget())) {
Gdx.graphics.setSystemCursor(Cursor.SystemCursor.Arrow);
}
}
@Override
public void enter(InputEvent event, float x, float y, int pointer,
Actor fromActor) {
if (!draggingCursor && event.getListenerActor().equals(event.getTarget())) {
if (vertical) {
Gdx.graphics.setSystemCursor(Cursor.SystemCursor.VerticalResize);
} else {
Gdx.graphics.setSystemCursor(Cursor.SystemCursor.HorizontalResize);
}
}
}
@Override
public void dragStop(InputEvent event, float x, float y, int pointer) {
Gdx.graphics.setSystemCursor(Cursor.SystemCursor.Arrow);
draggingCursor = false;
}
@Override
public void dragStart(InputEvent event, float x, float y,
int pointer) {
if (!draggingCursor && event.getListenerActor().equals(event.getTarget())) {
if (vertical) {
Gdx.graphics.setSystemCursor(Cursor.SystemCursor.VerticalResize);
} else {
Gdx.graphics.setSystemCursor(Cursor.SystemCursor.HorizontalResize);
}
draggingCursor = true;
}
}
}
ResizeArrowListener resizeArrowListener = new ResizeArrowListener(false);
splitPane.addListener(resizeArrowListener);
HorizontalGroup and VerticalGroup do not have a style at all because it is strictly used for layout very much like Table. But why would you want to use a HorizontalGroup instead of a Table? Horizontal group is a lot easier to add and remove elements to it. You don't have to think about rows or columns. You simply add actors to it.
HorizontalGroup horizontalGroup = new HorizontalGroup();
table.add(horizontalGroup);
horizontalGroup.addActor(widgetA);
horizontalGroup.addActor(widgetB);
horizontalGroup.addActor(widgetC);
horizontalGroup.addActor(widgetD);
HorizontalGroups go from left to right. VerticalGroups go from top to bottom.
VerticalGroup verticalGroup = new VerticalGroup();
table.add(verticalGroup);
verticalGroup.addActor(widgetA);
verticalGroup.addActor(widgetB);
verticalGroup.addActor(widgetC);
verticalGroup.addActor(widgetD);
You can reverse the order of the elements by simply calling reverse().
horizontalGroup.reverse();
Notice that the width of each "cell" conforms to the minWidth of the widget in a HorizontalGroup. The same applies to the heights in a VerticalGroup.
HorizontalGroup horizontalGroup = new HorizontalGroup();
table.add(horizontalGroup);
horizontalGroup.addActor(widgetLarge);
horizontalGroup.addActor(widgetMedium);
horizontalGroup.addActor(widgetSmall);
When the HorizontalGroup/VerticalGroup fills a large space, you can set the alignment of the contents. Beware that HorizontalGroup defaults to Align.left.
HorizontalGroup horizontalGroup = new HorizontalGroup();
table.add(horizontalGroup).grow();
horizontalGroup.addActor(widgetLarge);
horizontalGroup.addActor(widgetMedium);
horizontalGroup.addActor(widgetSmall);
horizontalGroup.align(Align.top);
horizontalGroup.align(Align.bottom);
Notice that each individual widget is not aligned. When your child widgets are not uniform size, you can set the row alignment of each child in the HorizontalGroup. It's important to know the difference between align() and rowAlign(). Set column alignment in VerticalGroup.
horizontalGroup.align(Align.center);
horizontalGroup.rowAlign(Align.bottom);
If you want to stretch the widgets to make up the difference in size, you can use grow().
horizontalGroup.grow();
Given an abundance of child widgets, you'll eventually run out of room and exceed the available space of the stage.
HorizontalGroup horizontalGroup = new HorizontalGroup();
table.add(horizontalGroup).grow();
horizontalGroup.addActor(widgetA);
horizontalGroup.addActor(widgetB);
horizontalGroup.addActor(widgetC);
horizontalGroup.addActor(widgetD);
horizontalGroup.addActor(widgetE);
horizontalGroup.addActor(widgetF);
horizontalGroup.addActor(widgetG);
horizontalGroup.addActor(widgetH);
horizontalGroup.addActor(widgetI);
horizontalGroup.addActor(widgetJ);
horizontalGroup.align(Align.center);
You can set wrap so that the elements will flow to the next available row given the available space.
horizontalGroup.wrap();
You can reverse the order of the rows or columns if you desire.
horizontalGroup.wrapReverse();
Let's talk about spacing and padding now. Spacing is the distance between each individual widget. In the case of HorizontalGroup, it's the horizontal space between each element on a row.
horizontalGroup.space(50);
Notice that it doesn't affect the vertical space between each row. To change that, you need to set the wrap space.
horizontalGroup.wrapSpace(20);
Padding is the extra space around the entire HorizontalGroup/VerticalGroup. This may not seem intuitive because of how padding/spacing can be used with table cells.
horizontalGroup.pad(50);
horizontalGroup.pad(150);
Proceed with the next chapter, 10 - Images or return to the table of contents.
Getting Started
Windows
Linux
Mac
Features Manual
Colors
Fonts
Creating Bitmap Fonts
Creating FreeType Fonts
Creating Image Fonts
Drawables
Nine Patches
Ten Patches
Classes, Styles, and the Preview Panel
Custom Classes
Exporting
Importing
Saving / Loading
VisUI Skins
Tips and Tricks
TextraTypist Playground
Scene Composer
Scene Composer
Exporting a Scene
Modifying a Scene
Tutorials
Skin Composer Videos
From The Ground Up Series
Examples
Ray3K Skins