# LocationPicker

> 在带 GPS 的地图上选择地理坐标，并把经纬度回传给调用方。

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

# LocationPicker

`LocationPicker` 在地图上选择一个**地理坐标**，支持 GPS 跟踪和可拖动的图钉。它遵循 picker 的模式（参见 [`Picker`](/docs/ui/widgets/picker)）并返回一个 `LatLon`。

> 🔴 · **包：** `dev.crossfly.ui.picker` · **继承自：** `Picker` · **硬件：** GPS + 地图

## 何时使用
- 在地图上采集一个位置（配送地址、兴趣点）。

## 外观
顶部栏带圆形按钮（地图类型 Normal/Satélite、返回、确认），地图（FILL）占据主体，一个带精度圆圈的可拖动图钉（根据 PDOP 显示绿色/红色），底部有一个状态标签。

## 完整示例（复制、粘贴并运行）
`LocationPicker` 会打开一个全屏地图 —— 请从 `Button` 触发它。该示例复用了基本用法，并在 `Label` 中显示已确认的坐标。`LatLon` 来自 `dev.crossfly.map`。

```java
package com.exemplo;

import dev.crossfly.map.LatLon;

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

/** 可执行的主界面。将 launcher 指向此类（classname）并运行：gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

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

      Button escolher = new Button("Escolher local no mapa")
         .onAction(c ->
         {
            LocationPicker lp = new LocationPicker(
               coord -> {},   // 构造函数的 onCapture（可选；可以为 null）
               10.0,          // minPdop
               true,          // 可以拖动图钉
               true,          // 高精度
               false);        // 无街景

            lp.show(answer ->
            {
               LatLon ll = (LatLon) answer;
               if (ll != null)
                  saida.setText("Local: " + ll.lat + ", " + ll.lon);
            });
         });
      add(LAY_AUTO, escolher);
   }
}
```

> 下面的片段**只展示核心部分**（放在 `onShow()` 里的内容）。要运行它们，请放入上面的 `MainWindow` 骨架中。

## 基本用法
```java
LocationPicker lp = new LocationPicker(
   coord -> Debug.log("Capturado: " + coord.lat + "," + coord.lon),
   10.0,   // minPdop
   true,   // 可以拖动图钉
   true,   // 高精度
   false); // 无街景

lp.show(answer ->
{
   LatLon ll = (LatLon) answer;
   salvarLocal(ll.lat, ll.lon);
});
```

## 构造函数
| 构造函数 | 描述 |
|---|---|
| `LocationPicker(RunnableWith<LatLon> onCapture, double minPdop, boolean canDragPin, boolean highPrecision, boolean streetview)` | 参见下方参数。 |

| 参数 | 类型 | 作用 |
|---|---|---|
| `onCapture` | `RunnableWith<LatLon>` | 确认时带 `LatLon` 的回调（可为 `null`）。 |
| `minPdop` | `double` | 可接受的最大 PDOP；在达到之前确认按钮保持隐藏。 |
| `canDragPin` | `boolean` | 允许拖动图钉以手动选点。 |
| `highPrecision` | `boolean` | 开启高精度 GPS。 |
| `streetview` | `boolean` | 在地图上启用街景。 |

## 回调与事件
| 回调 | 触发时机 |
|---|---|
| `onCapture`（构造函数） | 确认时，带 `LatLon`（若 `!= null`）。 |
| `show(onAnswer)` | 关闭时，交付已确认的 `LatLon`。 |

`getAnswer()` 返回已确认的 `LatLon`，若取消则返回 `null`。**结果有两条路径**（构造函数的 `onCapture` 和 `show` 的 `onAnswer`）—— 二者都仅在 `answer != null` 时触发。

## 状态
- 拖动图钉会关闭 GPS（`canUpdateGPS = false`），标记为 "Custom Location" 并显示确认按钮。
- 确认按钮仅在精度可接受时（或在桌面端，或手动拖动之后）出现。
- 资源（GPS 线程、`Location`、地图）在关闭时仅释放一次。

## 最佳实践
- 选择一个现实的 `minPdop`；在移动端，确认按钮在 GPS 达到该值之前保持隐藏。
- 不要在 `hide()` 之后复用该实例 —— GPS/地图资源已被释放。

## 常见错误
- **确认按钮始终不出现** —— GPS 未达到 `minPdop` 且用户未拖动图钉（在桌面端会立即出现）。
- **在取消时期望 `onAnswer`** —— 不会触发（`answer = null`）。

## 另请参阅
- 领域指南：[`ui/`](/docs/ui) · 实用配方：[`cookbook/`](/docs/cookbook)
- 模式基础：[`Picker`](/docs/ui/widgets/picker)
