How to send and receive arguments between views in flutter - android

I'm trying to send data from a page to another in flutter project, tried all methods I found in another question but all failed, here is my code :
The first page :
Navigator.pushNamed(context, '/line_details', arguments: {'line':line,});
The second page:
class _LineDetailsState extends State<LineDetails> {
Map data = {};
#override
Widget build(BuildContext context) {
data = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple,
title: Text("$data"),
),
);
}
}
note: the line is a custom object created.
the error : always returns null, even when tried to send a single string as {"test": "test string"} it returns a null too

your Example is working fine
route in MaterialApp
routes: { "/line_details": (context) => LineDetails(), },
Push on FlatButton:
onPressed: () => Navigator.pushNamed(context, '/line_details', arguments: {'line':'test',}),
class LineDetails
class LineDetails extends StatefulWidget {
#override
_LineDetailsState createState() => _LineDetailsState();
}
class _LineDetailsState extends State<LineDetails> {
Map data = {};
#override
Widget build(BuildContext context) {
data = ModalRoute.of(context).settings.arguments;
print(data);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple,
title: Text("$data"),
),
);
}
}
with GestureDetector is also working
new GestureDetector(
onTap: () => Navigator.pushNamed(context, '/line_details', arguments: {'line':'test',}),
child: new Container(child: new Text("GestureDetector"),),
),

try this:
Navigator.push(
context,
LineDetailsState(
builder: (context) => LineDetailsState(
line: line
)))
and
class LineDetailsState extends StatefulWidget {
LineDetailsState(this.line);
Line line;
#override
_LineDetailsState createState() => _LineDetailsState();
}
class _LineDetailsState extends State<LineDetails> {
Map data = {};
#override
Widget build(BuildContext context) {
data = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple,
title: Text("$data"),
),
);
}
}
instead of "Line" replace it with name of your custom object

Your example looks proper one other thing you can try is typecast your argument
like below which help dart for linting. Note this is not related that you are getting null
class LineDetails extends StatefulWidget {
#override
_LineDetailsState createState() => _LineDetailsState();
}
class _LineDetailsState extends State<LineDetails> {
Map data = {};
#override
Widget build(BuildContext context) {
data = ModalRoute.of(context).settings.arguments as Map<String,object>;
print(data);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple,
title: Text("$data"),
),
);
}
}

Related

Undefined name '_image'. Try correcting the name to one that is defined, or defining the name

Please help.
I'm trying to display the photo captured in 'Generated1Group1Widget1.dart' to 'GeneratedResultsWidget.dart'. However, 'main.dart' is having some errors.
GeneratedGroup1Widget1.dart
class GeneratedGroup1Widget1 extends StatefulWidget {
#override
_GeneratedGroup1Widget1State createState() => _GeneratedGroup1Widget1State();
}
class _GeneratedGroup1Widget1State extends State<GeneratedGroup1Widget1> {
XFile? _image;
Future _pickImage() async {
final imageSource = await showDialog<ImageSource>(
context: context,
builder: (context) => SimpleDialog(
title: const Text('Select Image Source'),
children: [
SimpleDialogOption(
onPressed: () => Navigator.pop(context, ImageSource.camera),
child: const Text('Camera'),
),
SimpleDialogOption(
onPressed: () => Navigator.pop(context, ImageSource.gallery),
child: const Text('Gallery'),
),
],
),
);
if (imageSource != null) {
final image = await ImagePicker().pickImage(source: imageSource);
setState(() {
_image = image;
});
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GeneratedResultsWidget(image: _image),
),
);
}
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => _pickImage(),
...
GeneratedResultsWidget.dart
class GeneratedResultsWidget extends StatelessWidget {
final XFile? image;
GeneratedResultsWidget({
required this.image,
});
#override
Widget build(BuildContext context) {
return Material(
child: ClipRRect(
...
main.dart
void main() {
runApp(food_classifierApp());
}
class food_classifierApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ScreenUtilInit(
designSize: Size(360, 640),
builder: (BuildContext context,child) => MaterialApp(
title: 'food-classifier',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/GeneratedHomepageWidget',
routes: {
'/GeneratedScanWidget': (context) => GeneratedScanWidget(),
'/GeneratedResultsWidget': (context) => GeneratedResultsWidget(image: _image),
'/GeneratedHomepageWidget': (context) => GeneratedHomepageWidget(),
'/GeneratedFoodlistWidget': (context) => GeneratedFoodlistWidget(),
},
),
);
}
}
Error
Undefined name '_image'.
Try correcting the name to one that is defined, or defining the name.
I already searched up google but I can't find answers to my question. Thanks in advance!
Where exactly you define _image variable in your food_classifierApp class?
You should use state management to access your image or ... in every where of your app
You need to create model to store your picked image file from GeneratedGroup1Widget1.
class AppModel {
String fileName;
AppModel(this.fileName);
}
Now you can call it from GeneratedGroup1Widget1
Navigator.pushNamed(context, '/GeneratedResultsWidget',
arguments: AppModel('your file or file name'));
And recieve it here
class GeneratedResultsWidget extends StatelessWidget {
const GeneratedResultsWidget({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguments as AppModel;
return Scaffold(body: Center(child: Text(args.fileName)));
}
}
Route should be
routes: {
//***
'/GeneratedResultsWidget': (context) => GeneratedResultsWidget(),
//***
}

Passing captured image between pages in flutter

I'm having problems with my code as I'm getting undefined_identifier errors.
I'm trying to pass the image I captured from 'GeneratedGroup1Widget1.dart' using 'flutter_screenutils' to 'GeneratedResultsWidget.dart'. However, my route in 'main.dart' doesn't define the image variable inside my parameter. I've been trying to fix this error for 10 hours now. Please help. Thanks in advance!
Error: (main.dart)
Undefined name 'image'.
Try correcting the name to one that is defined, or defining the name.
Here are my codes:
'GeneratedGroup1Widget1.dart'
class GeneratedGroup1Widget1 extends StatefulWidget {
#override
_GeneratedGroup1Widget1State createState() => _GeneratedGroup1Widget1State();
}
class _GeneratedGroup1Widget1State extends State<GeneratedGroup1Widget1> {
Future _pickImage() async {
final imageSource = await showDialog<ImageSource>(
context: context,
builder: (context) => SimpleDialog(
title: const Text('Select Image Source'),
children: [
SimpleDialogOption(
onPressed: () => Navigator.pop(context, ImageSource.camera),
child: const Text('Camera'),
),
SimpleDialogOption(
onPressed: () => Navigator.pop(context, ImageSource.gallery),
child: const Text('Gallery'),
),
],
),
);
if (imageSource != null) {
final image = await ImagePicker().pickImage(source: imageSource);
Navigator.pushNamed(context, '/GeneratedResultsWidget', arguments: image);
}
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => _pickImage(),
child: Container(
....
'GeneratedResultsWidget.dart'
class GeneratedResultsWidget extends StatelessWidget {
final XFile file;
const GeneratedResultsWidget({required Key key, required this.file})
: super(key: key);
#override
Widget build(BuildContext context) {
if (file == null) {
return Scaffold(body: Center(child: Text('No Image selected')));
} else {
return Scaffold(body: Center(child: Text(file.path)));
}
}
}
class GeneratedResultsWidget1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Material(
...
'main.dart'
void main() {
runApp(FoodClassifierApp());
}
class FoodClassifierApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ScreenUtilInit(
designSize: Size(360, 640),
builder: (BuildContext context, child) => MaterialApp(
title: 'food-classifier',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/GeneratedHomepageWidget',
routes: {
'/GeneratedScanWidget': (context) => GeneratedScanWidget(),
'/GeneratedResultsWidget': (context) =>
GeneratedResultsWidget(key: UniqueKey(), file: image),
'/GeneratedHomepageWidget': (context) => GeneratedHomepageWidget(),
'/GeneratedFoodlistWidget': (context) => GeneratedFoodlistWidget(),
},
),
);
}
}
This is my first time coding in flutter and I used figma to generate my widgets.

Pass variables from page to another page. Flutter/Dart

I have some variables in one page and i want to pass it to another page when navigate.
first page codes with variables:
int groupValue = -1;
int idButton = 0;
onTap: (){
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => SearchResault(),
settings: RouteSettings(
arguments: {
IdButton,
groupValue
}
)
));
},
the problem is that every time i get {-1,0} but i want to choose what i want to RECIVE.
EDITED
This is the edited code down here:
You can just pass the argument through the constructor of your widget, as such:
Navigator.of(context).push(
MaterialPageRoute(builder:
(BuildContext context) =>
SearchResault(idButton: IdButton, groupValue: groupValue),
),
);
You can then define your stateless widget :
class SearchResault extends StatelessWidget {
final int idButton;
final int groupValue;
const SearchResault({this.idButton, this.groupValue});
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Text("${idButton} - ${groupValue}")
);
}
}
You can just pass the argument through the constructor of your widget, as such:
Navigator.of(context).push(
MaterialPageRoute(builder:
(BuildContext context) =>
SearchResault(idButton: IdButton, groupValue: groupValue),
),
);
You can then define your stateless widget :
class SearchResault extends StatelessWidget {
final int idButton;
final int groupValue;
const SearchResault({this.idButton, this.groupValue});
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Text("${idButton} - ${groupValue}")
);
}
}

The argument type SearchBar can't be assigned to the parameter type Widget in flutter

I'm trying to implement an automatic Search Bar in Flutter.
When compiling I get the error: The argument type 'SearchBar' can't be assigned to the parameter type 'Widget?'.
class Home extends StatelessWidget {
Future<List<Post>> search(String search) async {
await Future.delayed(Duration(seconds: 2));
return List.generate(search.length, (int index) {
return Post(
"Title : $search $index",
"Description :$search $index",
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: SearchBar<Post>(
onSearch: search,
onItemFound: (Post post, int index) {
return ListTile(
title: Text(post.title),
subtitle: Text(post.description),
);
},
),
),
),
);
}
}
From the official Documentation, you need to call the build method to get a widget.
However, it would be better if you create your SearchBar inside your constructor itself, so that a new one doesn't get created every time.
From the official documentation,
class _MyHomePageState extends State<MyHomePage> {
SearchBar searchBar;
AppBar buildAppBar(BuildContext context) {
return new AppBar(
title: new Text('My Home Page'),
actions: [searchBar.getSearchAction(context)]
);
}
_MyHomePageState() {
searchBar = new SearchBar(
inBar: false,
setState: setState,
onSubmitted: print,
buildDefaultAppBar: buildAppBar
);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: searchBar.build(context)
);
}
}

Pass value from state of stateful class to different widget?

I have a function:
class LoginPage extends StatefulWidget {
static const routeName = '/auth';
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
Inside class _LoginPageState extends State I have a bool variable 'registered' that changes within setState to true when user registers for the first time. How can I pass this value to my main function whenever it gets changed? Additionally, this variable needs to be changed from different place as well to true. Based on it I wanna show different screen to my user - something like below:
home: Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
child: registered ? OnboardingPage() : HomePage(),
),
),
Could you show me some code or guide me? Thanks for any help!
Your Login page
class LoginPage extends StatefulWidget {
LoginPage({Key key}) : super(key: key);
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
bool registered;
// ...
void gotoSecondPage() {
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => SecondPage(registered),));
}
}
Your other page
class SecondPage extends StatefulWidget {
bool registered;
SecondPage(this.registered);
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Container(
child: widget.registered ? OnboardingPage() : HomePage(),
),
);
}
}
If this variable is changed inside _LoginPageState you can redirect the user according to its value as below:
// BEGIN: TODO
// registered = true;
// END: TODO
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => registered ? OnboardingPage() : HomePage()),
);
You can use a combination of StreamBuilder and Provider to first get the data asynchronously, and then send that data to different places in your widget tree. Something like:
final StreamController _controller = StreamController();
// Provide this _controller in your top level widget tree
return Provider<StreamController>(
create: (context) => _controller,
child: MaterialApp(...),
);
In your _LoginPageState, whenever you get a new registered value:
// ... other lines
var registered = async getUserRegisterStatus() // sample method
// Add the new value to Stream
Provider.of<StreamController>.add(registered);
You can then use this controller to notify any below widget of the change of value:
// Sample place that needs the value
home: Scaffold(
resizeToAvoidBottomInset: false,
body: StreamBuilder<bool>(
initialValue: false
stream: Provider.of<StreamController>.stream,
builder: (context, snapshot) {
if (!snapshot.hasData) return Container(child: CircularProgressIndicator());
var registered = snapshot.data;
return Container(
child: registered ? OnboardingPage() : HomePage(),
);
}
),
),

Categories

Resources