---
title: "Work with maps"
section: "frontend/geo"
platforms: ["android", "angular", "javascript", "nextjs", "react", "swift", "vue"]
gen: 2
last-updated: "2026-03-25T17:40:00.000Z"
url: "https://docs.amplify.aws/react/frontend/geo/maps/"
---

<!-- Platform: javascript, angular, react, vue, react-native, nextjs -->
## Display a map

First, ensure you've provisioned an Amazon Location Service Map resource and configured your app using the instructions in either [Set up map](/[platform]/build-a-backend/add-aws-services/geo/set-up-geo/) or [Use existing resources](/[platform]/build-a-backend/add-aws-services/geo/existing-resources/) guide.

<Callout>

**Note:** For React, you can use the [Amplify React MapView component](https://ui.docs.amplify.aws/react/components/geo)

</Callout>

To render a map, the [MapLibre GL](https://github.com/maplibre/maplibre-gl-js) and the `maplibre-gl-js-amplify` libraries are required. MapLibre GL is an open source map rendering library and `maplibre-gl-js-amplify` library makes it easy to integrate MapLibre with Amplify Geo and handles Authentication.

Add the dependencies to your app:

```bash title="Terminal" showLineNumbers={false} 
npm add maplibre-gl maplibre-gl-js-amplify
```

<Callout>

Verify the following:

- `maplibre-gl-js-amplify` version `4.0.0` or above is installed
- Any package bundlers (webpack, rollup, etc) are configured to handle css files. Check out the webpack documentation [here](https://webpack.js.org/loaders/css-loader/).

</Callout>

Import the library into your application:

```javascript
import { createMap } from 'maplibre-gl-js-amplify';
import 'maplibre-gl/dist/maplibre-gl.css';
```

Next, create and render the [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) with the help of [createMap](https://github.com/aws-amplify/maplibre-gl-js-amplify/blob/main/API.md#createmap).

**Note:** There must be a `div` with an `id="map"` on the DOM before making the call to `createMap` in this way.

```javascript
async function initializeMap() {
  const map = await createMap({
    container: 'map', // An HTML Element or HTML element ID to render the map in https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/
    center: [-123.1187, 49.2819], // [Longitude, Latitude]
    zoom: 11
  });
}

initializeMap();
```

To render a map using a className or something other than the ID you can pass in a reference to the HTML Element itself.

```javascript
const element = document.getElementsByClassName("class")[0];

const map = await createMap({
    container: element,
    ...
})
```

<Callout>

The MapLibre canvas requires a defined height to display properly, otherwise you may end up with a blank screen where the map is supposed to be.

The [amplify-map.css](https://github.com/aws-amplify/maplibre-gl-js-amplify/blob/main/src/public/amplify-map.css) file has a few commonly used methods for setting the height of the map component. You can add some of the examples listed to your own styles or directly import `amplify-map.css` like so:

```
import "maplibre-gl-js-amplify/dist/public/amplify-map.css";
```

To render a map using percentage based height you need to ensure that all ancestor elements to the map container have a height:

```css
html,
body,
#root {
  /* The ancestors of the map element */
  height: 100%;
}

#map {
  height: 50%;
}
```

</Callout>

![A map centered on Vancouver](/images/display-map.png)

## Display markers on map

To display markers on a map, use the `drawPoints` function. `drawPoints` expects:

- `sourceName` - specifies the layer on which the markers are rendered on. You can edit existing markers by passing the same `sourceName`
- coordinate data - (longitude, latitude) the coordinate data of the markers to be displayed
- a maplibre-gl-js Map - the map object on which to render the markers

First, import the `drawPoints` method in your app. Your import section should include look like this

```javascript
import { drawPoints } from 'maplibre-gl-js-amplify';
```

<Callout>

The `drawPoints` method returns ids of the source and layers used to display the markers on the map. These ids can be used for further customization through maplibre-gl-js [source](https://maplibre.org/maplibre-gl-js/docs/API/#sources), [paint](https://maplibre.org/maplibre-style-spec/layers/#paint-property), and [layer](https://maplibre.org/maplibre-style-spec/layers/) options.

For more information about the parameters and options that can be used with `drawPoints` check the documentation [here](https://github.com/aws-amplify/maplibre-gl-js-amplify/blob/main/API.md#drawpoints).

</Callout>

Next, use the following code snippet when you want to display the markers on the map. Add it to the `initializeMap()` function if you want the markers to show up on map load.

```javascript
map.on('load', function () {
  drawPoints(
    'mySourceName', // Arbitrary source name
    [
      {
        coordinates: [-122.483696, 37.833818], // [Longitude, Latitude]
        title: 'Golden Gate Bridge',
        address: 'A suspension bridge spanning the Golden Gate'
      },
      {
        coordinates: [-122.477, 37.8105] // [Longitude, Latitude]
      }
    ], // An array of coordinate data, an array of Feature data, or an array of [NamedLocations](https://github.com/aws-amplify/maplibre-gl-js-amplify/blob/main/src/types.ts#L8)
    map,
    {
      showCluster: true,
      unclusteredOptions: {
        showMarkerPopup: true
      },
      clusterOptions: {
        showCount: true
      }
    }
  );
});
```

![A map with points on the golden gate bridge](/images/display-map-with-points.png)

## Display different map styles

The `getAvailableMaps` API fetches information for all maps that are available to be displayed.

This is useful if you would like to give your users a variety of maps styles to choose from.

```javascript
import { Geo } from '@aws-amplify/geo';

Geo.getAvailableMaps();
```

The available maps are returned as an array with the following contents:

```javascript
//returns
[
  {
    mapName: 'myAmplifyGeoEsriStreetMap',
    style: 'VectorEsriStreets'
  },
  {
    mapName: 'myAmplifyGeoEsriTopographicMap',
    style: 'VectorEsriTopographic'
  }
];
```

You can resize and customize a map with the `resize` and `setStyle` functions:

```javascript
map.setStyle('myAmplifyGeoEsriTopographicMap'); // map name received from getAvailableMaps()
map.resize(); // forces the map to re-render
```

## Removing a map from the DOM

When it's time to remove the map from the DOM, you can use the `.remove` method of the generated map. This will clean up and release all resources associated with the map (DOM elements, event bindings, web workers, and WebGL resources).

```javascript
map.remove();
```

> **Warning:** After calling `.remove()`, you must not call any other methods on the map.

> **Warning:** **For React users:**
> 
> Not removing the map on component unmount can cause memory leaks in your application. It's recommended to call `.remove()` in either the return function of a React `useEffect` hook or the `componentWillUnmount` lifecycle hook of a class component.

## Add map to html website

To display a map on your html website, add the following scripts to your html webpage.

```html
<link href="https://cdn.amplify.aws/packages/maplibre-gl/1.15.2/maplibre-gl.css" rel="stylesheet" integrity="sha384-DrPVD9GufrxGb7kWwRv0CywpXTmfvbKOZ5i5pN7urmIThew0zXKTME+gutUgtpeD" crossorigin="anonymous" referrerpolicy="no-referrer"></link>
<script src="https://cdn.amplify.aws/packages/maplibre-gl/1.15.2/maplibre-gl.js" integrity="sha384-rwYfkmAOpciZS2bDuwZ/Xa/Gog6jXem8D/whm3wnsZSVFemDDlprcUXHnDDUcrNU" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.amplify.aws/packages/core/4.3.0/aws-amplify-core.min.js" integrity="sha384-7Oh+5w0l7XGyYvSqbKi2Q7SA5K640V5nyW2/LEbevDQEV1HMJqJLA1A00z2hu8fJ" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.amplify.aws/packages/auth/4.3.8/aws-amplify-auth.min.js" integrity="sha384-jfkXCEfYyVmDXYKlgWNwv54xRaZgk14m7sjeb2jLVBtUXCD2p+WU8YZ2mPZ9Xbdw" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.amplify.aws/packages/geo/1.1.0/aws-amplify-geo.min.js" integrity="sha384-TFMTyWuCbiptXTzvOgzJbV8TPUupG1rA1AVrznAhCSpXTIdGw82bGd8RTk5rr3nP" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.amplify.aws/packages/maplibre-gl-js-amplify/1.1.0/maplibre-gl-js-amplify.umd.min.js" integrity="sha384-7/RxWonKW1nM9zCKiwU9x6bkQTjldosg0D1vZYm0Zj+K/vUSnA3sOMhlRRWAtHPi" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
```

Next, add a div element with id `map` anywhere in your webpage where you want to render the map. Include the following code snippet to configure Amplify (update the `amplify_outputs.json` file path accordingly) and instantiate the map.

```html
<script type="module">
  import outputs from './amplify_outputs.json' assert { type: 'json' };
  const { Amplify } = aws_amplify_core;
  const { createMap } = AmplifyMapLibre;
  Amplify.configure(outputs);
  createMap({
    container: 'map',
    center: [-123.1187, 49.2819], // [Longitude, Latitude]
    zoom: 13
  });
</script>
```

### Sample application

```html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Display a map on a webpage</title>
        <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
        <link href="https://cdn.amplify.aws/packages/maplibre-gl/1.15.2/maplibre-gl.css" rel="stylesheet" integrity="sha384-DrPVD9GufrxGb7kWwRv0CywpXTmfvbKOZ5i5pN7urmIThew0zXKTME+gutUgtpeD" crossorigin="anonymous" referrerpolicy="no-referrer"></link>
        <script src="https://cdn.amplify.aws/packages/maplibre-gl/1.15.2/maplibre-gl.js" integrity="sha384-rwYfkmAOpciZS2bDuwZ/Xa/Gog6jXem8D/whm3wnsZSVFemDDlprcUXHnDDUcrNU" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        <script src="https://cdn.amplify.aws/packages/core/5.0.5/aws-amplify-core.min.js" integrity="sha384-eM2urkpomL9SRm/kuPHZG3XPEItAiUAAyotT/AqlhSus8iAqs/EfHaYy1Jn5ih7K" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        <script src="https://cdn.amplify.aws/packages/auth/5.0.5/aws-amplify-auth.min.js" integrity="sha384-H25CFLYd7YHa1Oib73fs3kJN36VhaHHkLjo4AhGrhJ4HuKam05pg2/0t2MR6epun" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        <script src="https://cdn.amplify.aws/packages/geo/2.0.5/aws-amplify-geo.min.js" integrity="sha384-Esc9xx0X7ckb/yeYHuYsZGqBB4FwYr98NFHS3BRXLeRE/eB0uVrad2w+G6cGxYb5" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        <script src="https://cdn.amplify.aws/packages/maplibre-gl-js-amplify/1.5.0/maplibre-gl-js-amplify.umd.min.js" integrity="sha384-9kJyZavd3Jk6QzHeaLpugVonfZmZZZdixek6uglOwzKtZvDS9K3W4dshw1uswmlV" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
        <style>
            body { margin: 0; padding: 0; }
            #map { position: absolute; top: 0; bottom: 0; width: 100%; }
        </style>
    </head>
    <body>
        <div id="map"></div>
        <script type="module">
            import outputs from "./amplify_outputs.json" assert { type: "json" };
            const { Amplify } = aws_amplify_core;
            const { createMap } = AmplifyMapLibre;
            Amplify.configure(outputs);
            createMap({
                container: "map",
                center: [-123.1187, 49.2819], // [Longitude, Latitude]
                zoom: 13,
            });
        </script>
    </body>
</html>
```

## Map API's

If you want more information about the maps you currently have configured or want a way to switch between maps programmatically, the `@aws-amplify/geo` package provides API's that return more information about your currently provisioned maps.

First, you need to import Geo from the `@aws-amplify/geo` package.

```javascript
import { Geo } from '@aws-amplify/geo';
```

### getAvailableMaps

`getAvailableMaps` will return the map resources you currently have provisioned in your Amplify project. You can switch between any of these different maps and display their different map styles.

#### API

```javascript
Geo.getAvailableMaps() => Promise<AmazonLocationServiceMapStyle[]>;
```

#### Parameters

- N/A

#### Return

The return from `getAvailableMaps` is a Promise that resolves to `AmazonLocationServiceMapStyle[]` which is an array of `mapName`, `style`, and `region`.

Each object has the following properties:

- `mapName` - name of the map you created.
- `style` - the Amazon Location Service style used to create the map.
- `region` - the AWS region the map is hosted in.

<Callout>

**Note:** When changing a map with Amplify and MapLibre the [setStyle](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#setstyle) function should be called with the name of the Location Service map NOT the style. This is because the `transformRequest` function uses the Location Service map name to make a new request for map tile data.

</Callout>

#### Example

```js
const availableMaps = await Geo.getAvailableMaps();

map.setStyle(availableMaps[0].mapName);
```

### getDefaultMap

`getDefaultMap` is used to get a the default map object.

#### API

```javascript
Geo.getDefaultMap() => Promise<AmazonLocationServiceMapStyle>;
```

#### Parameters

- N/A

#### Return

The return from `getDefaultMap` is a Promise that resolves to a AmazonLocationServiceMapStyle object.

The object has the following properties:

- `mapName` - name of the map you created.
- `style` - the Amazon Location Service style used to create the map.
- `region` - the AWS region the map is hosted in.

#### Example

```javascript
const defaultMap = await Geo.getDefaultMap();
```
<!-- /Platform -->

<!-- Platform: android, swift -->
## Install Amplify-MapLibre adapter

<!-- Platform: android -->
Add the following dependency to your **build.gradle (Module :app)** file and click "Sync Now" when prompted:

```groovy
dependencies {
    implementation 'com.amplifyframework:aws-auth-cognito:ANDROID_VERSION'
    implementation 'com.amplifyframework:aws-geo-location:ANDROID_VERSION'

    // Add this dependency to integrate MapLibre into your app
    implementation 'com.amplifyframework:maplibre-adapter:ANDROID_VERSION'
}
```

<Callout>

**Note:** the minimum API level required for the UI components is 21.

</Callout>
<!-- /Platform -->

<!-- Platform: swift -->
<Callout>

MapLibre is
[not officially supported on macOS](https://github.com/maplibre/maplibre-gl-native/blob/9d37d3d4aab293675f3df3a7f9bee7b2f476daf5/platform/ios/platform/macos/README.md?plain=1#L22),
and as a result `amplify-ios-maplibre` can only be used on iOS. Apple's [MapKit](https://developer.apple.com/documentation/mapkit/)
framework may be used in order to display maps on macOS applications.

</Callout>

First, ensure you've provisioned an Amazon Location Service Map resource and configured your app using the instructions in either [Configure maps](/[platform]/build-a-backend/add-aws-services/geo/set-up-geo/) or [Use existing resources](/[platform]/build-a-backend/add-aws-services/geo/existing-resources/) guide.

Amplify-MapLibre is an open source adapter that enables the popular MapLibre SDK to work seamlessly with Amplify Geo.

1. To install the Amplify-MapLibre adapter to your application, open your project in Xcode and select **File > Add Packages...**

1. Enter the amplify-ios-maplibre GitHub repo URL (`https://github.com/aws-amplify/amplify-ios-maplibre`) into the search bar and hit **Enter**. Wait for the result to load. You'll see the repository rules for which version of amplify-ios-mapLibre you want Swift Package Manager to install. 

1. Choose the dependency rule **Up to Next Major Version**, as it will use the latest compatible version of the dependency, then click **Add Package**.

1. Lastly, choose which of the libraries you want added to your project. If you want to use the SwiftUI user interface components provided by the adapter, select both **AmplifyMapLibreAdapter** and **AmplifyMapLibreUI**. If you only want to enable Amplify Geo to work directly with MapLibre and do not wish use use the provided SwiftUI views, you can just select **AmplifyMapLibreAdapter**. After you select the libraries, click **Add Package**.

<Callout>

You can always go back and modify which SPM packages are included in your project by opening the Swift Packages tab for your project (`Project file > Project > Package Dependencies`)

</Callout>
<!-- /Platform -->

## Display a map

First, ensure you've provisioned an Amazon Location Service Map resource and configured your app using the instructions in either [Configure maps](/[platform]/build-a-backend/add-aws-services/geo/set-up-geo/) or [Use existing resources](/[platform]/build-a-backend/add-aws-services/geo/existing-resources/) guide.

<!-- Platform: android -->
### Select your user interface

There are two UI components available to render maps on an Android app, the `MapLibreView` and the `AmplifyMapView`. The `MapLibreView` is an extension of the standard [Android MapLibre MapView](https://docs.maptiler.com/maplibre-gl-native-android/) that is integrated with the `Amplify.Geo` APIs, while the `AmplifyMapView` is a wrapper with built-in location search, map controls, markers and a few standard UX interactions.

#### `MapLibreView` vs `AmplifyMapView`

If the goal is to customize the UI, the `MapLibreView` provides a plain map that allows you to build and integrate your own controls and flow. If the goal is to use the map to search and select places, with a standard UI, then `AmplifyMapView` is a good choice.

Note that even though the extensibility of `AmplifyMapView` is limited, you have access to the wrapped `MapLibreView` through the `mapView` property (`getMapView()` on Java). So any API available to `MapLibreView` is also available on `AmplifyMapView`.

## MapLibreView

The `MapLibreView` is an extension of the standard `MapView` provided by the MapLibre library. The implementation adds the `Amplify.Geo` integration behind the scenes to enable developers to focus on their UI instead of the library integration. That also means all MapLibre APIs are available and will work as expected. Check the [official MapLibre SDK for Android documentation](https://docs.maptiler.com/maplibre-gl-native-android/) for the API reference and guides.

### Add a map to your app

1. Navigate to your app's `src/main/res/layout` directory in Android Studio

2. Create a new layout named `activity_main.xml`, or use an existing layout of your choice, and add the following:

```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:mapbox="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.amplifyframework.geo.maplibre.view.MapLibreView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    />

</androidx.constraintlayout.widget.ConstraintLayout>
```

### Initialize the MapLibreView

1. Navigate to your app's activity (e.g. `MainActivity`)

2. Add an import statement for MapLibreView at the top of your app's activity:

#### [Java]

```java
import com.amplifyframework.geo.maplibre.view.MapLibreView;
```

#### [Kotlin]

```kotlin
import com.amplifyframework.geo.maplibre.view.MapLibreView
```

3. Declare the view instance variable at top-level of the activity:

#### [Java]

```java
private MapLibreView mapView;
```

#### [Kotlin]

```kotlin
private val mapView by lazy {
    findViewById<MapLibreView>(R.id.mapView)
}
```

4. Interact with the map in the Activity's `onCreate`:

#### [Java]

```java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Note: make sure you configure Amplify before calling setContentView
    // See the Getting Started instructions

    setContentView(R.layout.activity_main);
    mapView = findViewById(R.id.mapView);

    // now you can interact with the mapView, see examples below
}
```

#### [Kotlin]

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Note: make sure you configure Amplify before calling setContentView
    // See the Getting Started instructions

    setContentView(R.layout.activity_main)

    // now you can interact with the mapView, see examples below
}
```

### Interact with the map

The map needs to be loaded in order to interact with it. You can use either `getMapAsync` that is called when the map is ready or `getStyle` that is called when both the map and its style are ready. Some APIs, like the `SymbolManager`, require the style to also be loaded so you can draw markers and other symbols on the map, that's when `getStyle` comes in handy.

### Update the map center

#### [Java]

```java
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLng;
```

```java
mapView.getMapAsync(map -> {
    LatLng seattle = new LatLng(47.6160281982247, -122.32642111977668);
    map.setCameraPosition(
        new CameraPosition.Builder()
            .target(seattle)
            .zoom(13.0)
            .build()
    );
});
```

#### [Kotlin]

```kotlin
import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.geometry.LatLng
```

```kotlin
mapView.getMapAsync { map ->
    val seattle = LatLng(47.6160281982247, -122.32642111977668)
    map.cameraPosition = CameraPosition.Builder()
        .target(seattle)
        .zoom(13.0)
        .build()
}
```

Updating `cameraPosition` moves the camera to the passed coordinates without any animation. If animation is needed, use `map.animateCamera()` instead. See the [official reference](https://docs.mapbox.com/android/maps/guides/camera-and-animation/camera/) for more details.

### Add markers to your map

The MapLibre SDK for Android relies on the [MapLibre Annotation Plugin](https://docs.mapbox.com/android/maps/guides/annotations/) in order to display markers on a map.

#### [Java]

```java
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions;
```

```java
mapView.getStyle((map, style) -> {
    LatLng spaceNeedle = new LatLng(47.6205063, -122.3514661);
    mapView.symbolManager.create(
        new SymbolOptions()
                .withIconImage("place")
                .withLatLng(spaceNeedle)
    );
    map.animateCamera(CameraUpdateFactory.newLatLngZoom(spaceNeedle, 16.0));
});
```

#### [Kotlin]

```kotlin
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions
```

```kotlin
mapView.getStyle { map, style ->
    val spaceNeedle = LatLng(47.6205063, -122.3514661)
    mapView.symbolManager.create(
        SymbolOptions()
            .withIconImage("place")
            .withLatLng(spaceNeedle)
    )
    map.animateCamera(CameraUpdateFactory.newLatLngZoom(spaceNeedle, 16.0))
}
```

**Notes:**

- The `mapView.symbolManager` is a built-in reference of `SymbolManager` from the [MapLibre Annotation Plugin](https://docs.mapbox.com/android/maps/guides/annotations/) with some standard configuration.
- If customized icons or render other types of shapes and layers are needed, an instance of `SymbolManager` can be created and used to manage the different types of custom use-cases.

### MapLibreView configuration parameters

The `MapLibreView` has several configuration parameters that are not present in the official guides yet. For a complete list, refer to the [source xml file](https://github.com/maplibre/maplibre-gl-native/blob/main/platform/android/MapLibreAndroid/src/main/res/values/attrs.xml).

Also, check the [official MapView API reference](https://docs.maptiler.com/maplibre-gl-native-android/com.mapbox.mapboxsdk.maps/#mapview) for the available public API documentation.

## AmplifyMapView

The `AmplifyMapView` provides a default search field, place markers, visualization modes (map or list) and map controls. It can be used to easily embed a place picker into any app. To use the search functionality of `AmplifyMapView`, provision a search index resource using the instructions in either [Configure Location Search](/[platform]/build-a-backend/add-aws-services/geo/configure-location-search/) or [Use existing Amazon Location Service resources](/[platform]/build-a-backend/add-aws-services/geo/configure-location-search/).

### Add a map to your app

1. Navigate to your app's `src/main/res/layout` directory in Android Studio

2. Create a new layout named `activity_main.xml`, or use an existing layout of your choice, and add the following:

```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.amplifyframework.geo.maplibre.view.AmplifyMapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    />

</androidx.constraintlayout.widget.ConstraintLayout>
```

### Initialize the AmplifyMapView

1. Navigate to your app's activity (e.g. `MainActivity`)

2. Add an import statement for AmplifyMapView at the top of your app's activity:

#### [Java]

```java
import com.amplifyframework.geo.maplibre.view.AmplifyMapView;
```

#### [Kotlin]

```kotlin
import com.amplifyframework.geo.maplibre.view.AmplifyMapView
```

3. Declare the view instance variable at top-level of the activity:

#### [Java]

```java
private AmplifyMapView amplifyMapView;
```

#### [Kotlin]

```kotlin
private val amplifyMapView by lazy {
    findViewById<AmplifyMapView>(R.id.mapView)
}
```

4. Interact with the map in the Activity's `onCreate`:

#### [Java]

```java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Note: make sure you configure Amplify before calling setContentView
    // See the Getting Started instructions

    setContentView(R.layout.activity_main);
    amplifyMapView = findViewById(R.id.mapView);

    // now you can interact with the mapView, see examples below
}
```

#### [Kotlin]

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Note: make sure you configure Amplify before calling setContentView
    // See the Getting Started instructions

    setContentView(R.layout.activity_main)

    // now you can interact with the mapView, see examples below
}
```

### Place select

The main API provided by `AmplifyMapView` is an event listener that is called when a place is selected on the map, either by clicking on the mark or the item on the list.

#### [Java]

```java
import android.util.Log;
```

```java
amplifyMapView.setOnPlaceSelectListener((place, symbol) -> {
    // place is an instance of AmazonLocationPlace
    // symbol is an instance of Symbol from MapLibre
    Log.i("MyAmplifyApp", "The selected place is " + place.getLabel());
    Log.i("MyAmplifyApp", "It is located at " + place.getCoordinates());
});
```

#### [Kotlin]

```kotlin
import android.util.Log
```

```kotlin
amplifyMapView.onPlaceSelect { place, symbol ->
    // place is an instance of AmazonLocationPlace
    // symbol is an instance of Symbol from MapLibre
    Log.i("MyAmplifyApp", "The selected place is ${place.label}")
    Log.i("MyAmplifyApp", "It is located at ${place.coordinates}")
}
```

### AmplifyMapView configuration parameters

The view can be initialized with the following configuration parameters:

| Property                       | Type    | Description                                          | Default |
|--------------------------------|---------|------------------------------------------------------|---------|
| `map:map_centerLatitude`       | Float   | The initial center latitude                          | `0.0`   |
| `map:map_centerLongitude`      | Float   | The initial center longitude                         | `0.0`   |
| `map:map_minZoomLevel`         | Integer | The minimum zoom level (min is 0)                    | `3`     |
| `map:map_maxZoomLevel`         | Integer | The maximum zoom level (max is 22)                   | `18`    |
| `map:map_showCompassIndicator` | Boolean | Whether the compass should be displayed or not       | `true`  |
| `map:map_showZoomControls`     | Boolean | Whether the zoom controls should be displayed or not | `false` |
| `map:map_zoomLevel`            | Integer | The initial zoom level (between 0 and 22)            | `14`    |

Example:

```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.amplifyframework.geo.maplibre.view.AmplifyMapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        map:map_zoomLevel="12"
        map:map_centerLatitude="47.6160281982247"
        map:map_centerLongitude="-122.32642111977668"
        map:map_showCompassIndicator="true"
        map:map_showZoomControls="true"
    />

</androidx.constraintlayout.widget.ConstraintLayout>
```
<!-- /Platform -->

<!-- Platform: swift -->
### Select your user interface

There are two ways to display a map. The easiest way to get started is to use the `AmplifyMaplibreUI` library to create an instance of `AMLMapView`. This is the recommended approach for new projects or anyone who wants to use SwiftUI.

Alternatively, if you are using UIKit or have existing code using the MapLibre/MapBox SDK, you can simply call `AmplifyMapLibre.createMap(completionHandler:)` to create an instance of `MGLMapView` that is pre-wired for use with Amazon Location Service and Amplify. For more information on using `MGLMapView` directly, please see the [MapLibre Documentation](https://docs.maptiler.com/maplibre-gl-native-ios/)

#### [SwiftUI]

```swift
import SwiftUI
import AmplifyMapLibreUI

struct ContentView: View {    
    var body: some View {
        AMLMapView()
            .edgesIgnoringSafeArea(.all)
    }
}
```

#### [UIKit]

```swift
import AmplifyMapLibreAdapter
import Mapbox
import Amplify

var mapView: MGLMapView?
do {
    mapView = try await AmplifyMapLibre.createMap()
} catch {
    print(error)
}
```

## Customize the map and access state

The `AMLMapView` can be customized through a number of view modifiers. The map state information can be set and observed through an instance of `AMLMapViewState`, which can optionally be passed into `AMLMapView` to set initial values. The following example sets an initial zoom level and center location for the map and configures the map to show the user's location.

```swift
@StateObject private var mapState = AMLMapViewState(
    zoomLevel: 8,
    center: CLLocationCoordinate2D(latitude: 39.7392, longitude: -104.9903)
)

var body: some View {
    AMLMapView(mapState: mapState)
        .showUserLocation(true)
        .edgesIgnoringSafeArea(.all)
}
```

## Inject custom behavior

The `AMLMapView` also allows for custom behavior triggered by user interaction to be injected. The following example sets a custom feature image and defines the maps behavior when that feature is tapped - zooming in two levels above the current level.

```swift
var body: some View {
    AMLMapView()
        .featureImage { MyCustomImage() }
        .featureTapped { mapView, pointFeature in
            mapView.setCenter(
                pointFeature.coordinate,
                zoomLevel: mapView.zoomLevel + 2,
                direction: mapView.camera.heading,
                animated: true
            )
        }
        .edgesIgnoringSafeArea(.all)
}
```

## AMLMapCompositeView

The `AMLMapCompositeView` combines `AMLMapView`, `AMLSearchBar`, `AMLMapControlView`, and `AMLPlaceCellView` to create a full user experience. This includes accessible map control buttons, a search bar that automatically searches for points of interest based on user input, and a list representation of points.
In its simplest form, which still leverages all of the above mentioned functionality, the `AMLMapCompositeView` can be instantiated without any arguments. All of the view modifiers and state tracking capabilities of `AMLMapView` are also available on `AMLMapCompositeView`.

```swift
var body: some View {
    AMLMapCompositeView()
}
```
<Callout>

For full details on `AMLMapView` usage and customization, see the [AmplifyMapLibre documentation](https://aws-amplify.github.io/amplify-ios-maplibre/docs/).

</Callout>
<!-- /Platform -->

## Display different map styles

<!-- Platform: android -->
The `getAvailableMaps` API fetches information for all maps that are available to be displayed.

This is useful if you would like to give your users a variety of map styles to choose from.

#### [Java]

```java
Amplify.Geo.getAvailableMaps(
    result -> {
        for (final MapStyle style : result) {
            Log.i("MyAmplifyApp", style.toString());
        }
    },
    error -> Log.e("MyAmplifyApp", "Failed to get available maps.", error)
);
```

#### [Kotlin - Callbacks]

```kotlin
Amplify.Geo.getAvailableMaps(
    {
        for (mapStyle in it) {
            Log.i("MyAmplifyApp", mapStyle.toString())
        }
    },
    { Log.e("MyAmplifyApp", "Failed to get available maps.", it) }
)
```

#### [Kotlin - Coroutines]

```kotlin
try {
    val result = Amplify.Geo.getAvailableMaps()
    for (mapStyle in result) {
        Log.i("MyAmplifyApp", mapStyle.toString())
    }
} catch (error: GeoException) {
    Log.e("MyAmplifyApp", "Failed to get available maps.", error)
}
```

#### [RxJava]

```java
RxAmplify.Geo.getAvailableMaps().subscribe(
    result -> {
        for (final MapStyle style : result) {
            Log.i("MyAmplifyApp", style.toString());
        }
    },
    error -> Log.e("MyAmplifyApp", "Failed to get available maps.", error)
);
```

You can set a different style to your map using `setStyle` method from the adapter:

#### [Java]

With `MapLibreView`:

```java
// where mapStyle is a reference to the selected style from Amplify.Geo.getAvailableMaps
mapView.setStyle(mapStyle, style -> {
    Log.i("MyAmplifyApp", "Finished loading " + mapStyle.getStyle());
});
```

With `AmplifyMapView`:
```java
// where mapStyle is a reference to the selected style from Amplify.Geo.getAvailableMaps
amplifyMapView.getMapView().setStyle(mapStyle, style -> {
    Log.i("MyAmplifyApp", "Finished loading " + mapStyle.getStyle());
});
```

#### [Kotlin]

With `MapLibreView`:

```kotlin
// where mapStyle is a reference to the selected style from Amplify.Geo.getAvailableMaps
mapView.setStyle(mapStyle) { style ->
    Log.i("MyAmplifyApp", "Finished loading ${mapStyle.style}.")
}
```

With `AmplifyMapView`:

```kotlin
// where mapStyle is a reference to the selected style from Amplify.Geo.getAvailableMaps
amplifyMapView.mapView.setStyle(mapStyle) { style ->
    Log.i("MyAmplifyApp", "Finished loading ${mapStyle.style}.")
}
```

<!-- /Platform -->

<!-- Platform: swift -->
The `availableMaps` API fetches information for all maps that are available to be displayed.

This is useful if you would like to give your users a variety of maps styles to choose from.

```swift
var maps = [Geo.MapStyle]()
do {
    maps = try await Amplify.Geo.availableMaps()
} catch let error as Geo.Error {
    print("Failed to get available maps: \(error)")
} catch {
    print("Unexpected error: \(error)")
}
```

You can load a different style map by passing it to the createMap function.

```swift
guard let mapStyle = maps.first else {
    print("No maps available")
    return
}

let mapView = AmplifyMapLibre.createMap(mapStyle)
```
<!-- /Platform -->
<!-- /Platform -->
