Skip to main content
GuidesAPI ReferenceExamplesFAQ

What Is Nearby

Estimated reading time: 3 minutes

This example demonstrates how to create a Flutter app that shows nearby landmarks based on the user’s current position using the Maps SDK for Flutter.

How It Works

This example app demonstrates the following features:

  • Obtain location permissions and show a map centered on the user’s location.
  • Display nearby landmarks as a list.
  • Allow navigation to a detail page displaying information about nearby landmarks.
hello_maphello_map
Current position availableNearby locations

Map Display and Permissions

The map is displayed and initialized within the MyHomePage widget, which also handles location permissions for Android and iOS. This widget handles the UI, setting up the map and app bar, and uses permission_handler for requesting location permissions.

class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});


State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
late GemMapController _mapController;
PermissionStatus _locationPermissionStatus = PermissionStatus.denied;
bool _hasLiveDataSource = false;


void dispose() {
GemKit.release();
super.dispose();
}


Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple[900],
title: const Text('What\'s Nearby', style: TextStyle(color: Colors.white)),
actions: [
IconButton(
onPressed: () => _onWhatIsNearbyButtonPressed(context),
icon: const Icon(Icons.question_mark, color: Colors.white),
),
],
),
body: GemMap(
key: ValueKey("GemMap"),
onMapCreated: _onMapCreated,
appAuthorization: projectApiToken,
),
);
}

Fetching Nearby Locations

The WhatIsNearbyPage widget displays a list of nearby landmarks based on the user’s current position. This code searches for nearby landmarks, displaying the results in a ListView.

class WhatIsNearbyPage extends StatefulWidget {
final Coordinates position;
const WhatIsNearbyPage({super.key, required this.position});


State<WhatIsNearbyPage> createState() => _WhatIsNearbyPageState();
}

class _WhatIsNearbyPageState extends State<WhatIsNearbyPage> {

Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: true,
foregroundColor: Colors.white,
title: const Text(
"What's Nearby",
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.deepPurple[900],
),
body: FutureBuilder(
future: _getNearbyLocations(),
builder: (context, snapshot) {
if (!snapshot.hasData || snapshot.data == null) {
return const Center(child: CircularProgressIndicator());
}
return ListView.separated(
itemBuilder: (contex, index) {
return NearbyItem(
landmark: snapshot.data!.elementAt(index),
currentPosition: widget.position,
);
},
separatorBuilder:
(context, index) => const Divider(indent: 0, height: 0),
itemCount: snapshot.data!.length,
);
},
),
);
}

Future<List<Landmark>?> _getNearbyLocations() async {
// Add all categories to SearchPreferences
final preferences = SearchPreferences(searchAddresses: false);
final genericCategories = GenericCategories.categories;
for (final category in genericCategories) {
preferences.landmarks.addStoreCategoryId(
category.landmarkStoreId,
category.id,
);
}
final completer = Completer<List<Landmark>?>();
// Perform search around position with current position and all categories
SearchService.searchAroundPosition(
preferences: preferences,
widget.position,
(err, result) {
completer.complete(result);
},
);
return completer.future;
}
}

Displaying Landmark Information

Each nearby landmark is displayed in a list tile showing the name and distance from the current position. This component formats and displays the name and distance of each landmark.

class NearbyItem extends StatefulWidget {
final Landmark landmark;
final Coordinates currentPosition;
const NearbyItem({
super.key,
required this.landmark,
required this.currentPosition,
});


State<NearbyItem> createState() => _NearbyItemState();
}

class _NearbyItemState extends State<NearbyItem> {

Widget build(BuildContext context) {
return ListTile(
title: Text(
widget.landmark.categories.first.name,
overflow: TextOverflow.fade,
style: const TextStyle(
color: Colors.black,
fontSize: 14,
fontWeight: FontWeight.w400,
),
maxLines: 2,
),
leading: widget.landmark.img.isValid
? Image.memory(widget.landmark.img.getRenderableImageBytes(size: Size(128, 128))!)
: SizedBox(),
trailing: Text(
_convertDistance(
widget.landmark.coordinates.distance(widget.currentPosition).toInt(),
),
overflow: TextOverflow.fade,
style: const TextStyle(
color: Colors.black,
fontSize: 14,
fontWeight: FontWeight.w400,
),
),
);
}

String _convertDistance(int meters) {
if (meters >= 1000) {
double kilometers = meters / 1000;
return '${kilometers.toStringAsFixed(1)} km';
} else {
return '${meters.toString()} m';
}
}
}

Flutter Examples

Maps SDK for Flutter Examples can be downloaded or cloned with Git.