Saltar al contenido
CrossFly es 100% open sourceSíguenos en GitHub
CrossFlyCrossFly
Empezar
Todos los ejemplos
RecetasNavegación90 líneas · 1 archivos

Floating action button

It floats over the content, so leave room at the bottom of the list — bottomInset is what stops it covering the last row nobody can then scroll past.

Qué muestra esto

The floating action button, and the rule that keeps it useful.

A FAB is a claim: this is the thing you came here to do. One per screen, and it must be the same verb the screen's title implies — on a list of orders, "new order". A FAB that opens a menu of six unrelated actions has stopped being a claim and become a second navigation bar, in the corner, that nobody looks in.

ActionButtonMenu exists for the case where the main action has two or three near relatives. Past that, the answer is a screen.

Ejecutarlo en tu máquina

Cada ejemplo es una Window normal, así que el lanzador solo necesita su nombre.

gradlew lwjgl3:run --args="classname dev.cf.recipe.R24Fab"
Editarlo

Java se compila antes de ejecutarse, así que el navegador no puede reconstruir una edición por su cuenta: el código que ves aquí se convirtió en JavaScript con TeaVM antes de publicarse. Copia el archivo a un proyecto y funciona sin cambios en las cuatro plataformas; el comando de arriba es toda la preparación.

Ejecutándose aquíCrossFly 0.1.32
Iniciando la aplicación…

Compilado a JavaScript por TeaVM: es el mismo código, no un vídeo de él. · Todos los ejemplos

Qué usa

Tipos del framework que toca este ejemplo. Los enlazados tienen página de referencia.

ActionButtonMenuCardComponentGapGridLayoutLabelRelativeScreenStylesVerticalLayoutWidgets

El código

Completo, sin recortes. Es el archivo, no un fragmento.

Crudo
dev/cf/recipe/R24Fab.java
package dev.cf.recipe;

import dev.cf.Tones;

import dev.crossfly.ui.*;
import dev.crossfly.ui.color.*;
import dev.crossfly.ui.graphics.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;

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

/**
 * The floating action button, and the rule that keeps it useful.
 *
 * <p>A FAB is a claim: <b>this is the thing you came here to do</b>. One per screen, and it must be
 * the same verb the screen's title implies — on a list of orders, "new order". A FAB that opens a
 * menu of six unrelated actions has stopped being a claim and become a second navigation bar, in
 * the corner, that nobody looks in.</p>
 *
 * <p>{@link ActionButtonMenu} exists for the case where the main action has two or three near
 * relatives. Past that, the answer is a screen.</p>
 */
public class R24Fab extends Recipe
{
   private Label last;

   public String title()
   {
      return "Floating action button";
   }

   public String note()
   {
      return "It floats over the content, so leave room at the bottom of the list — bottomInset is"
         + " what stops it covering the last row nobody can then scroll past.";
   }

   public void build(Component body) throws Exception
   {
      last = label("Nothing chosen yet.", 1.2f, true, Tones.accent(), Position.START);
      body.add(LAY_AUTO, outgap(last, 0, 0, 0, .8f));

      for (int i = 1; i <= 8; i++)
      {
         Card c = new Card();
         c.setLayout(new GridLayout(Position.START, Position.CENTER));
         c.getStyle()
            .outgap(Gap.ofFont(0, 0, 0, .5f));
         Component t = new Component();
         t.setLayout(new VerticalLayout(Position.START, Position.START));
         t.add(LAY_AUTO, label("Order " + (4180 + i), 1.2f, true, Styles.textColor,
            Position.START));
         t.add(LAY_AUTO, label("Placed this week", 1f, false, Styles.captionColor,
            Position.START));
         c.add(0f, 1f, Tones.tile(0xE8CC, Tones.cycle(i)), outgap(t, .6f, 0, 0, 0));
         body.add(LAY_AUTO, c);
      }

      ActionButtonMenu fab = new ActionButtonMenu(Styles.primaryColor.color(),
         Styles.backColor.color());
      // Two or three near relatives of the main action. Each says what it DOES, not what it is.
      fab.item(0xE8CC, Styles.primaryColor, "New order", () -> chose("New order"));
      fab.item(0xE7FD, secondary(), "New customer", () -> chose("New customer"));
      fab.item(0xE2C3, tertiary(), "Import a file", () -> chose("Import a file"));
      // Room for the bottom navigation, if there is one. Measured in font units like everything.
      fab.bottomInset(1f);
      fab.testTag("recipe.fab");
      // The FAB is added to the WINDOW, not to the scrolling body: it floats over the content and
      // must not scroll away with it.
      //
      // Two details, and getting either wrong empties the page. It covers the WHOLE window on
      // purpose: the widget dims what is behind it and catches the tap that closes the menu
      // anywhere outside the items, so it is only correct at full size, and since 09/09 it
      // reclaims the parent rect itself if the host hands it less. And it is added WITHOUT a
      // layout weight, so the vertical flow never reserves height for it. As a LAY_AUTO sibling of
      // the LAY_FILL content area it takes the window height for itself and the page below renders
      // EMPTY — which is exactly what happened, and what Test58 caught.
      fab.setRelativeBounds(Relative.START, Relative.START, Relative.FULL, Relative.FULL);
      addFloating(fab);
   }

   private void chose(String what)
   {
      last.setText("Chose: " + what);
      last.setValidLayout(false);
      Screen.repaint();
   }
}
Para una IA

Versiones de esta página legibles por máquina, para que un modelo lea el estante en vez de adivinar la API.

Este ejemplo, en JSONEste ejemplo, en Markdown
AnteriorPainting your ownSiguienteA map with pins