navigator operation requested with a context that does not include a navigator statefulwidget [duplicate] - button

This question already has answers here:
Navigator operation requested with a context that does not include a Navigator
(18 answers)
Closed 4 years ago.
I am working on the Flutter code that follows. I have issues with the second button called "Regitrese". Every place I have looked work with statelesswidgets so I'm not sure how to fix it. I tried changing the void to put on it home: MyHomePage() and put MyHomePage to statefull instead of taking the statefull from MyApp bus it shows a mistake Missing concrete implementation of StatefulWidget.createState. I am not sure how is it supposed to go. Can you make a button work in a StatefulWidget? Is there a trick I am not seeing?
void main()=> runApp(new MyApp());
class MyApp extends StatefulWidget{
#override
State<StatefulWidget> createState(){
return new MyHomePage();
}
}
class MyHomePage extends State<MyApp>{
final TextEditingController rutController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
var _rut, _password;
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new Container(
padding: const EdgeInsets.all(50.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFormField(
controller: this.rutController,
decoration: InputDecoration(
labelText: 'Rut',
hintText: 'eg. 154683265',
suffixIcon: IconButton(
icon: Icon(Icons.clear),
onPressed: () {
rutController.clear();
}
)
),
),
TextFormField(
controller: this.passwordController,
decoration: InputDecoration(
labelText: 'ContraseƱa',
hintText: 'ContraseƱa',
suffixIcon: IconButton(
icon: Icon(Icons.clear),
onPressed: () {
passwordController.clear();
},
)
),
obscureText: true,
),
RaisedButton(
onPressed: (){
loginButton(rut: this.rutController.text, password: this.passwordController.text);
},
child: Text('Login'),
),
RaisedButton(
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(builder(context)=>SelectUserPage())
)
},
child: Text('Registrese'),
),
],
),
),
),
);
}
}
class SelectUserType extends StatelessWidget{
#override
Widget build(BuildContext context){
return new Container(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: (){
//Do something
},
child: Text(''),
),
RaisedButton(
onPressed: (){
//Do something
},
child: Text(''),
),
],
),
);
}
}

The thing is that you need to access a context below the MaterialApp widget that adds the Navigator to the tree. If you look at your code the context is above it.
One way to solve it is to move a part of the tree to another widget.
Or you can use a Builder around your button or around the Column as in the following code:
Builder(
builder: (context) => RaisedButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) => SelectUserType()));
},
child: Text('Registrese'),
),
),

Related

No RaisedButton

Code doesn't work
Try to implement an ElevatedButton.
Someone have a idea?
I don't know how to fix it...
class _MyStatefullWidgetState extends State<MyStatefullWidget>{
get raisedButtonStyle => null;
#override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: Center(
child: ElevatedButton(
style: raisedButtonStyle,
child: Text("Klick mich", textDirection: TextDirection.ltr),
onPressed: () {
print("Hallo");
},
),
),
);

Flutter/Firebase - Right Track?

At 54 I'm self-learning Flutter and have come a long way. I am stuck (again) with a speed-bump concerning my implementation of Firebase. Although I am getting the very basic of displaying a line of data for each record the problem is getting to the details of each record. I believe the issue is that I am not referencing the record ID.
When looking at endless examples I also believe my code to display a ListView of records is bloated making it more difficult to grab a record and display all fields (edit screen).
I want to click the "Walsh-Test" links to view all fields and update. I can create a new edit/update screen my initial problem is opening the screen to the selected record.
Any advice would be greatly appreciated.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/rendering.dart';
class MeterReadHomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Color(0xff4367b1),
automaticallyImplyLeading: false,
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Icon(
Icons.arrow_back,
color: Colors.white,
),
),
title: Text(
"WelakaOne",
style: TextStyle(
color: Colors.white,
),
),
),
body: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('meter_reads')
.orderBy('accountname')
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return Padding(
padding: const EdgeInsets.fromLTRB(6, 20, 0, 0),
child: Container(
child: GestureDetector(
onTap: () {},
child: ListView(
children: snapshot.data.docs.map(
(document) {
return Row(
children: [
Container(
width: 50,
child: Icon(
Icons.access_alarm,
size: 36,
color: Color(0xff4367b1),
),
),
Container(
child: Text(
document['accountname'],
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xff4367b1),
),
),
),
SizedBox(height: 44),
],
);
},
).toList(),
),
),
),
);
},
),
);
}
}
[![Flutter/Firebase/Open to Selected Record][1]][1]
I understand that you want to go to another page (Edit Screen) onTapping the alarm tile.
So, my suggestion is to use A ListTile widget instead of the row widget you are using.
You can read about ListTile's onTap property, here
Regarding your routing to a new screen/page, you'll have to make use of MaterialPageRoute to create a new route and using Navigator's push method you can push it onto your Material App.
Attaching an example code that uses Navigator to go to different pages, you need the BuildContext of your app. Here is an example of how you can get it:
import 'package:flutter/material.dart';
import 'package:rate_your_professor/screens/firstScreen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Some App',
home: SomeApp(),
);
}
}
class SomeApp extends StatelessWidget {
Widget getListView(BuildContext context) {
var listView = ListView(
children: <Widget>[
Text(
"XXXXXXXXXXXXXXX",
textDirection: TextDirection.rtl,
textAlign: TextAlign.center,
),
ListTile(
leading: Icon(Icons.location_city),
title: Text("XXXXX ", textDirection: TextDirection.rtl),
subtitle: Text(
"XXXXXXXXXX",
textDirection: TextDirection.rtl,
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => YourNewPage(),
),
);
},
),
],
);
return listView;
}
#override
Widget build(BuildContext context) {
return Scaffold(body: getListView(context));
}
}

How can I add data from the Firebase database in a reversed order? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am currently developing a chat app. The problem is, that when someone types something it shows randomly on the chat screen (after a user registered and logged in).
I want it to look like a normal chat app, so the last message should be at the bottom of the screen. I even reversed the data and list view, but it didn't work.
My code:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:naber/constants.dart';
final _firestore=FirebaseFirestore.instance;
User loggedInUser;
class ChatScreen extends StatefulWidget {
static String id="chat_screen";
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final messageTextController = TextEditingController();
final _auth = FirebaseAuth.instance;
String messageText;
void initState(){
super.initState();
getCurrentUser();
}
void getCurrentUser()async{
try{
final currentUser = await _auth.currentUser;
if(currentUser!=null){
loggedInUser=currentUser;
}
}
catch(e){
print(e);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
_auth.signOut();
Navigator.pop(context);
}),
],
title: Text('Chat'),
backgroundColor: Colors.lightBlueAccent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
MessagesStream(),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: messageTextController,
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
FlatButton(
onPressed: () {
messageTextController.clear();
_firestore.collection('messages').add({
'text': messageText,
'sender': loggedInUser.email,
});
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
class MessagesStream extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('messages').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
final messages = snapshot.data.docs.reversed;
List<MessageBubble> messageBubbles = [];
for (var message in messages) {
final messageText = message.data()['text'];
final messageSender = message.data()['sender'];
final currentUser = loggedInUser.email;
final messageBubble = MessageBubble(
sender: messageSender,
text: messageText,
isMe: currentUser == messageSender,
);
messageBubbles.add(messageBubble);
}
return Expanded(
child: ListView(
reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
children: messageBubbles,
),
);
},
);
}
}
class MessageBubble extends StatelessWidget {
MessageBubble({this.sender, this.text, this.isMe});
final String sender;
final String text;
final bool isMe;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment:
isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(
sender,
style: TextStyle(
fontSize: 12.0,
color: Colors.black54,
),
),
Material(
borderRadius: isMe
? BorderRadius.only(
topLeft: Radius.circular(30.0),
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0))
: BorderRadius.only(
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
elevation: 5.0,
color: isMe ? Colors.lightBlueAccent : Colors.white,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
child: Text(
text,
style: TextStyle(
color: isMe ? Colors.white : Colors.black54,
fontSize: 15.0,
),
),
),
),
],
),
);
}
}
You add messages with:
_firestore.collection('messages').add({
'text': messageText,
'sender': loggedInUser.email,
});
Firestore doesn't have any built-in default ordering for documents. If you want to be able to order the documents, you will need to add a value to each document to allow that.
For example, you could add a timestamp of when the document was created with:
_firestore.collection('messages').add({
'text': messageText,
'sender': loggedInUser.email,
'createdAt': FieldValue.serverTimestamp()
});
By using FieldValue.serverTimestamp() the server will automatically populate this field, which you can then use when reading the data with:
stream: _firestore.collection('messages').orderBy('createdAt', descending: true).snapshots()

Firebase "CurrentUser displayName" won't update with bottomsheet

My application has Firebase Authentication implemented and each user have to input their display name to register into the application.
Inside my application I want the user to be able to update this display name.
The logic is very simple, user clicks 'Change Display Name' button, a ModalBottomSheet appears where user can input his new display name and save it. But this way the screen doesn't gets updated when the display name is changed until I hot reload or restart the application.
class Body extends StatelessWidget {
final FirebaseAuth _auth = FirebaseAuth.instance;
#override
Widget build(BuildContext context) {
String displayName = _auth.currentUser.displayName;
final _formKey = GlobalKey<FormState>();
String newDisplayName;
return Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Current display name is:',
style: TextStyle(fontSize: 20),
),
Text(
'$displayName',
style: TextStyle(fontSize: 25),
),
RaisedButton(
child: Text('Change Display Name'),
onPressed: () {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) {
return Padding(
padding: MediaQuery.of(context).viewInsets
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
decoration: InputDecoration(
labelText: 'New Display Name',
),
keyboardType: TextInputType.text,
onSaved: (value) {
newDisplayName = value;
},
),
RaisedButton(
child: Text('Change'),
onPressed: () {
_formKey.currentState.save();
_auth.currentUser
.updateProfile(displayName: newDisplayName);
Navigator.pop(context);
},
),
],
),
),
);
},
);
},
),
],
),
),
);
}
}
I have tried to call .reload in different places but the display name won't change until page is refreshed.
_auth.currentUser.reload();
EDIT: Solution thanks to https://stackoverflow.com/users/11921453/twelve
Wrap the manin widget with the following StreamBuilder and you will be able to retrieve the snapshot.data.displayName instantly.
child: StreamBuilder<User>(
stream: FirebaseAuth.instance.userChanges(),
Firebase has a stream to listen to user changes. Define this stream next to your _auth.
Wrap your widget-tree with au streambuilder and set the value to the defined stream.
Now the widget-tree gets rebuild every time the user data changes.

error:- Another exception was thrown: A RenderFlex overflowed by 33 pixels on the bottom

[enter image description here]
1Error showing when i run my app...My code is below ...can anyone tell what is wrong with my code
///////////////////////
Error showing when i run my app...My code is below ...can anyone tell what is wrong with my code
///////////////////////
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:async';
import
'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
class OfferPage extends StatefulWidget {
#override
_OfferPageState createState() => new _OfferPageState();
}
class _OfferPageState extends State<OfferPage> {
StreamSubscription<QuerySnapshot> subscription;
List<DocumentSnapshot> offerpostList;
final CollectionReference collectionReference =
Firestore.instance.collection("todos");
#override
void initState() {
// TODO: implement initState
super.initState();
subscription = collectionReference.snapshots().listen((datasnapshot) {
setState(() {
offerpostList = datasnapshot.documents;
});
});
// _currentScreen();
}
#override
void dispose() {
subscription?.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: offerpostList != null? new StaggeredGridView.countBuilder(
padding: const EdgeInsets.all(8.0),
crossAxisCount: 4,
itemCount: offerpostList.length,
itemBuilder: (context, i) {
String imgPath = offerpostList[i].data['url'];
String title = offerpostList[i].data['productTitle'];
return new Material(
elevation: 8.0,
borderRadius:
new BorderRadius.all(new Radius.circular(8.0)),
child: new InkWell(
child:new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(title,style: new TextStyle(
fontStyle: FontStyle.italic,
color: Colors.green[900],
fontSize: 16.0)),
new Hero(
tag: imgPath,
child:
new FadeInImage(
image: new NetworkImage(imgPath),
fit: BoxFit.cover,
placeholder: new AssetImage("assets/logo.png"),
),
),
],
),
),
);
},
staggeredTileBuilder: (i) =>
new StaggeredTile.count(2, i.isEven ? 2 : 3),
mainAxisSpacing: 8.0,
crossAxisSpacing: 8.0,
)
: new Center(
child: new CircularProgressIndicator(),
));
}
}
Column in flutter doesn't have scrolling ability. The issue is your data from firebase cannot be fit inside a single screen. That's why overflow error was thrown. Use ListView instead of Column which has the scrolling ability.
Column widget for available room in the device to get qll data in firebase and also to get scroll effect you can use FirebaseAnimatedList.
For an Olx like gridview with text over image, here is a sample. Try it out and change your question because it might be misleading.
main.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firestore_grid_view/product.dart';
import 'package:firestore_grid_view/product_details.dart';
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(
home: new MyApp(),
debugShowCheckedModeBanner: false,
));
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Product> _products = [];
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Home'),
),
body: new StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('products').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return new Text('Loading...');
return new GridView.count(
crossAxisCount: 2,
children: _buildGrid(snapshot.data.documents),
);
},
),
);
}
List<Widget> _buildGrid(List<DocumentSnapshot> documents) {
List<Widget> _gridItems = [];
_products.clear();
for (DocumentSnapshot document in documents) {
_products.add(new Product(
name: document['productTitle'],
category: document['category'],
imageUrl: document['url'],
contactNumber: document['contactNumber']));
}
for (Product product in _products) {
_gridItems.add(_buildGridItem(product));
}
return _gridItems;
}
Widget _buildGridItem(Product product) {
return new GestureDetector(
child: new Card(
child: new Stack(
alignment: Alignment.center,
children: <Widget>[
new Hero(
tag: product.name,
child: new Image.network(product.imageUrl, fit: BoxFit.cover),
),
new Align(
child: new Container(
padding: const EdgeInsets.all(10.0),
child: new Text(product.name,
style: new TextStyle(color: Colors.white)),
color: Colors.black.withOpacity(0.4),
width: double.infinity,
),
alignment: Alignment.bottomCenter,
),
],
),
),
onTap: () => onProductTapped(product),
);
}
onProductTapped(Product product) {
Navigator.of(context).push(new MaterialPageRoute(
builder: (context) => new ProductDetails(product)));
}
}
product_details.dart
import 'package:firestore_grid_view/product.dart';
import 'package:flutter/material.dart';
class ProductDetails extends StatelessWidget {
final Product product;
ProductDetails(this.product);
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Column(
children: <Widget>[
new Expanded(child: new Container()),
new Hero(
tag: product.name,
child: new Image(
image: new NetworkImage(product.imageUrl),
fit: BoxFit.fill,
width: double.infinity,
height: 300.0,
)),
new Padding(
padding: const EdgeInsets.all(15.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Padding(
padding: const EdgeInsets.only(right: 8.0),
child: new Text(
'Category -',
style: new TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
),
new Text(
product.category,
style: new TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
],
),
),
new Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Padding(
padding: const EdgeInsets.only(right: 8.0),
child: new Text(
'Contact Number -',
style: new TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
),
new Text(
product.contactNumber,
style: new TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
],
),
),
new Expanded(child: new Container()),
],
),
);
}
}
product.dart
class Product {
final name, category, imageUrl, contactNumber;
Product({this.name, this.category, this.imageUrl, this.contactNumber});
}

Resources