跳到内容
CrossFly 是 100% 开源在 GitHub 关注我们
CrossFlyCrossFly
开始使用

本页面由葡萄牙语机器翻译,可能存在错误。葡萄牙语版本为准。

窗口栈

理解这个模型可以避免大多数导航相关的 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 却不保留状态(滚动、选中)。
  • 假设打开另一个窗口时下方的窗口已被销毁——它仍然存活。

另请参阅

这个页面有帮助吗?