本页面由葡萄牙语机器翻译,可能存在错误。葡萄牙语版本为准。
ListView
ListView 是一个可滚动的文本项选择列表,可随时嵌入任意容器。每一项都会变成一个可点击的“卡片”。选择模式在构造函数中通过 ItemType 固定:SINGLE(点击即选择并确认)或 MULTIPLE(复选框 + “确认”按钮)。
与 VirtualListView 不同,ListView 为每一项创建一个组件(不回收)—— 适合小/中型列表(数十项),而不适合数千行。
🟡 · 包:
dev.crossfly.ui· 继承自:Component· 样式:ListViewStyle(项/表头/按钮)+WindowStyle(背景,通过selectionWindowStyle())
何时使用
- 屏幕内嵌入的选择器(选项菜单、筛选器、类别选择)。
- 数十个文本项,且无需滚动的精确高度很有用(
computeIdealHeight)。 - 需要显式确认的多选(
MULTIPLE)。
何时不要使用
- 大型列表(数百/数千项)→ 使用会回收组件的
VirtualListView。 - 模态弹出选择 → 使用
ListViewWindow,它将ListView包裹在Window中。 - 带图片/多字段的丰富行 → 使用
itemFactory(...)或用列表项手动构建列表。
外观
居中文本卡片的垂直列(column),带可选表头(标题 + 返回图标),在 MULTIPLE 模式下底部还有一个“确认”按钮。在 SINGLE 模式下每个卡片是 LabelItem;在 MULTIPLE 模式下是 CheckLabelItem(复选框 + 标签)。
完整示例(复制、粘贴并运行)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
/** 可执行的主界面。将 launcher 指向此类(classname)并运行:gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
ListView list = new ListView(new String[]{"Um", "Dois", "Três"}, ListView.ItemType.SINGLE)
.showHeader(false);
list.onConfirm(e -> System.out.println("Escolhido: " + list.getSelectedText()));
add(LAY_FILL, list); // 列表使用 LAY_FILL(占满高度)
}
}
下面的片段只展示核心部分(放在
onShow()里的内容)。要运行它们,请放入上面的MainWindow骨架中。
基本用法
// SINGLE,无表头,自动高度(不滚动)
ListView list = new ListView(new String[]{"Um", "Dois", "Três"}, ListView.ItemType.SINGLE)
.showHeader(false);
list.onConfirm(e -> System.out.println("Escolhido: " + list.getSelectedText()));
contents.add(.95f, list);
构造函数
| 构造函数 | 描述 |
|---|---|
ListView(String[] items, ItemType itemType) |
无标题列表 |
ListView(String title, String[] items, ItemType itemType) |
表头带标题的列表 |
ItemType(定义于 UIConstants):SINGLE 或 MULTIPLE。构造之后该模式不可变。
属性与自定义
| 属性 / 方法 | 类型 | 默认值 | 作用 |
|---|---|---|---|
addItem(String) |
ListView |
— | 添加一项(惰性重建;忽略 null) |
addItems(String...) |
ListView |
— | 添加多项(仅一次失效) |
showHeader(boolean) |
ListView |
true |
显示/隐藏表头(标题 + 返回) |
title(String) |
ListView |
null |
设置标题 |
confirmText(String) |
ListView |
"Confirmar" |
按钮文本(仅 MULTIPLE) |
itemStyle(ComponentStyle) |
ListView |
主题 | 覆盖所有项的样式 |
confirmButtonStyle(ComponentStyle) |
ListView |
主题 | 确认按钮的样式 |
headerStyle(LabelStyle) |
ListView |
主题 | 表头样式 |
itemFactory(ItemFactory) |
ListView |
null |
自定义项工厂(接收 text、index) |
closeAction(Runnable) |
ListView |
null |
关闭动作(ListViewWindow 将其指向 this::hide) |
computeIdealHeight(int width) |
int |
— | 无滚动的精确高度,若存在 itemFactory 则返回 -1 |
选择查询
getSelectedCount()、getSelectedIndex()、getSelectedText()、getSelectedIndices()、getSelectedTexts()、isSelected(int)、getSelectionState()(boolean[])。
回调与事件
| 回调 | 触发时机 |
|---|---|
onConfirm(Component.Action) |
SINGLE:点击某项时。MULTIPLE:点击“确认”时 |
在 SINGLE 模式下,点击会清除之前的选择、标记该索引、触发 onConfirm 并调用 close()。在 MULTIPLE 模式下,点击会切换该项的复选框;确认由按钮发出。
状态
- SINGLE —— 一次只标记一项;点击即确认并关闭。
- MULTIPLE —— 可标记多项;即使在确认前也可通过
getSelectionState()查询状态。 - 表头和底部按钮是可选的(取决于
showHeader/title和ItemType)。
带自动高度的 MULTIPLE
ListView multi = new ListView(new String[]{"Vermelho", "Verde", "Azul"},
ListView.ItemType.MULTIPLE)
.showHeader(false)
.confirmText("Aplicar");
multi.getStyle().autoHeight(Relative.ofFont(9f));
multi.onConfirm(e -> {
for (String t : multi.getSelectedTexts())
System.out.println("marcado: " + t);
});
contents.add(.95f, multi);
使用 itemFactory 的自定义行
ListView list = new ListView(labels, ListView.ItemType.SINGLE).showHeader(false);
list.itemFactory((text, index) -> {
Component row = new Component();
row.style(Styles.component().pressable().ingap(Gap.ofFont(.3f)));
row.setLayout(new GridLayout(Position.START, Position.CENTER));
row.add(new Label(text));
return row;
});
list.onConfirm(e -> System.out.println("idx = " + list.getSelectedIndex()));
contents.add(.95f, list);
最佳实践
- 优先使用
addItems(...)而不是多次addItem(...)—— 只触发一次布局失效。 - 当你想要一个无滚动且高度精确的列表时使用
computeIdealHeight(width)(若存在itemFactory则返回-1,因为自定义项无法被通用地度量)。 - 项的重建是惰性的(发生在下一次布局时),包括宽度变化时。
常见错误
- 将
ListView用于数千项 —— 它不回收;内存呈线性增长。请迁移到VirtualListView。 - 期望
MULTIPLE每次点击都触发onConfirm—— 在MULTIPLE模式下回调仅在按钮“确认”时触发;用getSelectionState()来响应每次标记。 - 假设存在无项的构造函数 —— 构造函数要求提供
items和ItemType;请以new String[]{}起步并使用addItems(...)。
另请参阅
- 领域指南:
ui/· 实用配方:cookbook/ - 相关组件:
ListViewWindow·VirtualListView· 列表项(LabelItem/CheckLabelItem)