Pular para o conteúdo
CrossFly é 100% open sourceSiga no GitHub
CrossFlyCrossFly
Começar
Todos os exemplos
ReceitasImagens97 linhas · 1 arquivos

Images

Decode once, keep the Image, reuse it. Loading inside onPaint or inside a list's bind step is what makes scrolling stutter where the pictures are.

O que isto mostra

Images, and the two questions that come up before the picture does.

How does it fill its box? ImageSize is the whole answer, and picking wrong is the most visible mistake in an app: a portrait photo stretched into a landscape tile is noticed by everybody and reported by nobody, because it looks like a bad photo rather than a bug. Cropping to fill is almost always right for a photo; fitting inside is almost always right for a logo.

Where does the image come from? An app's own assets, or bytes it was handed — a camera capture, a database blob, a download. Both end up as an Image, and neither belongs in onPaint: decoding is expensive, and doing it per frame is the classic reason a list stutters exactly where the pictures are.

Drawn here rather than loaded from a file, so the recipe carries no asset of its own — but a generated image and a decoded one behave identically from this point on.

Rodar na sua máquina

Todo exemplo é uma Window comum, então o launcher só precisa do nome dela.

gradlew lwjgl3:run --args="classname dev.cf.recipe.R26Images"
Editar o exemplo

Java é compilado antes de rodar, então o navegador não consegue reconstruir uma edição sozinho — o código que você vê aqui virou JavaScript pelo TeaVM antes de ser publicado. Copie o arquivo para um projeto e ele roda sem mudanças nas quatro plataformas; o comando acima é toda a preparação.

Rodando aquiCrossFly 0.1.32
Iniciando o aplicativo…

Compilado para JavaScript pelo TeaVM — é o mesmo código, não um vídeo dele. · Todos os exemplos

O que ele usa

Tipos do framework que este exemplo toca. Os que têm link têm página de referência.

CardColorUtilsComponentGapImageImageViewRelativeStylesWidgets

O código

Completo, sem cortes. É o arquivo, não um trecho dele.

Bruto
dev/cf/recipe/R26Images.java
package dev.cf.recipe;

import dev.crossfly.ui.*;
import dev.crossfly.ui.color.ColorUtils;
import dev.crossfly.ui.graphics.*;
import dev.crossfly.ui.image.Image;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.style.*;

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

/**
 * Images, and the two questions that come up before the picture does.
 *
 * <p><b>How does it fill its box?</b> {@link ImageView.ImageSize} is the whole answer, and picking
 * wrong is the most visible mistake in an app: a portrait photo stretched into a landscape tile is
 * noticed by everybody and reported by nobody, because it looks like a bad photo rather than a bug.
 * Cropping to fill is almost always right for a photo; fitting inside is almost always right for a
 * logo.</p>
 *
 * <p><b>Where does the image come from?</b> An app's own assets, or bytes it was handed — a camera
 * capture, a database blob, a download. Both end up as an {@link Image}, and neither belongs in
 * {@code onPaint}: decoding is expensive, and doing it per frame is the classic reason a list
 * stutters exactly where the pictures are.</p>
 *
 * <p>Drawn here rather than loaded from a file, so the recipe carries no asset of its own — but a
 * generated image and a decoded one behave identically from this point on.</p>
 */
public class R26Images extends Recipe
{
   public String title()
   {
      return "Images";
   }

   public String note()
   {
      return "Decode once, keep the Image, reuse it. Loading inside onPaint or inside a list's bind"
         + " step is what makes scrolling stutter where the pictures are.";
   }

   public void build(Component body) throws Exception
   {
      // Made once, held, reused by all three views below — the point of the recipe.
      Image swatch = gradient(240, 160);

      // The names repay one careful reading, because two of them are the opposite of what they
      // sound like. RATIO fits the whole picture INSIDE the box; FIT scales until it COVERS the
      // box and crops what hangs over. Guessing between those two is how a portrait photo ends up
      // letterboxed in a tile that had room to crop it properly.
      show(body, "RATIO — the whole picture, inside the box", swatch, ImageSize.RATIO);
      show(body, "FIT — covers the box, crops the overflow", swatch, ImageSize.FIT);
      show(body, "STRETCH — fills by distorting. Almost never right", swatch, ImageSize.STRETCH);
   }

   private void show(Component body, String caption, Image img, ImageSize size)
      throws Exception
   {
      Card c = new Card();
      c.add(LAY_AUTO, label(caption, 1f, true, Styles.textColor, Position.START));
      ImageView v = new ImageView(img, size);
      v.getStyle()
         .autoHeight(Relative.ofFont(6f));
      c.add(LAY_AUTO, outgap(v, 0, .4f, 0, 0));
      c.getStyle()
         .outgap(Gap.ofFont(0, 0, 0, .6f));
      body.add(LAY_AUTO, c);
   }

   /**
    * Builds an image in memory from the theme's own colours.
    *
    * <p>An {@code Image} is pixels; where they came from stops mattering the moment you have one.
    * The same object could have arrived from {@code PhotoPicker}, from a SQLite blob or from a
    * download, and every line after this one would be unchanged.</p>
    */
   private static Image gradient(int w, int h) throws Exception
   {
      Image img = Image.createSurface(w, h);
      int[] px = new int[w * h];
      int from = Styles.primaryColor.color(), to = tertiary().color();
      for (int y = 0; y < h; y++)
      {
         int rowColor = ColorUtils.lerpColor(from, to, y / (float) h);
         for (int x = 0; x < w; x++)
            // Diagonal bands, so cropping and stretching are both obvious at a glance.
            px[y * w + x] = ((x + y) / 18) % 2 == 0 ? rowColor
               : ColorUtils.lerpColor(rowColor, Styles.backColor.color(), .35f);
      }
      img.setPixels(px);
      // Pixels written, texture stale: applyChanges is what pushes them to the GPU. Forgetting it
      // gives you an image that is correct in memory and blank on screen.
      img.applyChanges();
      return img;
   }
}
Para uma IA

Versões desta página legíveis por máquina, para um modelo ler a prateleira em vez de adivinhar a API.

Este exemplo, em JSONEste exemplo, em Markdown
AnteriorA map with pinsPróximoKeyboard and focus