跳到内容
CrossFly 是 100% 开源在 GitHub 关注我们
CrossFlyCrossFly
开始使用
全部示例
配方导航布局65 行 · 1 个文件

Bottom nav that becomes a rail

One flag — tabsAtBottom — and the strip is a bottom bar on a phone and a rail on a tablet. Resize the window to see it happen.

它展示了什么

Bottom navigation that turns into a rail on a wide screen, with no width check anywhere.

Resize the window and watch the strip move to the left edge and grow labels. Nothing below asks how wide the screen is, listens for an orientation change, or holds a phone/tablet flag — that behaviour is the TabBar's, and an app that reimplements it gets a second, slightly different answer to the same question.

在你的机器上运行

每个示例都是普通的 Window,启动器只需要它的名字。

gradlew lwjgl3:run --args="classname dev.cf.recipe.R12Nav"
修改它

Java 是提前编译的,浏览器无法自行重建你的修改 —— 这里的代码在发布前已由 TeaVM 转成 JavaScript。把文件复制到项目里,它在四个平台上原样运行;上面那条命令就是全部准备工作。

正在此处运行CrossFly 0.1.32
正在启动应用…

由 TeaVM 编译为 JavaScript —— 是同一份代码,不是录像。 · 全部示例

它用到了什么

本示例触及的框架类型。带链接的有参考页。

ComponentMaterialIconSkinStylesTabBarVerticalLayoutWidgets

源码

完整无删减。这就是那个文件,不是片段。

原始
dev/cf/recipe/R12Nav.java
package dev.cf.recipe;

import dev.crossfly.ui.*;
import dev.crossfly.ui.graphics.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.skin.Skin;
import dev.crossfly.ui.style.*;

import static dev.crossfly.ui.Widgets.*;

/**
 * Bottom navigation that turns into a rail on a wide screen, with no width check anywhere.
 *
 * <p>Resize the window and watch the strip move to the left edge and grow labels. Nothing below
 * asks how wide the screen is, listens for an orientation change, or holds a phone/tablet flag —
 * that behaviour is the {@link TabBar}'s, and an app that reimplements it gets a second, slightly
 * different answer to the same question.</p>
 */
public class R12Nav extends Recipe
{
   private static final int IC_HOME = 0xE88A, IC_LIST = 0xE8EF, IC_CHART = 0xE6E1, IC_MORE = 0xE5D2;

   public String title()
   {
      return "Bottom nav that becomes a rail";
   }

   public String note()
   {
      return "One flag — tabsAtBottom — and the strip is a bottom bar on a phone and a rail on a"
         + " tablet. Resize the window to see it happen.";
   }

   public void build(Component body) throws Exception
   {
      TabBar tabs = new TabBar(new TabBar.Tab("Home", MaterialIcon.of(IC_HOME, 1.5f)),
         new TabBar.Tab("Items", MaterialIcon.of(IC_LIST, 1.5f)),
         new TabBar.Tab("Reports", MaterialIcon.of(IC_CHART, 1.5f)),
         // railHidden: a "More" tab exists to reach what does not fit on a phone. On a rail
         // everything already fits, so the tab that only reopens the same list is dropped.
         new TabBar.Tab("More", MaterialIcon.of(IC_MORE, 1.5f)).railHidden(true));

      tabs.setContent(page("Home"), page("Items"), page("Reports"), page("More"));
      // A badge is a count the user has not dealt with. Null clears it — never show a zero.
      tabs.badge(1, "3");
      tabs.style(Skin.get()
         .tabBar()
         .copy()
         .tabsAtBottom(true));
      tabs.testTag("recipe.nav");
      body.add(LAY_FILL, tabs);
   }

   /** Each destination is a Component the bar keeps alive — not a Window. See dev.cf.app.crud. */
   private Component page(String name) throws Exception
   {
      Component c = new Component();
      c.setLayout(new VerticalLayout(Position.CENTER, Position.CENTER));
      c.add(LAY_AUTO, label(name, 1.5f, true, Styles.textColor, Position.CENTER));
      c.add(LAY_AUTO, outgap(label("Kept alive across switches, so coming back finds it where you"
         + " left it.", 1f, false, Styles.captionColor, Position.CENTER), 1f, .4f, 1f, 0));
      return c;
   }
}
给 AI 助手

本页的机器可读版本,让模型直接读取示例集,而不是猜测 API。

本示例(JSON)本示例(Markdown)
上一个Telling the user something下一个Waiting