Skip to content

Commit 7a34489

Browse files
committed
feat(maps): adding maps demo
1 parent 56893a3 commit 7a34489

21 files changed

+1133
-115
lines changed

.example.env

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GOOGLE_MAPS_API_KEY=YOUR_GOOGLE_MAPS_API_KEY

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
.history
1111
.svn/
1212
.swiftpm/
13+
.env
1314
migrate_working_dir/
1415

1516
# IntelliJ related

.vscode/settings.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"java.configuration.updateBuildConfiguration": "interactive"
3+
}

android/app/build.gradle

+12
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ android {
1010
compileSdk = flutter.compileSdkVersion
1111
ndkVersion = flutter.ndkVersion
1212

13+
def flutterEnv = new Properties()
14+
def envFile = rootProject.file('.env')
15+
if (envFile.exists()) {
16+
envFile.withInputStream { stream ->
17+
flutterEnv.load(stream)
18+
}
19+
}
20+
1321
compileOptions {
1422
sourceCompatibility = JavaVersion.VERSION_1_8
1523
targetCompatibility = JavaVersion.VERSION_1_8
@@ -28,6 +36,10 @@ android {
2836
targetSdk = flutter.targetSdkVersion
2937
versionCode = flutter.versionCode
3038
versionName = flutter.versionName
39+
40+
manifestPlaceholders = [
41+
GOOGLE_MAPS_API_KEY: flutterEnv['GOOGLE_MAPS_API_KEY'] ?: ""
42+
]
3143
}
3244

3345
buildTypes {

android/app/src/main/AndroidManifest.xml

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
android:name="io.flutter.embedding.android.NormalTheme"
2121
android:resource="@style/NormalTheme"
2222
/>
23+
<meta-data
24+
android:name="com.google.android.geo.API_KEY"
25+
android:value="${GOOGLE_MAPS_API_KEY}" />
2326
<intent-filter>
2427
<action android:name="android.intent.action.MAIN"/>
2528
<category android:name="android.intent.category.LAUNCHER"/>

lib/main.dart

+21-110
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,36 @@
1+
import 'package:flutter/foundation.dart' show kIsWeb;
12
import 'package:flutter/material.dart';
3+
import 'package:flutter_dotenv/flutter_dotenv.dart';
4+
import 'dart:html' as html;
25

3-
void main() {
4-
runApp(const MyApp());
5-
}
6+
import 'router.dart';
67

7-
class MyApp extends StatelessWidget {
8-
const MyApp({super.key});
8+
Future<void> main() async {
9+
await dotenv.load(fileName: ".env");
910

10-
// This widget is the root of your application.
11-
@override
12-
Widget build(BuildContext context) {
13-
return MaterialApp(
14-
title: 'Flutter Demo',
15-
theme: ThemeData(
16-
// This is the theme of your application.
17-
//
18-
// TRY THIS: Try running your application with "flutter run". You'll see
19-
// the application has a purple toolbar. Then, without quitting the app,
20-
// try changing the seedColor in the colorScheme below to Colors.green
21-
// and then invoke "hot reload" (save your changes or press the "hot
22-
// reload" button in a Flutter-supported IDE, or press "r" if you used
23-
// the command line to start the app).
24-
//
25-
// Notice that the counter didn't reset back to zero; the application
26-
// state is not lost during the reload. To reset the state, use hot
27-
// restart instead.
28-
//
29-
// This works for code too, not just values: Most code changes can be
30-
// tested with just a hot reload.
31-
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
32-
useMaterial3: true,
33-
),
34-
home: const MyHomePage(title: 'Flutter Demo Home Page'),
35-
);
11+
if (kIsWeb) {
12+
final apiKey = dotenv.env['GOOGLE_MAPS_API_KEY'] ?? '';
13+
final script = html.ScriptElement()
14+
..type = 'text/javascript'
15+
..src = 'https://maps.googleapis.com/maps/api/js?key=$apiKey'
16+
..defer = true;
17+
html.document.head!.append(script);
3618
}
37-
}
38-
39-
class MyHomePage extends StatefulWidget {
40-
const MyHomePage({super.key, required this.title});
4119

42-
// This widget is the home page of your application. It is stateful, meaning
43-
// that it has a State object (defined below) that contains fields that affect
44-
// how it looks.
45-
46-
// This class is the configuration for the state. It holds the values (in this
47-
// case the title) provided by the parent (in this case the App widget) and
48-
// used by the build method of the State. Fields in a Widget subclass are
49-
// always marked "final".
50-
51-
final String title;
52-
53-
@override
54-
State<MyHomePage> createState() => _MyHomePageState();
20+
runApp(const MyApp());
5521
}
5622

57-
class _MyHomePageState extends State<MyHomePage> {
58-
int _counter = 0;
59-
60-
void _incrementCounter() {
61-
setState(() {
62-
// This call to setState tells the Flutter framework that something has
63-
// changed in this State, which causes it to rerun the build method below
64-
// so that the display can reflect the updated values. If we changed
65-
// _counter without calling setState(), then the build method would not be
66-
// called again, and so nothing would appear to happen.
67-
_counter++;
68-
});
69-
}
23+
class MyApp extends StatelessWidget {
24+
const MyApp({super.key});
7025

7126
@override
7227
Widget build(BuildContext context) {
73-
// This method is rerun every time setState is called, for instance as done
74-
// by the _incrementCounter method above.
75-
//
76-
// The Flutter framework has been optimized to make rerunning build methods
77-
// fast, so that you can just rebuild anything that needs updating rather
78-
// than having to individually change instances of widgets.
79-
return Scaffold(
80-
appBar: AppBar(
81-
// TRY THIS: Try changing the color here to a specific color (to
82-
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
83-
// change color while the other colors stay the same.
84-
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
85-
// Here we take the value from the MyHomePage object that was created by
86-
// the App.build method, and use it to set our appbar title.
87-
title: Text(widget.title),
88-
),
89-
body: Center(
90-
// Center is a layout widget. It takes a single child and positions it
91-
// in the middle of the parent.
92-
child: Column(
93-
// Column is also a layout widget. It takes a list of children and
94-
// arranges them vertically. By default, it sizes itself to fit its
95-
// children horizontally, and tries to be as tall as its parent.
96-
//
97-
// Column has various properties to control how it sizes itself and
98-
// how it positions its children. Here we use mainAxisAlignment to
99-
// center the children vertically; the main axis here is the vertical
100-
// axis because Columns are vertical (the cross axis would be
101-
// horizontal).
102-
//
103-
// TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
104-
// action in the IDE, or press "p" in the console), to see the
105-
// wireframe for each widget.
106-
mainAxisAlignment: MainAxisAlignment.center,
107-
children: <Widget>[
108-
const Text(
109-
'You have pushed the button this many times:',
110-
),
111-
Text(
112-
'$_counter',
113-
style: Theme.of(context).textTheme.headlineMedium,
114-
),
115-
],
116-
),
28+
return MaterialApp.router(
29+
title: 'Flutter Google Maps Demo',
30+
routerConfig: router,
31+
theme: ThemeData(
32+
primarySwatch: Colors.blue,
11733
),
118-
floatingActionButton: FloatingActionButton(
119-
onPressed: _incrementCounter,
120-
tooltip: 'Increment',
121-
child: const Icon(Icons.add),
122-
), // This trailing comma makes auto-formatting nicer for build methods.
12334
);
12435
}
12536
}

lib/router.dart

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import 'package:go_router/go_router.dart';
2+
import 'package:wiap_2/screens/direction_demo_screen.dart';
3+
import 'package:wiap_2/screens/mapstyle_demo_screen.dart';
4+
import 'package:wiap_2/screens/overlay_demo_screen.dart';
5+
import 'screens/home_screen.dart';
6+
import 'screens/pin_demo_screen.dart';
7+
import 'screens/drawing_demo_screen.dart';
8+
import 'screens/live_tracking_demo_screen.dart';
9+
import 'screens/place_search_demo_screen.dart';
10+
11+
final GoRouter router = GoRouter(
12+
initialLocation: '/',
13+
routes: [
14+
GoRoute(
15+
path: '/',
16+
builder: (context, state) => const HomeScreen(),
17+
),
18+
GoRoute(
19+
path: '/pin',
20+
builder: (context, state) => const PinDemoScreen(),
21+
),
22+
GoRoute(
23+
path: '/drawing',
24+
builder: (context, state) => const DrawingDemoScreen(),
25+
),
26+
GoRoute(
27+
path: '/live-tracking',
28+
builder: (context, state) => const LiveTrackingDemoScreen(),
29+
),
30+
GoRoute(
31+
path: '/overlays',
32+
builder: (context, state) => const OverlaysDemoScreen(),
33+
),
34+
GoRoute(
35+
path: '/custom-style',
36+
builder: (context, state) => const CustomMapStyleDemoScreen(),
37+
),
38+
GoRoute(
39+
path: '/place-search',
40+
builder: (context, state) => const PlaceSearchDemoScreen(),
41+
),
42+
GoRoute(
43+
path: '/directions',
44+
builder: (context, state) => const DirectionsDemoScreen(),
45+
),
46+
],
47+
);
+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:google_maps_flutter/google_maps_flutter.dart';
3+
4+
class DirectionsDemoScreen extends StatefulWidget {
5+
const DirectionsDemoScreen({super.key});
6+
7+
@override
8+
State<DirectionsDemoScreen> createState() => _DirectionsDemoScreenState();
9+
}
10+
11+
class _DirectionsDemoScreenState extends State<DirectionsDemoScreen> {
12+
late GoogleMapController _mapController;
13+
final LatLng _origin = const LatLng(-7.983908, 112.621391);
14+
final LatLng _destination = const LatLng(-7.9710, 112.6326);
15+
16+
Set<Marker> _markers = {};
17+
Set<Polyline> _polylines = {};
18+
19+
@override
20+
void initState() {
21+
super.initState();
22+
_markers.addAll([
23+
Marker(
24+
markerId: const MarkerId('origin'),
25+
position: _origin,
26+
infoWindow: const InfoWindow(title: 'Origin'),
27+
),
28+
Marker(
29+
markerId: const MarkerId('destination'),
30+
position: _destination,
31+
infoWindow: const InfoWindow(title: 'Destination'),
32+
),
33+
]);
34+
List<LatLng> route = [
35+
_origin,
36+
const LatLng(-7.9825, 112.6240),
37+
const LatLng(-7.9800, 112.6260),
38+
_destination,
39+
];
40+
_polylines.add(
41+
Polyline(
42+
polylineId: const PolylineId('route'),
43+
points: route,
44+
color: Colors.green,
45+
width: 5,
46+
),
47+
);
48+
}
49+
50+
void _onMapCreated(GoogleMapController controller) {
51+
_mapController = controller;
52+
}
53+
54+
@override
55+
Widget build(BuildContext context) {
56+
return Scaffold(
57+
appBar: AppBar(
58+
title: const Text('Directions Demo'),
59+
),
60+
body: GoogleMap(
61+
onMapCreated: _onMapCreated,
62+
initialCameraPosition: CameraPosition(
63+
target: _origin,
64+
zoom: 14,
65+
),
66+
markers: _markers,
67+
polylines: _polylines,
68+
),
69+
);
70+
}
71+
}

lib/screens/drawing_demo_screen.dart

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:google_maps_flutter/google_maps_flutter.dart';
3+
4+
class DrawingDemoScreen extends StatefulWidget {
5+
const DrawingDemoScreen({super.key});
6+
7+
@override
8+
State<DrawingDemoScreen> createState() => _DrawingDemoScreenState();
9+
}
10+
11+
class _DrawingDemoScreenState extends State<DrawingDemoScreen> {
12+
late GoogleMapController _mapController;
13+
14+
final List<LatLng> _points = [];
15+
final Set<Polyline> _polylines = {};
16+
final Set<Marker> _markers = {};
17+
18+
void _onMapCreated(GoogleMapController controller) {
19+
_mapController = controller;
20+
}
21+
22+
void _onTap(LatLng position) {
23+
setState(() {
24+
_points.add(position);
25+
_markers.add(
26+
Marker(
27+
markerId: MarkerId('marker_${_points.length}'),
28+
position: position,
29+
),
30+
);
31+
_polylines.clear();
32+
_polylines.add(
33+
Polyline(
34+
polylineId: const PolylineId('route'),
35+
points: _points,
36+
color: Colors.blue,
37+
width: 5,
38+
),
39+
);
40+
});
41+
}
42+
43+
void _clearDrawing() {
44+
setState(() {
45+
_points.clear();
46+
_markers.clear();
47+
_polylines.clear();
48+
});
49+
}
50+
51+
@override
52+
Widget build(BuildContext context) {
53+
return Scaffold(
54+
appBar: AppBar(
55+
title: const Text('Interactive Drawing Demo'),
56+
),
57+
body: GoogleMap(
58+
onMapCreated: _onMapCreated,
59+
initialCameraPosition: const CameraPosition(
60+
target: LatLng(-7.983908, 112.621391),
61+
zoom: 14.0,
62+
),
63+
onTap: _onTap,
64+
markers: _markers,
65+
polylines: _polylines,
66+
),
67+
floatingActionButton: FloatingActionButton(
68+
onPressed: _clearDrawing,
69+
tooltip: 'Clear Drawing',
70+
child: const Icon(Icons.clear),
71+
),
72+
);
73+
}
74+
}

0 commit comments

Comments
 (0)