Skip to content
CrossFly is 100% open sourceFollow us on GitHub
CrossFlyCrossFly
Get started

This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.

PhotoPicker

PhotoPicker captures a photo or records a video (with/without audio) using the device camera, with effects (brightness/contrast/sharpness), camera switching and optional confirmation. It follows the picker pattern (see Picker), but the result is a file path — or an error string.

🔴 · Package: dev.crossfly.ui.picker · Extends: Picker implements GdxCamera.Listener · Hardware: camera

When to use

  • Take a photo or record a video inside the app.

When NOT to use

Appearance

Full-screen camera preview (black background, no frame) with semi-transparent circular buttons: Cancel (X), Capture/Record (center), Switch camera and Settings/Pause. In photo mode with confirmation, a confirm/retake screen.

Complete example (copy, paste and run)

PhotoPicker is a camera overlay — to open it, trigger it from a Button. The example reuses the basic usage and shows the returned path (or the error) in a Label.

package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
import dev.crossfly.ui.picker.*;

/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      Label saida = new Label("Nenhuma foto ainda");
      add(LAY_AUTO, saida);

      Button tirarFoto = new Button("Tirar foto")
         .onAction(c ->
         {
            PhotoPicker pp = new PhotoPicker(PhotoPicker.Preview.PHOTO);
            pp.show(answer ->
            {
               String caminho = (String) answer;
               if (pp.isError())
                  saida.setText("Falha na câmera: " + caminho);
               else
                  saida.setText("Foto salva em: " + caminho);
            });
         });
      add(LAY_AUTO, tirarFoto);
   }
}

The snippets below show only the core (what goes inside onShow()). To run them, place them in the MainWindow skeleton above.

Basic usage

PhotoPicker pp = new PhotoPicker(PhotoPicker.Preview.PHOTO);
pp.show(answer ->
{
   String caminho = (String) answer;
   if (pp.isError())
      new Alert("Falha na câmera", caminho, "OK").show();
   else
      Debug.log("Foto salva em: " + caminho);
});

Constructors

Constructor Description
PhotoPicker(Preview type) Mode: Preview.PHOTO, Preview.MUTED_VIDEO or Preview.AUDIO_VIDEO.

Properties and customization

Field Type Default What it does
PhotoPicker.defaultJpegQuality (static) int 90 JPG quality when saving the photo.
PhotoPicker.showConfirmation (static) boolean true Confirm/retake screen in photo mode.
videoQuality Camera.AVQuality HIGH Video quality.
videoTimeLimit int (s) 0 Recording limit (0 = no limit).

Callbacks and events

Callback When it fires
show(onAnswer) on closing, delivers the path String (or "ERROR: ...").

Result (important)

getAnswer() returns the file path (JPG for the photo or MP4 for the video). In case of a camera error, it returns the string "ERROR: ...".

⚠️ Always check isError() first before treating the value as a path — getAnswer() mixes path and error message.

States

  • onAppPause/onAppResume pause/resume the camera; onRemove stops everything and clears the listener.
  • Camera error → records answer = "ERROR: ..." and closes.

Video with audio and a 30 s limit

PhotoPicker vp = new PhotoPicker(PhotoPicker.Preview.AUDIO_VIDEO);
vp.videoTimeLimit = 30;
vp.show(a -> Debug.log("MP4 em: " + a));

Best practices

  • Check isError() before opening the returned file.
  • Do not reuse the same instance after hide() — the camera resources are released on close.

Common mistakes

  • Treating answer as a path without checking isError() — it may be "ERROR: ...".
  • Assuming a portable path — the video path is fixed at /sdcard/... (Android).

See also

Was this page helpful?