# PhotoPicker

> Captura de foto ou vídeo pela câmera do dispositivo, devolvendo o caminho do arquivo gerado.

Source: https://crossfly.dev/pt/docs/ui/widgets/photopicker — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# PhotoPicker

`PhotoPicker` captura **foto** ou grava **vídeo** (com/sem áudio) usando a câmera do dispositivo, com efeitos (brilho/contraste/nitidez), troca de câmera e confirmação opcional. Segue o padrão dos pickers (ver [`Picker`](/docs/ui/widgets/picker)), mas o resultado é um **caminho de arquivo** — ou uma string de erro.

> 🔴 · **Pacote:** `dev.crossfly.ui.picker` · **Estende:** `Picker implements GdxCamera.Listener` · **Hardware:** câmera

## Quando usar
- Tirar uma foto ou gravar um vídeo dentro do app.

## Quando NÃO usar
- Ler código de barras/QR → use [`BarcodePicker`](/docs/ui/widgets/barcodepicker).

## Aparência
Preview de câmera em tela cheia (fundo preto, sem moldura) com botões circulares semitransparentes: Cancelar (X), Capturar/Gravar (central), Trocar câmera e Config/Pause. No modo foto com confirmação, uma tela confirmar/refazer.

## Exemplo completo (copiar, colar e rodar)
`PhotoPicker` é um overlay de câmera — para abri-lo, dispare-o a partir de um `Button`. O exemplo reutiliza o uso básico e mostra o caminho retornado (ou o erro) num `Label`.

```java
package com.exemplo;

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

/** Tela principal executável. Aponte o launcher (classname) e rode: 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);
   }
}
```

> Os trechos abaixo mostram **só o miolo** (o que vai dentro de `onShow()`). Para rodar, coloque-os no esqueleto `MainWindow` acima.

## Uso básico
```java
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);
});
```

## Construtores
| Construtor | Descrição |
|---|---|
| `PhotoPicker(Preview type)` | Modo: `Preview.PHOTO`, `Preview.MUTED_VIDEO` ou `Preview.AUDIO_VIDEO`. |

## Propriedades e personalização
| Campo | Tipo | Default | O que faz |
|---|---|---|---|
| `PhotoPicker.defaultJpegQuality` (estático) | `int` | 90 | Qualidade JPG ao salvar a foto. |
| `PhotoPicker.showConfirmation` (estático) | `boolean` | `true` | Tela confirmar/refazer no modo foto. |
| `videoQuality` | `Camera.AVQuality` | HIGH | Qualidade do vídeo. |
| `videoTimeLimit` | `int` (s) | 0 | Limite de gravação (0 = sem limite). |

## Callbacks e eventos
| Callback | Quando dispara |
|---|---|
| `show(onAnswer)` | ao fechar, entrega a `String` do caminho (ou `"ERROR: ..."`). |

## Resultado (importante)
`getAnswer()` retorna o **caminho** do arquivo (JPG da foto ou MP4 do vídeo). Em caso de erro de câmera, retorna a string `"ERROR: ..."`.

> ⚠️ **Sempre cheque `isError()` antes** de tratar o valor como caminho — `getAnswer()` mistura caminho e mensagem de erro.

## Estados
- `onAppPause`/`onAppResume` param/retomam a câmera; `onRemove` para tudo e limpa o listener.
- Erro de câmera → grava `answer = "ERROR: ..."` e fecha.

### Vídeo com áudio e limite de 30s
```java
PhotoPicker vp = new PhotoPicker(PhotoPicker.Preview.AUDIO_VIDEO);
vp.videoTimeLimit = 30;
vp.show(a -> Debug.log("MP4 em: " + a));
```

## Boas práticas
- **Cheque `isError()`** antes de abrir o arquivo retornado.
- Não reaproveite a mesma instância após `hide()` — os recursos de câmera são liberados no fechamento.

## Erros comuns
- **Tratar `answer` como caminho sem checar `isError()`** — pode ser `"ERROR: ..."`.
- **Assumir caminho portável** — o caminho de vídeo é fixo em `/sdcard/...` (Android).

## Veja também
- Guia da área: [`ui/`](/docs/ui) · Receitas: [`cookbook/`](/docs/cookbook)
- Base do padrão: [`Picker`](/docs/ui/widgets/picker)
- Componentes relacionados: [`BarcodePicker`](/docs/ui/widgets/barcodepicker)
