本页面由葡萄牙语机器翻译,可能存在错误。葡萄牙语版本为准。
窗口栈
理解这个模型可以避免大多数导航相关的 bug。
模型(LIFO)
EventsProcessor 维护一个 Window 的栈。栈顶的窗口是接收事件并绘制在最上层的那个。下方的窗口仍然存活(不会被销毁),只是被遮盖。
┌─────────────┐ ← topo: recebe toque/teclado, é pintada
│ TelaDetalhe │
├─────────────┤
│ TelaLista │ ← coberta, viva
├─────────────┤
│ TelaHome │ ← base
└─────────────┘
show()→ push:在EventsProcessor中注册,调用onShow()。hide()→ pop:注销,调用onRemove();下方的窗口回到栈顶。
每个窗口的生命周期
| 方法 | 何时 | 用途 |
|---|---|---|
onShow() |
进入栈时 | 构建 UI(务必调用 super.onShow()) |
onReposition() |
调整尺寸/旋转时 | 重新组织/重新计算布局 |
onRemove() |
离开栈时 | 释放计时器、光标、监听器 |
全屏与弹窗
同一个 Window 类既可以是全屏也可以是弹窗——取决于 WindowStyle
(widthRatio/heightRatio < 1 ⇒ 弹窗;参见 对话框与模态框)。弹窗覆盖在前一个屏幕之上(后者仍然在后方可见)。
返回按钮(Android)与点击外部
- 物理返回键被应用捕获,默认对栈顶窗口执行
hide()。 - 在
canHide = true的弹窗中,点击外部会关闭弹窗。 - 要阻止退出(例如:放弃确认),请在允许
hide()发生之前处理该意图。
完整示例(复制、粘贴并运行)
演示栈的 push/pop 以及在被压入窗口的 WindowStyle 中配置的进入过渡动画。
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;
/** 可执行的主界面。将 launcher 指向此类(classname)并运行:gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
add(LAY_AUTO, new Label("Base da pilha (MainWindow)"));
Button empilhar = new Button("Empilhar tela (push)");
empilhar.onAction(c -> new TelaEmpilhada().show()); // push:进入栈顶
add(LAY_AUTO, empilhar);
}
}
/** 带转场进入栈顶、用 hide()(pop)返回的屏幕。 */
class TelaEmpilhada extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
// 此窗口的进入/退出转场(下方那个仍在后面存活)
getStyle().transition(UIConstants.Transition.SLIDE_LEFT);
setLayout(new VerticalLayout());
add(LAY_AUTO, new Label("Topo da pilha — a tela de baixo continua viva"));
Button voltar = new Button("Voltar (pop)");
voltar.onAction(c -> hide()); // pop:出栈,下方那个回到栈顶
add(LAY_AUTO, voltar);
}
}
下面的片段只展示核心部分(放进
onShow()里的内容)。要运行它们,请将其放入上面的MainWindow骨架中。
过渡动画
进入/退出动画来自 WindowStyle.transition(UIConstants.Transition):NONE
(默认)、FADE、SLIDE_LEFT/RIGHT/UP/DOWN、SCALE、SCALE_DOWN。选择器默认使用 FADE。
getStyle().transition = UIConstants.Transition.SLIDE_LEFT; // 打开时滑入
最佳实践
- 不要在超出必要的时间内持有下方窗口的引用——让它们在
hide()时被回收。 - 每个
show()都应有对应的hide()(避免堆叠无法返回的屏幕)。
常见错误
- 在
onReposition()中重建 UI 却不保留状态(滚动、选中)。 - 假设打开另一个窗口时下方的窗口已被销毁——它仍然存活。
另请参阅
这个页面有帮助吗?感谢你的反馈!