मुख्य सामग्री पर जाएँ
CrossFly 100% ओपन सोर्सGitHub पर फ़ॉलो करें
CrossFlyCrossFly
शुरू करें
सभी उदाहरण
रेसिपीथीम129 पंक्तियाँ · 1 फ़ाइलें

Brand and dark mode

One seed generates the whole palette, for both themes. Nothing below names a colour, which is why the switch needs no rebuild.

यह क्या दिखाता है

Declaring a brand: one seed, and everything else follows.

You do not pick colours in a CrossFly app. You declare one seed, and the framework derives the rest — primary and what reads on it, surfaces, containers, outlines, the tonal fill behind an active tab, both themes. Tap the swatches below: nothing on this screen is rebuilt, and every colour moves at once, because none of them was ever written down.

Skip this and your app is not "unstyled", it is grey — the skin's neutral palette is what you get when nobody declared anything, and it reads as a rendering bug rather than as a default. That is the first thing to check when a screen looks broken and nothing is broken.

Two calls, and the difference between them matters exactly once. setBrand restyles every open window; setBrandSilent does not, and exists for code running before there is anything to restyle — class initialisation, the line before the first window is shown.

अपनी मशीन पर चलाएँ

हर उदाहरण एक साधारण Window है, इसलिए लॉन्चर को सिर्फ़ उसका नाम चाहिए।

gradlew lwjgl3:run --args="classname dev.cf.recipe.R29Brand"
इसे बदलना

Java पहले से संकलित होता है, इसलिए ब्राउज़र आपके बदलाव को खुद दोबारा नहीं बना सकता — यहाँ दिखा कोड प्रकाशित होने से पहले TeaVM द्वारा JavaScript में बदला गया था। फ़ाइल को किसी प्रोजेक्ट में कॉपी कीजिए और वह चारों प्लेटफ़ॉर्म पर बिना बदलाव चलती है; ऊपर दी गई कमांड ही पूरी तैयारी है।

यहीं चल रहा हैCrossFly 0.1.32
ऐप शुरू हो रहा है…

TeaVM ने इसे JavaScript में संकलित किया — यह वही कोड है, उसका वीडियो नहीं। · सभी उदाहरण

यह क्या इस्तेमाल करता है

इस उदाहरण में छुए गए फ़्रेमवर्क टाइप। जिनमें लिंक है उनका संदर्भ पृष्ठ मौजूद है।

ButtonCardColorSchemeComponentGapHorizontalLayoutStylesSwitchTextFieldWidgets

सोर्स कोड

पूरा, बिना कटौती के। यह वही फ़ाइल है, उसका अंश नहीं।

कच्चा
dev/cf/recipe/R29Brand.java
package dev.cf.recipe;

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

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

/**
 * Declaring a brand: one seed, and everything else follows.
 *
 * <p>You do not pick colours in a CrossFly app. You declare one seed, and the framework derives the
 * rest — primary and what reads on it, surfaces, containers, outlines, the tonal fill behind an
 * active tab, both themes. Tap the swatches below: nothing on this screen is rebuilt, and every
 * colour moves at once, because none of them was ever written down.</p>
 *
 * <p><b>Skip this and your app is not "unstyled", it is grey</b> — the skin's neutral palette is
 * what you get when nobody declared anything, and it reads as a rendering bug rather than as a
 * default. That is the first thing to check when a screen looks broken and nothing is broken.</p>
 *
 * <p>Two calls, and the difference between them matters exactly once. {@code setBrand} restyles
 * every open window; {@code setBrandSilent} does not, and exists for code running before there is
 * anything to restyle — class initialisation, the line before the first window is shown.</p>
 */
public class R29Brand extends Recipe
{
   /** A few seeds. Any ARGB works: the palette is generated, not looked up. */
   private static final int[] SEED = { 0xFF1565C0, 0xFFE2622C, 0xFF2E7D32, 0xFF6A1B9A,
      0xFFB71C1C };
   private static final String[] SEED_NAME = { "Blue", "Orange", "Green", "Purple", "Red" };

   /** What was in force when this recipe opened, so it can be handed back. */
   private Integer previousBrand;
   private ColorScheme previousScheme;

   public String title()
   {
      return "Brand and dark mode";
   }

   public String note()
   {
      return "One seed generates the whole palette, for both themes. Nothing below names a colour,"
         + " which is why the switch needs no rebuild.";
   }

   public void build(Component body) throws Exception
   {
      remember();

      body.add(LAY_AUTO, outgap(label("THE SEED", 1f, true, Styles.captionColor, Position.START), 0,
         0, 0, .5f));

      Component swatches = new Component();
      swatches.setLayout(new HorizontalLayout(Position.START, Position.CENTER));
      for (int i = 0; i < SEED.length; i++)
      {
         final int seed = SEED[i];
         Button b = new Button(SEED_NAME[i]);
         b.getStyle()
            .backColor(seed)
            .textColor(0xFFFFFFFF)
            .outgap(Gap.ofFont(0, 0, .4f, 0));
         b.onAction(c -> Styles.setBrand(seed));
         swatches.add(LAY_AUTO, b);
      }
      body.add(LAY_AUTO, outgap(swatches, 0, 0, 0, 1f));

      Switch dark = new Switch("Dark mode");
      dark.checked(Styles.isDarkMode());
      // One call. Every PalColor token re-resolves in place and every window is restyled — no
      // screen tracks a flag of its own, and none rebuilds.
      dark.onAction(c -> Styles.setDarkMode(dark.isChecked()));
      body.add(LAY_AUTO, outgap(dark, 0, 0, 0, 1.2f));

      body.add(LAY_AUTO, outgap(label("WHAT FOLLOWS, WITHOUT BEING TOLD", 1f, true,
         Styles.captionColor, Position.START), 0, 0, 0, .5f));

      Card c = new Card();
      c.add(LAY_AUTO, label("A card on a surface", 1.2f, true, Styles.textColor, Position.START));
      c.add(LAY_AUTO, outgap(label("Caption text, the tone below the title.", 1f, false,
         Styles.captionColor, Position.START), 0, .2f, 0, .5f));
      c.add(LAY_AUTO, outgap(new TextField().caption("A field"), 0, 0, 0, .5f));
      c.add(LAY_AUTO, outgap(new Button("A button"), 0, 0, 0, .5f));
      Component chips = new Component();
      chips.setLayout(new HorizontalLayout(Position.START, Position.CENTER));
      chips.add(LAY_AUTO, outgap(toneBadge(Styles.primaryColor, "primary"), 0, 0, .4f, 0));
      chips.add(LAY_AUTO, outgap(toneBadge(secondary(), "secondary"), 0, 0, .4f, 0));
      chips.add(LAY_AUTO, toneBadge(tertiary(), "tertiary"));
      c.add(LAY_AUTO, chips);
      body.add(LAY_AUTO, c);
   }

   /**
    * Snapshots the palette, so leaving this recipe does not repaint the app it was opened from.
    *
    * <p>A <b>copy</b>, never the reference: {@link Styles} keeps one {@link ColorScheme} instance
    * for the life of the app and mutates its roles in place on every seed change — deliberately, so
    * that a {@code PalColor} captured into a style at build time keeps resolving. Save the
    * reference and you have saved the object that is about to be overwritten.</p>
    */
   private void remember()
   {
      previousBrand = Styles.hasBrand() ? Integer.valueOf(Styles.brand()) : null;
      ColorScheme live = Styles.colorScheme();
      if (live != null)
      {
         previousScheme = ColorScheme.fromSeed(SEED[0], live.isDark);
         previousScheme.copyFrom(live);
      }
   }

   @Override
   public void onRemove()
   {
      super.onRemove();
      if (previousBrand != null)
         Styles.setBrand(previousBrand.intValue());
      else
      {
         Styles.clearBrand();
         if (previousScheme != null)
            Styles.setColorScheme(previousScheme);
      }
   }
}
एआई सहायक के लिए

इस पृष्ठ के मशीन-पठनीय रूप, ताकि मॉडल API का अनुमान लगाने के बजाय उदाहरण पढ़ सके।

यह उदाहरण, JSON मेंयह उदाहरण, Markdown में
पिछलाWriting your own componentअगलाEmpty, loading and broken