# How to let the user pick a location on the map

> Open a map with a draggable pin and GPS for the user to confirm a coordinate (LatLon) via LocationPicker.

Source: https://crossfly.dev/docs/cookbook/device/escolher-local-no-mapa — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# How to let the user pick a location on the map

**Purpose.** Open a map screen (Google) with a **draggable pin** and GPS tracking, so the
user can confirm a position. The result is a `LatLon` delivered via callback.

## APIs used
- `LocationPicker(RunnableWith<LatLon> onCapture, double minPdop, boolean canDragPin, boolean highPrecision, boolean streetview)` — full constructor (it's the actual source signature).
  - `onCapture` — callback called with the confirmed `LatLon` (may be `null`).
  - `minPdop` — minimum acceptable PDOP; the confirm button stays hidden until the fix reaches that precision (on desktop it's always enabled).
  - `canDragPin` — `true` to allow dragging the pin to a custom position.
  - `highPrecision` — `true` for high-precision GPS.
  - `streetview` — `true` to enable street view on the map.
- `LatLon getAnswer()` — confirmed position, or `null` if cancelled.
- Configurable statics: `LocationPicker.defaultZoom`, `Instrucoes`, `GpsLocation`, `CustomLocation`, `Precision`, `Meters`.

> **Divergence vs. the request description.** `LocationPicker` does **not** use `show(onAnswer)` for the
> result: the coordinate arrives through the `RunnableWith<LatLon> onCapture` passed in the **constructor**
> (and it's also available in `getAnswer()`). `onCapture` is only called when the user **confirms** with a
> non-null position. Internally the picker runs its **own** `GPSThread` (inner class) and already
> dispatches the updates via `Component.onUI(...)`, so your callback runs on the paint thread.

## Complete example (copy, paste, and run)

```java
package com.exemplo;

import dev.crossfly.ui.*;                   // Window, Button, Label
import dev.crossfly.ui.layout.*;            // VerticalLayout
import dev.crossfly.ui.picker.*;            // LocationPicker
import dev.crossfly.map.*;                  // LatLon
import dev.crossfly.util.*;                 // RunnableWith

/** 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 resultado = new Label("");
      add(LAY_AUTO, resultado);

      Button acao = new Button("Escolher no mapa");
      acao.onAction(c ->
      {
         RunnableWith<LatLon> aoConfirmar = coord ->
         {
            // Already arrives on the paint thread (the picker uses Component.onUI internally)
            resultado.setText("Lat " + coord.lat + " / Lon " + coord.lon);
         };

         LocationPicker picker = new LocationPicker(
            aoConfirmar,   // callback with the confirmed LatLon
            30.0,          // minPdop: enables confirm when accuracy <= 30m
            true,          // canDragPin: user can drag the pin
            true,          // highPrecision
            false);        // streetview
         picker.show();
      });
      add(LAY_AUTO, acao);
   }
}
```

> The snippet below shows **only the core**. To run it, place it in the `MainWindow` skeleton above.

## Minimal snippet

```java
// verified at source: LocationPicker.java (constructor lines 129-141, onCapture/closeWith, getAnswer)
import dev.crossfly.ui.picker.*;           // LocationPicker
import dev.crossfly.map.*;                 // LatLon
import dev.crossfly.util.*;                // RunnableWith

RunnableWith<LatLon> aoConfirmar = coord -> {
   // Already arrives on the paint thread (the picker uses Component.onUI internally)
   double lat = coord.lat, lon = coord.lon;
   salvarLocal(lat, lon);
};

LocationPicker picker = new LocationPicker(
   aoConfirmar,   // callback with the confirmed LatLon
   30.0,          // minPdop: enables confirm when accuracy <= 30m
   true,          // canDragPin: user can drag the pin
   true,          // highPrecision
   false);        // streetview
picker.show();

// Alternative: read the result later via getAnswer() (null if cancelled)
```

## Go deeper
- Location guide: [Location & GPS](/docs/data-and-services/device-location-gps) · Widget: [LocationPicker](/docs/ui/widgets/locationpicker)
- Sibling recipe: [escolher-local-no-mapa.md](/docs/cookbook/device/obter-gps)
