I have a problem with my app...
I want only pass two 'double' arguments to widget in others pages when user using ElevatedButton and recover arguments for set coordonate in Maps.
I tried all the ways to do it by reading the doc on Flutter.dev but nothing the value I get is Null...
Main.dart :
import 'package:flutter/material.dart';
import 'package:booki3/route/route.dart' as route;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Booking',
theme: ThemeData(
primarySwatch: Colors.blue,
),
onGenerateRoute: route.controller,
initialRoute: route.home,
);
}
}
Home.dart :
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:booki3/views/maps.dart';
import 'package:booki3/route/route.dart' as route;
const dgreen = Color(0xFF54D3C2);
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const MyAppBar(),
body: SingleChildScrollView(
child: Column(
children: [
const SearchSection(),
HotelSection(),
],
),
));
}
}
class Data {
double coordx = 45.20;
double coordy = 20.50;
}
class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
const MyAppBar({Key? key}) : super(key: key);
@override
Size get preferredSize => const Size.fromHeight(50);
@override
Widget build(BuildContext context) {
return AppBar(
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.grey[800],
size: 20,
),
onPressed: null,
),
title: Text(
'Explore',
style: GoogleFonts.nunito(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.w800,
),
),
centerTitle: true,
actions: [
IconButton(
icon: Icon(
Icons.favorite_outline_rounded,
color: Colors.grey[800],
size: 20,
),
onPressed: null,
),
IconButton(
icon: Icon(
Icons.place,
color: Colors.grey[800],
size: 20,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const MyMaps(data: Data),
),
);
},
),
],
backgroundColor: Colors.white,
);
}
}
Maps.dart :
Line 25, I put random values because otherwise the page won't open... In the end, I want to put the values of Data. But so far I can't get them back.
import 'package:booki3/views/home.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class MyMaps extends StatefulWidget {
const MyMaps({Key? key, required data}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyMaps> {
late GoogleMapController mapController;
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
@override
Widget build(BuildContext context) {
final data = ModalRoute.of(context)!.settings.arguments as Data;
debugPrint(data.toString());
LatLng _center = const LatLng(25.32, 2.5); // <= Two 'double' of Data..
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Maps Sample App'),
backgroundColor: Colors.green[700],
),
body: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
),
),
);
}
}
Route.dart :
import 'package:flutter/material.dart';
import 'package:booki3/views/home.dart';
import 'package:booki3/views/maps.dart';
const String home = "home";
const String maps = "maps";
Route<dynamic> controller(RouteSettings settings) {
switch (settings.name) {
case home:
return MaterialPageRoute(builder: (context) => const HomePage());
case maps:
return MaterialPageRoute(
builder: (context) => const MyMaps(
data: Data,
),
settings: const RouteSettings(
arguments: Data,
),
);
default:
throw ('This route name not exist');
}
}
With solution's Daniel, I have this error message : Error Message
New Home.dart :
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:booki3/views/maps.dart';
import 'package:booki3/route/route.dart' as route;
const dgreen = Color(0xFF54D3C2);
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const MyAppBar(),
body: SingleChildScrollView(
child: Column(
children: [
const SearchSection(),
HotelSection(),
],
),
));
}
}
class Data {
double coordx = 45.20;
double coordy = 20.50;
@override
String toString() => 'Data(coordx: $coordx, coordy: $coordy)'; // just to prin
}
class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
const MyAppBar({Key? key}) : super(key: key);
@override
Size get preferredSize => const Size.fromHeight(50);
@override
Widget build(BuildContext context) {
return AppBar(
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.grey[800],
size: 20,
),
onPressed: null,
),
title: Text(
'Explore',
style: GoogleFonts.nunito(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.w800,
),
),
centerTitle: true,
actions: [
IconButton(
icon: Icon(
Icons.favorite_outline_rounded,
color: Colors.grey[800],
size: 20,
),
onPressed: null,
),
IconButton(
icon: Icon(
Icons.place,
color: Colors.grey[800],
size: 20,
),
onPressed: () {
Navigator.of(context).pushNamed(
route.maps,
arguments: Data,
);
},
),
],
backgroundColor: Colors.white,
);
}
}
New Route.dart :
import 'package:flutter/material.dart';
import 'package:booki3/views/home.dart';
import 'package:booki3/views/maps.dart';
const String home = "home";
const String maps = "maps";
Route<dynamic> controller(RouteSettings settings) {
final args = settings.arguments; // get the arguments here
switch (settings.name) {
case home:
return MaterialPageRoute(builder: (context) => const HomePage());
case maps:
return MaterialPageRoute(
builder: (context) => MyMaps(
data: args as Data,
),
);
default:
throw ('This route name not exist');
}
}
New Maps.dart :
import 'package:booki3/views/home.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class MyMaps extends StatefulWidget {
const MyMaps({
Key? key,
required this.data,
}) : super(key: key);
final Data data;
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyMaps> {
late GoogleMapController mapController;
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
@override
Widget build(BuildContext context) {
final data = widget.data;
debugPrint(data.toString());
LatLng _center = LatLng(data.coordx, data.coordy);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Maps Sample App'),
backgroundColor: Colors.green[700],
),
body: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
),
),
);
}
}
Thank you in advance for your help because I don't know what to do anymore.. I feel like I have tried everything..
Love to you ;)
CodePudding user response:
Ok, let's go step by step, in the Data class I only put the toString so that when you print it the values are displayed (nothing revealing).
The problem comes when you want to send ALL the class to the page Maps which is not possible (in this case), what you have to send is an instance of that class, therefore we create it.
On the other hand you will use pushNamed since you yourself are telling it that they are called "home", or "maps" in the routes, so we are going to use them, not to create another MaterialPageRoute if they are already in your routes, you got it?
Home :
class Data {
double coordx = 45.20;
double coordy = 20.50;
@override
String toString() => 'Data(coordx: $coordx, coordy: $coordy)'; // just to print
}
class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
const MyAppBar({Key? key}) : super(key: key);
@override
Size get preferredSize => const Size.fromHeight(50);
@override
Widget build(BuildContext context) {
final newData = Data(); // new instance creation
return AppBar(
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.grey[800],
size: 20,
),
onPressed: null,
),
title: const Text(
'Explore',
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.w800,
),
),
centerTitle: true,
actions: [
IconButton(
icon: Icon(
Icons.favorite_outline_rounded,
color: Colors.grey[800],
size: 20,
),
onPressed: null,
),
IconButton(
icon: Icon(
Icons.place,
color: Colors.grey[800],
size: 20,
),
onPressed: () {
Navigator.of(context).pushNamed( // using pushNamed not push
"maps",
arguments: newData, // send the instance
);
},
),
],
backgroundColor: Colors.white,
);
}
}
Routes :
Route<dynamic> controller(RouteSettings settings) {
final args = settings.arguments; // get the arguments here
switch (settings.name) {
case home:
return MaterialPageRoute(builder: (context) => const HomePage());
case maps:
return MaterialPageRoute(
builder: (context) => MyMaps( // we delete the settings and pass directly in the MyMaps
data: args as Data,
),
);
default:
throw ('This route name not exist');
}
}
Finally, once the instance is created, then sent by the arguments to the routes and finally arriving here, to obtain that instance, we simply add the final variable and in its constructor.
And the only thing left to do is to put it in your LatLng ! :D
Maps :
class MyMaps extends StatefulWidget {
const MyMaps({
Key? key,
required this.data, // here in constructor
}) : super(key: key);
final Data data; // final variable
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyMaps> {
late GoogleMapController mapController;
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
@override
Widget build(BuildContext context) {
final data = widget.data; // get the data that comes
debugPrint(data.toString());
LatLng _center = LatLng(
data.coordx,
data.coordy,
); // voila !
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Maps Sample App'),
backgroundColor: Colors.green[700],
),
body: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
),
),
);
}
}
CodePudding user response:
To support null, you need to convert
final data = ModalRoute.of(context)!.settings.arguments as Data;
to
final data = ModalRoute.of(context)!.settings.arguments as Data?;