Related
I am a beginner with flutter, I had just started a few days ago. I want to go from one page to another page . But when I use the navigator it shows an error.
I've tried to solve it using some answers to similar problems on stack overflow, but I can't solve it. Also, I am not able to understand those properly.
These are some of them:
Undefined name 'context'
_buildDrawer() {
return ClipPath(
clipper: OvalRightBorderClipper(),
child: Drawer(
child: Container(
padding: const EdgeInsets.only(left: 16.0, right: 40),
decoration: BoxDecoration(
color: primary, boxShadow: [BoxShadow(color: Colors.black45)]),
width: 300,
child: SafeArea(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
alignment: Alignment.centerRight,
child: IconButton(
icon: Icon(
Icons.power_settings_new,
color: active,
),
onPressed: () {},
),
),
Container(
height: 90,
alignment: Alignment.center,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient:
LinearGradient(colors: [Colors.pink, Colors.red])),
child: CircleAvatar(
radius: 40,
backgroundImage: NetworkImage(profile),
),
),
SizedBox(height: 5.0),
Text(
"Mohd Amin bin Yaakob",
style: TextStyle(color: Colors.white, fontSize: 18.0),
),
Text(
"Pegawai",
style: TextStyle(color: active, fontSize: 16.0),
),
SizedBox(height: 30.0),
_buildRow(Icons.home, "Home", () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) {
return HomePageWidgetPage();
},
),
);
}),
_buildDivider(),
_buildRow(Icons.home, "Home", () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) {
return HomePageWidgetPage();
},
),
);
}),
_buildDivider(),
_buildRow(Icons.home, "Home", () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) {
return HomePageWidgetPage();
},
),
);
}),
_buildDivider(),
_buildRow(Icons.home, "Home", () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) {
return HomePageWidgetPage();
},
),
);
}),
_buildDivider(),
_buildRow(Icons.home, "Home", () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) {
return HomePageWidgetPage();
},
),
);
}),
_buildDivider(),
],
),
),
),
),
),
);
}
Divider _buildDivider() {
return Divider(
color: active,
);
}
Widget _buildRow(IconData icon, String title, VoidCallback onTap) {
final TextStyle tStyle = TextStyle(color: active, fontSize: 16.0);
return InkWell(
child: Container(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row(
children: [
Icon(
icon,
color: active,
),
SizedBox(width: 10.0),
Text(
title,
style: tStyle,
),
],
),
),
onTap: onTap,
);
}
}
Undefined name 'context' in flutter navigation
You can pass the context like
_buildDrawer(BuildContext context){
And the place you call this method
_buildDrawer(context)
There was a problem with my code, while I was trying to exit a screen of mine from my bus tracking app main page but this is showing an error. I have tried importing everything given in StackOverflow.
help me to get this solved please
import 'dart:js';
import 'package:flutter/services.dart';
import 'registration_screen.dart';
import 'login_screen.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:path/path.dart';
class WelcomePage extends StatelessWidget {
From here the function starts
Future<bool?> _onBackPressed() async {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(`enter code here`
title: Text('Do you want to exit?'),
actions: <Widget>[
TextButton(
child: Text('No'),
onPressed: () {
Navigator.of(context).pop(false);
},
),
TextButton(
child: Text('Yes'),
onPressed: () {
Navigator.of(context).pop(true);
SystemNavigator.pop();
},
),
],
);
}
);
}
Scaffold start here also the WillPopScope starts here which returns the _onBackPressed();
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
bool? result = await _onBackPressed();
if (result == null) {
result = false;
}
return result;
},
child: Scaffold(
// return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
children: [
Flexible(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 20,
),
Lottie.asset('assets/images/bus.json'),
SizedBox(
height: 20,
),
Text(
"Welcome to \n Bus Tracking",
style: GoogleFonts.poppins(
fontSize: 34, fontWeight: FontWeight.w700),
textAlign: TextAlign.center,
),
],
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 38),
child: Container(
height: 65,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
spreadRadius: 2,
blurRadius: 3,
offset: Offset(0, 5))
],
color: Colors.deepPurple,
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Expanded(
child: GestureDetector(
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) =>
RegistrationScreen()));
},
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: Colors.deepPurple,
width: 0.9,
)
//textColor: Colors.black87,
),
child: const Center(
child: Text(
'Register',
style: TextStyle(
color: Colors.deepPurple,
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
),
),
),
),
Expanded(
child: GestureDetector(
//bgColor: Colors.transparent,
//buttonName: 'Sign In',
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => LoginScreen(),
));
},
child: Container(
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: Colors.deepPurple,
width: 0.9,
)
//textColor: Colors.black87,
),
child: const Center(
child: Text(
'Login',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
),
),
),
),
],
),
),
),
],
),
),
),
));
}
}
Change the function _onBackPressed as
Future<bool?> _onBackPressed(BuildContext ctx) async {
return showDialog(
context: ctx,
builder: (BuildContext context) {
return AlertDialog(`enter code here`
title: Text('Do you want to exit?'),
actions: <Widget>[
TextButton(
child: Text('No'),
onPressed: () {
Navigator.of(context).pop(false);
},
),
TextButton(
child: Text('Yes'),
onPressed: () {
Navigator.of(context).pop(true);
SystemNavigator.pop();
},
),
],
);
}
);
}
Now in the build function use :
bool? result = await _onBackPressed(context);
context is getting clashed may de due to import 'package:path/path.dart'; if you don't need it remove it.
Here in the question i have been using a stateless widget but I need to use a stateful widget, so the solution is to create a new file as a stateful widget and dumb all this code in it and the error was solved.
On my login screen : user is asked to type in login and password. I save these value in two variables : email and password. Then the user must tap a button to actually log in.
The problem is that for some reason (that I really can't figure out...) email and password are always empty when user hits the button....
Here's the full code :
class SeConnecterScreen extends StatelessWidget {
static const String id = 'se_connecter_screen';
#override
Widget build(BuildContext context) {
var uD = Provider.of<UdProvider>(context);
String email = '';
String passWord = '';
final Connectivity _connectivity = Connectivity();
var scaffold = Scaffold(
extendBody: true,
extendBodyBehindAppBar: true,
backgroundColor: Colors.indigo[900],
body: Column(
children: [
Expanded(
flex: 4,
child: Container(
margin: const EdgeInsets.only(bottom: 12),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/start2.jpg'), fit: BoxFit.cover),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(50),
),
),
height: MediaQuery.of(context).size.height / 4,
),
),
Expanded(
flex: 6,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
height: MediaQuery.of(context).size.height -
(MediaQuery.of(context).size.height / 4),
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
width: 1.0,
color: Colors.white,
),
borderRadius: BorderRadius.circular(10.0),
),
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Text(
'WORD CHAMPIONS',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.indigo[900],
fontSize: 28.0,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 50,
),
TextField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
focusColor: Colors.white,
border: OutlineInputBorder(),
labelText: 'Tape ton adresse email'),
onChanged: (value) {
email = value;
print(email);
},
),
SizedBox(
height: 25.0,
),
TextField(
obscureText: true,
keyboardType: TextInputType.name,
decoration: InputDecoration(
focusColor: Colors.white,
border: OutlineInputBorder(),
labelText: 'Tape ton mot de passe'),
onChanged: (value) {
passWord = value;
print(passWord);
},
),
SizedBox(
height: 35.0,
),
ElevatedButton.icon(
label: Text('Se connecter'),
icon: Icon(Icons.library_add_check_rounded),
style: ElevatedButton.styleFrom(
minimumSize: Size(30, 45),
primary: Colors.green[800],
onPrimary: Colors.white,
),
onPressed: () async {
print('Email : $email');
print('passWord : $passWord');
if (await _connectivity.checkConnectivity() ==
ConnectivityResult.none) {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text(
'Oups!',
style: TextStyle(fontSize: 22.0),
),
content: Text(
'Il faut te connecter à Internet !',
style: TextStyle(fontSize: 18.0),
),
actions: [
TextButton(
onPressed: () {
Navigator.pushReplacementNamed(
context, StartingScreen.id);
},
child: Text(
'OK',
style: TextStyle(fontSize: 18.0),
),
),
],
),
);
} else {
String accountVerif =
await uD.checkAccountId(email, passWord);
if (accountVerif == '') {
DialogBuilder(context).showLoadingIndicator(
text: 'Téléchargement des bases',
color: Colors.black45);
await uD.downLoadUserInfo(email);
DialogBuilder(context).hideOpenDialog();
Navigator.pushReplacementNamed(
context, ProfileScreen.id);
} else {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text(
'Oups!',
style: TextStyle(fontSize: 22.0),
),
content: Text(
'Ce compte n\'existe pas, ou le mot de passe est incorrect.',
style: TextStyle(fontSize: 18.0),
),
actions: [
TextButton(
onPressed: () {
Navigator.pushReplacementNamed(
context, StartingScreen.id);
},
child: Text(
'OK',
style: TextStyle(fontSize: 18.0),
),
),
],
),
);
}
}
}),
],
),
),
),
),
)),
],
),
);
return scaffold;
}
}
Please Try to define you password and email variables outside build method. It may solve issue.
See it works for me, May be you should do
stop execution
run 'flutter clean'
run 'flutter pub get'
execute it
Define the variables just below the override instead of below the build method
Add the textediting controller to it
so that your problem will be solved
Flutter & AlertDialog : My app doesn't show the alert dialog after loading.
Even the 2 prints before and after the alert dialog was printed, the dialog was skip. Why is that? Please help me with this.
onTap: () async {
if (_formKey.currentState.validate() &&
_ratingStar > 0) {
setState(() {
_loading = true;
});
dynamic result =
await User_DatabaseService().uploadFeedback(
comment: review );
setState(() {
_loading = false;
});
if (result) {
print('Before dialog');
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(6.0))),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(
vertical: 60, horizontal: 10),
child: Text(
//'Please rate with star',
'평가해 주셔서 감사합니다!',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
InkWell(
onTap: () {
Navigator.pop(context);
},
child: Container(
alignment: Alignment.center,
height: 50,
//color: primaryColor,
child: Text(
AppLocalizations.of(context)
.translate('OKAY'),
style: TextStyle(
color: Colors.white,
fontWeight:
FontWeight.bold),
),
),
),
],
),
);
},
);
print('After dialog');
Navigator.pop(context);
} else {
print('Sth wrong');
}
} else {
print('Not submit');
}
},
Please have a look on my code and tell me what's wrong. Thank you. I am looking forward to hearing from you.
Here is the problem:
if (result) {
print('Before dialog');
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(6.0))),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(
vertical: 60, horizontal: 10),
child: Text(
//'Please rate with star',
'평가해 주셔서 감사합니다!',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
InkWell(
onTap: () {
Navigator.pop(context);
},
child: Container(
alignment: Alignment.center,
height: 50,
//color: primaryColor,
child: Text(
AppLocalizations.of(context)
.translate('OKAY'),
style: TextStyle(
color: Colors.white,
fontWeight:
FontWeight.bold),
),
),
),
],
),
);
},
);
print('After dialog');
Navigator.pop(context);
} else {
print('Sth wrong');
}
You are presenting the dialogue, then popping it. Make sure to add the Navigator.pop(context) method, only after you click a button on the alert dialogue. So, rewrite the code like this:
if (result) {
print('Before dialog');
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(6.0))),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(
vertical: 60, horizontal: 10),
child: Text(
//'Please rate with star',
'평가해 주셔서 감사합니다!',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
InkWell(
onTap: () {
Navigator.pop(context);
},
child: Container(
alignment: Alignment.center,
height: 50,
//color: primaryColor,
child: Text(
AppLocalizations.of(context)
.translate('OKAY'),
style: TextStyle(
color: Colors.white,
fontWeight:
FontWeight.bold),
),
),
),
],
),
);
},
);
print('After dialog');
} else {
print('Sth wrong');
}
The issue lies in the line just after the print('After dialog') line. You are doing a Navigator.pop(context); which is basically removing the dialog from the navigation stack.
In flutter:
The showDialog() is used to show the dialog. And the Navigator.pop(context) is used to remove the dialog
I want my app to create a ListView.builder with user's data that are fetched from backend API with provider and http package.
Provider's Method For Fetching data (Works fine now):
Future<List<User>> fetchUsersList() async {
var resp = await UserService().getAllUsers();
if (resp.statusCode == 200) {
return userListFromJson(resp.body);
} else {
decodeErrorMessage(resp);
return _usersList = [];
}
}
My Code for Creating the ListView.builder:
class _StaffViewState extends State<StaffView> {
bool _searchaMode = false;
bool _fetchingData = false;
List<User> _userList = List<User>();
#override
Widget build(BuildContext context) {
Provider.of<UserProvider>(context).fetchUsersList().then(
(data) => this._userList = data);
return Consumer<UserProvider>(
builder: (context, providerData, _) => Scaffold(
appBar: AppBar(
title: _searchaMode == false
? Text('Staff\s List')
: TextField(
autofocus: true,
cursorColor: Colors.white,
onSubmitted: (String value) async {
await showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Thanks!'),
content: Text('You typed "$value".'),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('OK'),
),
],
);
},
);
},
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
hintText: 'Search . . .',
hintStyle: TextStyle(color: Colors.white),
border: InputBorder.none,
),
),
actions: [
_searchaMode == false
? IconButton(
onPressed: () {
setState(() {
_searchaMode = true;
});
},
icon: Icon(Icons.search),
)
: IconButton(
onPressed: () {
setState(() {
_searchaMode = false;
});
},
icon: Icon(
Icons.cancel,
color: Colors.tealAccent,
),
),
RaisedButton.icon(
onPressed: () async {},
color: Colors.yellow.shade900,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(100.0),
topLeft: Radius.circular(100.0),
),
),
icon: Icon(
Icons.add,
size: 25.0,
color: Colors.white,
),
label: Text(
'Add User',
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
],
),
drawer: AppSideNav(),
body: _fetchingData == true
? pr.show()
: ListView.builder(
itemCount: _userList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: .9,
color: Colors.yellow.shade700,
),
),
),
child: ListTile(
leading: Image.network(
providerData.getUsersList()[index].image != null
? providerData.getUsersList()[index].image
: 'https://via.placeholder.com/150'),
title: Center(
child:
Text(providerData.getUsersList()[index].email)),
subtitle: Center(
child: Text(providerData.getUsersList()[index].nid)),
trailing:
providerData.getUsersList()[index].isAuthority == true
? Text('Authority')
: providerData.getUsersList()[index].isStaff ==
true
? Text('Staff')
: Text('General User'),
contentPadding: EdgeInsets.symmetric(horizontal: 20.0),
visualDensity: VisualDensity.adaptivePlatformDensity,
isThreeLine: false,
onTap: () {},
),
);
},
),
),
);
}
}
My Data is loading to build the list. But the problem is an error occurs that says
setState() or markNeedsBuild() called during build.
My question is what is the actual way of populating data with the provider package where the dataFetching method will be executed first and than the list will be build.
Instead of calling your fetch function at the start of the build function or in the initState function, you can simply use the FutureBuilder widget. This way you can specify exactly what to show when it is still loading and what when finished, without adding more and more member variables.
Your modified code could then look like this:
class _StaffViewState extends State<StaffView> {
bool _searchaMode = false;
#override
Widget build(BuildContext context) {
return Consumer<UserProvider>(
builder: (context, providerData, _) => FutureBuilder(
future: providerData.fetchUsersList(),
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return Text("Loading...");
}
List<User> userList = snapshot.data;
return Scaffold(
appBar: AppBar(
title: _searchaMode == false
? Text('Staff\s List')
: TextField(
autofocus: true,
cursorColor: Colors.white,
onSubmitted: (String value) async {
await showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Thanks!'),
content: Text('You typed "$value".'),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('OK'),
),
],
);
},
);
},
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
hintText: 'Search . . .',
hintStyle: TextStyle(color: Colors.white),
border: InputBorder.none,
),
),
actions: [
_searchaMode == false
? IconButton(
onPressed: () {
setState(() {
_searchaMode = true;
});
},
icon: Icon(Icons.search),
)
: IconButton(
onPressed: () {
setState(() {
_searchaMode = false;
});
},
icon: Icon(
Icons.cancel,
color: Colors.tealAccent,
),
),
RaisedButton.icon(
onPressed: () async {},
color: Colors.yellow.shade900,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(100.0),
topLeft: Radius.circular(100.0),
),
),
icon: Icon(
Icons.add,
size: 25.0,
color: Colors.white,
),
label: Text(
'Add User',
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
],
),
drawer: AppSideNav(),
body: ListView.builder(
itemCount: userList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: .9,
color: Colors.yellow.shade700,
),
),
),
child: ListTile(
leading: Image.network(
providerData.getUsersList()[index].image != null
? providerData.getUsersList()[index].image
: 'https://via.placeholder.com/150'),
title: Center(
child: Text(
providerData.getUsersList()[index].email)),
subtitle: Center(
child:
Text(providerData.getUsersList()[index].nid)),
trailing: providerData
.getUsersList()[index]
.isAuthority ==
true
? Text('Authority')
: providerData.getUsersList()[index].isStaff ==
true
? Text('Staff')
: Text('General User'),
contentPadding:
EdgeInsets.symmetric(horizontal: 20.0),
visualDensity: VisualDensity.adaptivePlatformDensity,
isThreeLine: false,
onTap: () {},
),
);
},
),
);
},
),
);
}
}
#override
void initState() {
super.initState();
use api here
}
You shouldn't call the API inside build as you will have a new call each time the framework rebuilds the screen, instead call it inside initState().
If you need to wait for the API data, then use a FutureBuilder in your build function so it will rebuild automatically once the data has been retrieved.