location_webview 1.0.6
location_webview: ^1.0.6 copied to clipboard
A Flutter package that displays an interactive map using WebView with OpenStreetMap and Leaflet, perfect for showing location coordinates with customizable styling.
import 'package:flutter/material.dart';
import 'package:location_webview/location_webview.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'location_webview example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const MapExamplePage(),
);
}
}
class MapExamplePage extends StatefulWidget {
const MapExamplePage({super.key});
@override
State<MapExamplePage> createState() => _MapExamplePageState();
}
class _LocationOption {
final String label;
final double lat;
final double lng;
final String address;
const _LocationOption({
required this.label,
required this.lat,
required this.lng,
required this.address,
});
}
class _MapExamplePageState extends State<MapExamplePage> {
static const _locations = <_LocationOption>[
_LocationOption(
label: 'Concord Tower, Dubai',
lat: 25.0978092,
lng: 55.1562957,
address: 'Concord Tower, Dubai',
),
_LocationOption(
label: 'Times Square, NYC',
lat: 40.7580,
lng: -73.9855,
address: 'Times Square, New York, NY',
),
_LocationOption(
label: 'London Bridge, London',
lat: 51.5079,
lng: -0.0877,
address: 'London Bridge, London',
),
];
_LocationOption _selected = _locations.first;
bool _isDark = false;
bool _useCustomTap = false;
double _height = 360;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('location_webview example'),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
InputDecorator(
decoration: const InputDecoration(
labelText: 'Location',
border: OutlineInputBorder(),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<_LocationOption>(
isExpanded: true,
value: _selected,
items: _locations
.map(
(loc) => DropdownMenuItem(
value: loc,
child: Text(loc.label),
),
)
.toList(),
onChanged: (loc) {
if (loc == null) return;
setState(() => _selected = loc);
},
),
),
),
const SizedBox(height: 12),
SwitchListTile.adaptive(
contentPadding: EdgeInsets.zero,
title: const Text('Dark mode'),
value: _isDark,
onChanged: (v) => setState(() => _isDark = v),
),
SwitchListTile.adaptive(
contentPadding: EdgeInsets.zero,
title: const Text('Use custom onTap (override directions)'),
subtitle: const Text('Shows a SnackBar instead of opening Maps.'),
value: _useCustomTap,
onChanged: (v) => setState(() => _useCustomTap = v),
),
const SizedBox(height: 8),
Text('Height: ${_height.round()}px'),
Slider(
min: 220,
max: 600,
divisions: 19,
value: _height,
label: _height.round().toString(),
onChanged: (v) => setState(() => _height = v),
),
const SizedBox(height: 12),
LocationWebView(
lat: _selected.lat,
lng: _selected.lng,
address: _selected.address,
height: _height,
isDark: _isDark,
onTap: _useCustomTap
? () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Custom onTap called'),
),
);
}
: null,
),
const SizedBox(height: 12),
const Text(
'Tip: when custom onTap is OFF, tapping the map opens directions in your default maps app.',
),
],
),
);
}
}