可直接用于libgdx项目中的布局类(可直接复制进项目使用),支持定制行列宽,支持表格嵌套,支持单元格元素居中/左对齐,支持整体显示和隐藏的切换
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
import java.util.LinkedList;
public class GridLayout {
// 舞台元素
private Actor[][] actors;
// 行数,列数
private int row;
private int column;
// 行高,列宽
private float[] rowHeights;
private float[] columnWidths;
// 坐标
private float x;
private float y;
// 居中对齐
private boolean center;
// 网格们
private LinkedList<GridLayout> grids = new LinkedList<>();
// layout的宽高
private float width;
private float height;
// 是否可见
private boolean visible;
/**
* 构造布局
* @param row 行数
* @param column 列数
* @param x 网格开始坐标x
* @param y 网格开始坐标y
* @param rowHeight 行高
* @param columnWidth 列宽
* @param center 每格剧中布局? true/false
*/
public GridLayout(int row, int column, float x, float y, float rowHeight, float columnWidth, boolean center) {
this.center = center;
this.row = row;
this.column = column;
this.x = x;
this.y = y;
actors = new Actor[row][column];
rowHeights = new float[row];
columnWidths = new float[column];
for (int i = 0; i < row; i++) {
rowHeights[i] = rowHeight;
}
for (int i = 0; i < column; i++) {
columnWidths[i] = columnWidth;
}
width = columnWidth * column;
height = rowHeight * row;
visible=true;
}
/**
* 布局到舞台
* 调用此方法实现布局
* @param stage 舞台
*/
public void layout(Stage stage) {
for (int i = 0; i < row; i++) {
float alHeight = y;
for (int h = 0; h < i; h++) {
alHeight += rowHeights[h];
}
for (int j = 0; j < column; j++) {
if (actors[i][j] == null) continue;
float alWidth = x;
for (int w = 0; w < j; w++) {
alWidth += columnWidths[w];
}
if (center) {
actors[i][j].setPosition(
alWidth + (columnWidths[j] - actors[i][j].getWidth()) / 2,
alHeight + (rowHeights[i] - actors[i][j].getHeight()) / 2
);
} else {
actors[i][j].setPosition(alWidth, alHeight);
}
}
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if (actors[i][j] == null) {
continue;
}
stage.addActor(actors[i][j]);
}
}
for (GridLayout grid : grids) {
grid.layout(stage);
}
}
/**
* 通过Actor数组添加元素,元素数量不得超过row * column,从左下到右上添加(和libgdx布局方式保持一致)
* @param actorArray Actor数组
*/
public void pushActors(Actor[] actorArray) {
if (actorArray.length > row * column) {
throw new ArrayIndexOutOfBoundsException("元素数量超出网格布局最大限制");
} else {
int index = 0;
for (int i = 0; i < row; i++) {
if (index >= actorArray.length) {
break;
}
for (int j = 0; j < column; j++) {
actors[i][j] = actorArray[index];
if (++index > actorArray.length) {
break;
}
}
}
}
}
/**
* 在网格中添加网格
* @param rowIndex
* @param columnIndex
*/
public void addElement(GridLayout grid, int rowIndex, int columnIndex) {
float alWidth = x;
for (int i = 0; i < columnIndex; i++) {
alWidth += columnWidths[i];
}
float alHeight = y;
for (int i = 0; i < rowIndex; i++) {
alHeight += rowHeights[i];
}
grid.setLocation(alWidth, alHeight);
grids.add(grid);
}
/**
* 在网格的指定位置添加元素
* @param rowIndex
* @param columnIndex
*/
public void addElement(Actor actor, int rowIndex, int columnIndex) {
actors[rowIndex][columnIndex] = actor;
}
/**
* 自定义列宽
* @param columnIndex 列index (从0开始)
* @param width 设置的宽度
*/
public void setWidth(int columnIndex, float width) {
columnWidths[columnIndex] = width;
}
/**
* 自定义行高
* @param rowIndex 行index (从0开始)
* @param height 设置的高度
*/
public void setHeight(int rowIndex, float height) {
rowHeights[rowIndex] = height;
}
/**
* 设置坐标
* @param x
* @param y
*/
public void setLocation(float x, float y) {
this.x = x;
this.y = y;
}
/**
* 更改居中
* @param center 居中否
*/
public void setCenter(boolean center) {
this.center = center;
}
public float getWidth() {
return width;
}
public float getHeight() {
return height;
}
public float getX() {
return this.x;
}
public float getY() {
return this.y;
}
/**
* grid居中于指定舞台
* @param stage
*/
public void moveToCenter(Stage stage) {
float gridX;
float gridY;
gridX = (stage.getWidth() - getWidth()) / 2;
gridY = (stage.getHeight() - getHeight()) / 2;
setLocation(gridX, gridY);
}
/**
* 用于显示整个layout的元素
* @param stage layout所在的stage
*/
public void show(Stage stage){
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if (actors[i][j]!=null){
stage.addActor(actors[i][j]);
}
}
}
for(GridLayout grid:grids){
grid.show(stage);
}
visible = true;
}
/**
* 用于隐藏整个layout的元素
* @param stage layout所在的stage
*/
public void hide(Stage stage){
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if (actors[i][j]!=null){
stage.getRoot().removeActor(actors[i][j]);
}
}
}
for(GridLayout grid:grids){
grid.hide(stage);
}
visible = false;
}
/**
* 查看该layout是否处于可见状态
* @return boolean true/false 可见/隐藏
*/
public boolean isVisible(){
return visible;
}
/**
* 设置可见(不是隐藏用的方法)不推荐使用!!!
* 使用show()和hide()方法控制表格布局的显示和隐藏,不要使用此方法!!!
* @param visible boolean true/false
*/
public void setVisible(boolean visible) {
this.visible = visible;
}
}
使用demo(仅供参考,非完整可运行程序):
// 设置button样式
upTexture = new Texture(Gdx.files.internal("but1.png"));
downTexture = new Texture(Gdx.files.internal("but2.png"));
Button.ButtonStyle style = new Button.ButtonStyle();
style.up = new TextureRegionDrawable(new TextureRegion(upTexture));
style.down = new TextureRegionDrawable(new TextureRegion(downTexture));
// 声明网格布局4行3列
grid1 = new GridLayout(4,3,0,0,100,100,false);
buttons[0] = new Button(style);
buttons[0].addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG,"1按钮被点击了");
}
});
buttons[0].setSize(100,100);
buttons[1] = new Button(style);
buttons[1].addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG,"2按钮被点击了");
}
});
buttons[1].setSize(100,100);
buttons[2] = new Button(style);
buttons[2].addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG,"3按钮被点击了");
}
});
buttons[2].setSize(100,100);
buttons[3] = new Button(style);
buttons[3].addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG,"4按钮被点击了");
}
});
buttons[3].setSize(100,100);
buttons[4] = new Button(style);
buttons[4].addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG,"5按钮被点击了");
}
});
buttons[4].setSize(100,100);
buttons[5] = new Button(style);
buttons[5].addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG,"6按钮被点击了");
}
});
buttons[5].setSize(100,100);
buttons[6] = new Button(style);
buttons[6].addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG,"7按钮被点击了");
}
});
buttons[6].setSize(100,100);
buttons[7] = new Button(style);
buttons[7].addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG,"8按钮被点击了");
}
});
buttons[7].setSize(100,100);
buttons[8] = new Button(style);
buttons[8].addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG,"9按钮被点击了");
}
});
buttons[8].setSize(100,100);
button3 = new Button(style);
button3.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG,"666按钮被点击了");
}
});
button3.setSize(100,100);
// 控制开关(点击此按钮控制整个GridLayout的显示和隐藏)
Button button4 = new Button(style);
button4.addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
if(grid1.isVisible()){
grid1.hide(stage);
}else{
grid1.show(stage);
}
}
});
button4.setSize(100,100);
button4.setPosition(1000,300);
stage.addActor(button4);
// 再建立3个按钮
for(int i=0;i<3;i++){
buttons2[i] = new Button(style);
buttons2[i].addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG,"按钮被点击了");
}
});
buttons2[i].setSize(100,100);
}
// 设置第二个网格布局,展示嵌套使用
GridLayout grid2 = new GridLayout(1,3,0,0,100,100,false);
grid2.pushActors(buttons2);
grid1.pushActors(buttons);
// 可以灵活改变表格宽高
grid1.setWidth(1, 300);
grid1.addElement(grid2,3,1);
grid1.addElement(button3,3,0);
grid1.layout(stage);
效果图: