LibGdx 游戏开发之TableLayout

https://github.com/EsotericSoftware/tablelayout

Please use the TableLayout discussion group for support.

Overview 概述

TableLayout是一个轻量级的Java库,它和HTML的table类似。可以利用logical table来设置UI widget的位置尺寸
TableLayout的核心是UI toolkit agnostic,支持 libgdx, Swing, Android, and TWL。使用table的layout非常直观,而且TableLayout's JAVA API非常好用。

快速开始

下面是libgdx中一个简单例子:

    // Keep your code clean by creating widgets separate from layout.
    Label nameLabel = new Label("Name:", skin);
    TextField nameText = new TextField(skin);
    Label addressLabel = new Label("Address:", skin);
    TextField addressText = new TextField(skin);

    Table table = new Table();
    table.add(nameLabel);              // Row 0, column 0.
    table.add(nameText).width(100);    // Row 0, column 1.
    table.row();                       // Move to next row.
    table.add(addressLabel);           // Row 1, column 0.
    table.add(addressText).width(100); // Row 1, column 1.

上面的代码增加了2行2列一共4个单元格。add方法返回1个cell, cell有控制layout的方法。在例子中text fields的宽度被设置为100.
本文档中使用的示例代码是针对libgdx的,但其他支持的工具包的API几乎完全相同

image.png

Root table 根表

当进行UI布局的时候,UI widget并不设置它自己的尺寸,它只是提供minimun,preferredmaximum三种选项。widget的父元素使用其自身的尺寸和这三种选项,来对widget进行尺寸设置。许多布局会使用单个固定尺寸(通常为整个屏幕)的table作为根表.widgets和内部表被加入到根表中。
每种UI toolkit都有不同的设定根表尺寸的方法,例如:在Swing中需要把table加入JFrame‘s的内容面板;在libgdx中用setFillParent方法:

    Table table = new Table();
    table.setFillParent(true);
    stage.addActor(table);

Debugging 调试

TableLayout可以画出调试线,用于视觉化。Debugging通过在table上调用debug方法来开启。如果debugging开启了,Libgdx可以自动渲染调试线。其他的UI toolkits可能需要调用函数去渲染调试线。

    table.debug();      // Turn on all debug lines (table, cell, and widget).
    table.debugTable(); // Turn on only table lines.

Adding cells 增加单元格

Widgets通过add方法来加入到表格(对于已经有add方法的UI toolkits,那么将使用addcell方法)。这个方法将在此行中增加1个单元格。如果要增加下一行,则调用row方法。

    table.add(nameLabel);    // Row 0, column 0.
    table.add(nameText);     // Row 0, column 1. 
    table.row();             // Move to next row.
    table.add(addressLabel); // Row 1, column 0.
    table.add(addressText);  // Row 1, column 1.

add方法返回一个Cell,Cell有一些属性可以控制布局。Cell的每个方法的返回值都是Cell,允许链式调用。

    table.add(nameText).padLeft(10).width(100); // Sets left padding and width on the new cell.

Logical table 逻辑表

这些Cells组成了一个逻辑表,但是逻辑表的大小和table的尺寸是不一样的。

image.png

外面的蓝色矩形展示了table widget的尺寸。里面的蓝色矩形展示了逻辑表的尺寸,且默认居中对齐。对齐方式可以通过table的函数去设置。table函数反馈值为table,所以也可以像cell的方法一样进行链式调用。

    table.right().bottom();
image.png

Cell properties 单元格属性

Expand 扩展

为了使得逻辑表占据table的全部,TableLayber需要被告知那些cells会占用到额外的空间。

    table.add(nameLabel).expandX(); // Column 0 receives all extra horizontal space.
    table.add(nameText).width(100);
    table.row();
    table.add(addressLabel);
    table.add(addressText).width(100);
image.png

红线表示单元格边界,绿线表示widget的边界。注意左边列占据了X轴上横向空间。只需要有1个单元格被扩展,就可以占用整行或者整列的额外空间。如果多列被扩展,那么额外的空间就会均匀分布。

    table.add(nameLabel).expandX();           // Receives extra horizontal space.
    table.add(nameText).width(100).expandX(); // Also receives extra horizontal space.
    table.row();
    table.add(addressLabel);
    table.add(addressText).width(100);
image.png

见下图: Expand在Y轴同样适用,相应函数是expandYexpand方法则是在X和Y轴上都进行扩展。

    table.add(nameLabel).expand();     // Receives all extra horizontal and vertical space.
    table.add(nameText).width(100);
    table.row();
    table.add(addressLabel);
    table.add(addressText).width(100);
image.png

Alignment 对齐

与对齐逻辑表类似,widget在单元格里面也能做对齐。

    table.add(nameLabel).expand().bottom().right(); // Aligned bottom right.
    table.add(nameText).width(100).top();           // Aligned top.
    table.row();
    table.add(addressLabel);
    table.add(addressText).width(100);
image.png

Fill 填充

fill方法使得widget的尺寸调整到单元格的尺寸。同expand类似,有fillXfillY两种方法。

    table.add(nameLabel).expand().bottom().fillX(); // Sized to cell horizontally.
    table.add(nameText).width(100).top();
    table.row();
    table.add(addressLabel);
    table.add(addressText).width(100);
image.png

请注意,红色单元格线是在绿色小部件行的顶部绘制的。

Widget size Widget的尺寸

默认情况下,attempt将widgets的尺寸调整到它们的preferred size。如果widget不能适配,它们的尺寸将被调整到preferred sizeminimum size之间,具有较大首选尺寸的小部件,将获得更多空间。
如果widgets的minimum size都不能使用,那么布局被破坏,widgets可能重叠。 “fill”方法不会使widgets大于widgets的最大尺寸。

不应将Widgets改为preferredminimum或'maximum'。 相反,这些size可以在cell上进行设置,并将用来代替widgets的size。

    table.add(nameLabel);
    table.add(nameText).minWidth(100);     // Sets min width.
    table.row();
    table.add(addressLabel);
    table.add(addressText).prefWidth(999); // Sets pref width.
image.png

这里的“prefWidth”是999,比table还是大,因此它的大小将自动调整`。

width 方法可以快捷的设置 minWidth, prefWidth, 和 maxWidth为相同的值. height 方法可以快捷的设置 minHeight, prefHeight, 和 maxHeight为相同的值. size 方法需要widthheight,且设置所有6个属性.

Padding 填充

padding是指单元格边缘的额外空间。

    table.add(nameLabel);
    table.add(nameText).width(100).padBottom(10); // Sets bottom padding.
    table.row();
    table.add(addressLabel);
    table.add(addressText).width(100).pad(10);    // Sets top, left, bottom, right padding.

image.png

请注意:单元格之间的padding,所以文本字段之间有20个像素。 调试线不一定显示paddning来自哪个单元格,因为它对于表格的布局并不重要。
填充也可以应用到table的边缘。

    table.pad(10);

Spacing

和padding类似,spacing是cell边的额外空间。但是cells之间的spacing不会联合,相反,较大的一个spacing会被使用。另外,spacing不适用于table. spacing使得cells之间的一致的空间变得容易。

    table.add(nameLabel);
    table.add(nameText).width(100).spaceBottom(10); // Sets bottom spacing.
    table.row();
    table.add(addressLabel);
    table.add(addressText).width(100).space(10);    // Sets top, left, bottom, right spacing.
image.png

注意:cells之间的spacing不会融合,所有在text fildes之间有10 pixels. 另外注意在text field的低部没有spcing,因为spacing不适用于table的边界。

Colspan

一个cell可以span多列(就是合并)。

    table.add(nameLabel);
    table.add(nameText).width(100).spaceBottom(10);
    table.row();
    table.add(addressLabel).colspan(2);             // Spans 2 columns.
image.png

注意: 不能合并多个行。但是可以用嵌套表格达到此目的。

Uniform 统一

单元格设置uniform后,单元格的尺寸都变成统一的。
Cells with uniform set to true will be the same size.

    table.add(nameLabel).uniform();           // These two cells will have
    table.add(nameText).width(100).uniform(); // the same width and height.
    table.row();
    table.add(addressLabel);
    table.add(addressText).width(100);
image.png

Defaults 默认

Cell defaults 单元格默认

一般来说,单元格设计时一般采用相同的属性,所有给所有单元设置一个默认的属性会大大减少布局的工作量。table的defaults方法返回一个单元格,这个单元格的属性将被应用到所有的单元格。

    table.defaults().width(100); // Sets defaults for all cells.
    table.add(nameLabel);
    table.add(nameText);
    table.row();
    table.add(addressLabel);
    table.add(addressText);
image.png

Column defaults 列默认

table的columnDefaults方法返回一个单元格,这个单元格的属性将应用于此单元格所在的列的所有单元格。通过方法设置的属性将覆盖单元格的默认属性。列的索引从0开始。

    table.columnDefaults(1).width(150); // Sets defaults for cells in column 0.
    table.add(nameLabel);
    table.add(nameText);
    table.row();
    table.add(addressLabel);
    table.add(addressText);
image.png

Row defaults 行默认

当row方法调用时,会返回一个单元格,这个单元格的属性将被应用到其所在行的所有单元格。通过此方法设置的属性将会覆盖单元格的默认属性和列的默认属性。row方法在增加单元格之前就可以调用,这就使得第一行就可以用默认的属性。

    table.row().height(50);  // Set cell defaults for row 0.
    table.add(nameLabel);
    table.add(nameText);
    table.row().height(100); // Set cell defaults for row 1.
    table.add(addressLabel);
    table.add(addressText);
image.png

Stacks 堆栈

stack widget是一种特殊类型的容器,它将每个child设置为stack的大小。当需要将widgets堆叠在一起时,这非常有用。 添加到stack的第一个widget绘制在底部,添加的最后一个widget绘制在顶部。

Similar libraries

A few Java, table-based layout managers:

GridBagLayout can handle complex table-based layouts, but does so via a clunky API.

TableLayout (the other one) uses 2D arrays of percentages, sizes, and flags to describe the table and how it should be sized. This approach has the same problems as GridBagLayout.

PageLayout uses a concise Java API to describe the table.

PnutsLayout (webpage no longer available) was written by Toyokazu Tomatsu as part of Pnuts. TableLayout was originally inspired by PnutsLayout.

UIHierarchy was also inspired by PnutsLayout. It is interesting because it is not actually a layout manager, instead it uses a combination of method chaining and constraint strings to more cleanly create UI hierarchies and configure layout parameters.

RiverLayout uses tags in constraint strings.

FormLayout is similar to RiverLayout, but more sophisticated.

MIGLayout is even more sophisticated than FormLayout. It attempts to support many kinds of layouts beyond tables and has a somewhat bloated number of features. It has a complex constraint language. It can layout using a grid, border, absolute, etc.

DesignGridLayout uses canonical grids. For the most part, widgets are simply added and the ideal table is determined automatically. This cuts down the needed Java code to a minimum and enforces UI guidelines. The downside is that DesignGridLayout does not handle arbitrary table layouts. If a UI problem can be handled using a canonical grid, DesignGridLayout is the most elegant solution. If you want to deviate from a canonical grid, you have no recourse.

Please feel free to submit additional libraries to be included in this section or suggest better descriptions.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351