Flutter problem with saving the value from document from database to a initState value - flutter

I have a problem with fetching value from database document to a variable called in initState method. When I am doing that there is a problem with null value and I think that get() method from Firebase is taking the value too late(it happens when i reload the scene).
bool _dark;
bool options;
MainModel model;
final MyUser myUser;
final UserSettings userSettings;
_SettingsOnePageState(this.userSettings, this.myUser);
final user = FirebaseAuth.instance.currentUser;
#override
void initState() {
super.initState();
// _dark = false;
FirebaseFirestore.instance
.collection("settings")
.doc(user.uid)
.get()
.then((value) {
print(value.data()['darkMode']);
_dark = value.data()['darkMode'];
});
options = false;
}
Brightness _getBrightness() {
return _dark ? Brightness.dark : Brightness.light;
}
#override
Widget build(BuildContext context) {
return Theme(
// return StreamProvider<QuerySnapshot>.value(
isMaterialAppTheme: true,
data: ThemeData(
brightness: _getBrightness(),
),
// value: SettingsUser().settings,
child: StreamBuilder<UserSettings>(
//setting the stream for settings from database
stream: DatabaseUser(userId: user.uid).userData,
builder: (context, snapshot) {
if (snapshot.hasData) {
//data for user from database
UserSettings userSettings = snapshot.data;
// _dark = userSettings.darkMode;
// print("dark mode " + userSettings.darkMode.toString());
return Form(
key: _formKey,
child: Scaffold(
backgroundColor: _dark ? null : Colors.grey.shade200,
appBar: AppBar(
//elevation: 10,
brightness: _getBrightness(),
iconTheme: IconThemeData(
color: _dark ? Colors.white : Colors.black),
backgroundColor: Colors.transparent,
title: Text(
'Change theme',
style: TextStyle(
color: _dark ? Colors.white : Colors.black),
textAlign: TextAlign.center,
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.auto_awesome),
onPressed: () {
setState(() {
_dark = !_dark;
});
},
)
],
),
body: Stack(fit: StackFit.expand, children: <Widget>[
SingleChildScrollView(
//padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Stack(
children: <Widget>[
Align(
alignment: Alignment.center,
child: Text(
userSettings.nick,
textScaleFactor: 4,
style: TextStyle(
color: _dark
? Colors.white
: Colors.purple[500],
//fontWeight: FontWeight.w500,
),
)),
const SizedBox(height: 50.0),
],
),
Stack(
children: <Widget>[
Align(
alignment: Alignment.center,
child: Container(
// width: 200,
// height: 200,
child: CircleAvatar(
radius: 100.0,
backgroundImage:
//NetworkImage(user.photoURL),
NetworkImage(
userSettings.pictureUrl),
),
),
),
],
),
//const SizedBox(height: 20.0),
if (options == true) ...[
//SettingsEdit(),
//NickChange(),
ImageInput(),
],
const SizedBox(height: 10.0),
Card(
elevation: 4.0,
margin: const EdgeInsets.fromLTRB(
32.0, 8.0, 32.0, 16.0),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(10.0)),
child: Column(
children: <Widget>[
ListTile(
leading: Icon(
Icons.account_box,
color: Colors.purple,
),
title: Text("Change Nickname"),
trailing:
Icon(Icons.keyboard_arrow_right),
onTap: () {
//open change nick
//changeNick();
},
),
_buildDivider(),
ListTile(
leading: Icon(
Icons.add_a_photo,
color: Colors.purple,
),
title: Text("Change Photo"),
trailing:
Icon(Icons.keyboard_arrow_right),
onTap: () {
//open change photo
//changePhoto();
},
),
_buildDivider(),
ListTile(
leading: Icon(
Icons.lock_rounded,
color: Colors.purple,
),
title: Text("Change Password"),
trailing:
Icon(Icons.keyboard_arrow_right),
onTap: () {
//open change password
//changePassword();
},
),
_buildDivider(),
ListTile(
leading: Icon(
Icons.location_on,
color: Colors.purple,
),
title: Text("Change Your Location"),
trailing:
Icon(Icons.keyboard_arrow_right),
onTap: () {
//open change location
},
),
],
),
),
const SizedBox(height: 20.0),
]))
])));
}
return Scaffold();
}));
}
debug console
settings where I use theme now
Do you know how to avoid this null in initState? I am trying to change theme of the app and I am taking that from Firebase document whick I created when the user registered. Than I will be changing it in user settings and also want to use it(this theme) in whole app.
Thanks for help

InitState is not async (meaning execution doesn't wait for your firebase call to complete). This means that your view will be rendered before you assign _dark a value.
If you want to wait until that call is complete, use something called FutureBuilder.

Related

assigning icon value based on data from flutter sqflite

I'm trying to load the favorite button on my card based on the data from database inside the future builder. while using the following code inside ListView.Builder, is sets the value to true and button click does not change it. I think it is because of FutureBuilder.
txtData.zFavourite == null
? isFavourite[index] = false
: isFavourite[index] = true;
it also requires to initialize the value for isFavourite and if it is assigned outside the widget, I do not get the data from database as it directly loads into the future builder.
how do we assign the value for isFavourite based on the data from the database and change the favourite icon based on the button click?
I also checked this link to handle button clicks for the individual list.
late List<bool> isFavourite = [false, false];
Widget _displayZhesa() {
return FutureBuilder<List<Zhebsa>>(
future: _getZhebsa(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
final txtData = snapshot.data![index];
txtData.zFavourite == null
? isFavourite[index] = false
: isFavourite[index] = true;
return Card(
elevation: 10,
color: Colors.white70,
shadowColor: Colors.amber[500],
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.all(5.0),
width: double.infinity,
decoration: BoxDecoration(
color: Colors.orange[400],
border: Border.all(
color: Colors.amber.shade100,
width: 2,
),
),
child: Center(
child: Text(
sQuery,
style: const TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.w500),
),
),
),
Row(
children: <Widget>[
Center(
child: IconButton(
onPressed: () {
setState(() {
isFavourite[index] = !isFavourite[index];
});
},
/* () =>
_setFaviurite(txtData.zFavourite, index), */
icon: Icon(
isFavourite[index]
? Icons.favorite_sharp
: Icons.favorite_border_sharp,
size: 30.0,
color: Colors.redAccent,
),
),
),
Expanded(
child: ListTile(
title: const Text('ཞེ་ས།'),
subtitle: Text(txtData.zWord), //ཞེ་སའི་ཚིག
),
),
Container(
padding: const EdgeInsets.only(right: 20),
child: IconButton(
onPressed: () {
isPlayingPronunciation
? stopPronunciation()
: _playPronunciation(
'${txtData.zPronunciation}');
setState(() {
isPlayingPronunciation =
!isPlayingPronunciation;
});
},
icon: Icon(
isPlayingPronunciation
? Icons.stop_circle_outlined
: Icons.volume_up,
size: 50.0,
color: Colors.blue,
),
),
),
],
),
Container(
padding: const EdgeInsets.only(left: 30.0),
child: ListTile(
title: const Text('དཔེར་བརྗོད།'),
subtitle: SelectableText('${txtData.zPhrase}'),
),
),
],
),
);
},
);
} else {
return const Text('No Data');
}
});
}

Flutter showing null check operator used on a null value on app start up

I'm new to flutter, i'm trying to write a radio streaming app, i used just_audio to handle my player. When i start up my app on debug mode, it gives me the null check operator used on a null value message. I've tried adding a if condition to check if is null, but it didn't quite work.
Here's my widget code:
#override
Widget build(BuildContext context) {
return new WillPopScope(
onWillPop: () async => false,
child: new MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Container(
decoration: new BoxDecoration(
image: new DecorationImage(image: AssetImage("assets/img/MobilePlayer.png"), fit: BoxFit.cover),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: StreamBuilder<SequenceState?>(
stream: _player.sequenceStateStream,
builder: (context, snapshot) {
final state = snapshot.data;
if (state?.sequence.isEmpty ?? true) return SizedBox();
final metadata = state!.currentSource!.tag as AudioMetadata;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child:
Center(
child: Image.network(metadata.artwork,
scale: 1.5,
),
),
),
),
// Text(metadata.album,
// style: Theme.of(context).textTheme.headline6),
// Text(metadata.title),
],
);
},
),
),
ControlButtons(_player),
// StreamBuilder<PositionData>(
// stream: _positionDataStream,
// builder: (context, snapshot) {
// final positionData = snapshot.data;
// return SeekBar(
// duration: positionData?.duration ?? Duration.zero,
// position: positionData?.position ?? Duration.zero,
// bufferedPosition:
// positionData?.bufferedPosition ?? Duration.zero,
// onChangeEnd: (newPosition) {
// _player.seek(newPosition);
// },
// );
// },
// ),
SizedBox(height: 8.0),
Row(
children: [
],
),
Container(
height: 300.0,
color: Colors.transparent,
**child: StreamBuilder<SequenceState?>(**
stream: _player.sequenceStateStream,
builder: (context, snapshot) {
final state = snapshot.data;
final sequence = state?.sequence ?? [];
final metadata = state!.currentSource!.tag as AudioMetadata;
return ListView(
children: [
for (var i = 0; i < sequence.length; i++)
Dismissible(
key: ValueKey(sequence[i]),
background: Container(
color: Colors.transparent,
alignment: Alignment.centerRight,
child: Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Icon(Icons.delete, color: Colors.transparent),
),
),
onDismissed: (dismissDirection) {
_playlist.removeAt(i);
},
child: Material(
color: i == state.currentIndex
? Colors.transparent
: Colors.transparent,
child: Card(
color: Colors.transparent,
shape: StadiumBorder(
side: BorderSide(
color: i == state.currentIndex
? Colors.yellow
: Colors.white,
width: 1.0,
),
),
child: ListTile(
title: Text(sequence[i].tag.title as String,
style: GoogleFonts.lato(
textStyle: TextStyle(color: i == state.currentIndex
? Colors.yellow
: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w700,
),
),
textAlign: TextAlign.center,
),
onTap: () {
_player.seek(Duration.zero, index: i);
},
leading: Wrap(
children: <Widget>[
IconButton(icon: i == state.currentIndex
? Icon(Icons.pause, color: i == state.currentIndex
? Colors.yellow
: Colors.white,)
: Icon(Icons.play_arrow,
color: i == state.currentIndex
? Colors.yellow
: Colors.white,),
onPressed: (){
_player.seek(Duration.zero, index: i);
i == state.currentIndex
? _player.pause()
: _player.play();
}
),
],
),
trailing: Wrap(
children: <Widget>[
IconButton(icon: Icon(FontAwesomeIcons.whatsapp,
color: i == state.currentIndex
? Colors.yellow
: Colors.white,),
onPressed: () async => await launch(sequence[i].tag.wpp as String)
)
],
),
),
),
),
),
],
);
},
),
),
],
),
),
),
),
);
}
this is a common problem in Flutter, this error means that you have marked a variable that will never be null with this ! mark. but while your program is running this value has become null.
In your code, you have used ! this mark in multiple lines. simply, place a debug pointer there and identify when this becomes null.
also, you should use the below method whenever possible.
String hello = state?.value ?? 'default';
instead of this:
String hello = state!.value
When you use a StreamBuilder, make sure you check if you already have the data before you try to work with it:
if (!snapshot.hasData) return CircularProgressIndicator();
You get a null error because you try to use the variable before the StreamBuilder put some data in it, so it is still null... But with the ! mark you say that "don't worry about this variable, when the code gets here I make sure it is not null"

How to fix when BackdropScaffold frontLayer's elements doesn't appear?

Sorry for the bad title:(!
My app should show in the home screen cards and FloatingActionButton, I've created the cards in separate file, so I'm forwarding the data to it, also to store my data I'm using sqlite which I'm new to it..
the FloatingActionButton should appear when I run the application, and I need it to add new cards. I know that the database is empty now, but why the FloatingActionButton is not appearing?
when running it it looks like this.
I had followed a tutorial in the part when using the sqlite, and this is a part of my homeScreen code :
frontLayer: FutureBuilder<List<Reminder>>(
future: _reminders,
builder: (context, snapshot) {
if (snapshot.hasData) {
_currentReminders = snapshot.data!;
return ListView(children: [
...snapshot.data!.map<Widget>((reminder) {
return ReminderCard(
name: reminder.name, details: reminder.details);
}).followedBy([
Scaffold(
backgroundColor: Colors.amber,
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.black,
child: Icon(Icons.add),
onPressed: () {},
),
)
]).toList(),
Padding(
padding: const EdgeInsets.all(8.0),
),
Scaffold(
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.black,
child: Icon(Icons.add),
onPressed: () {}
this is the full code if I didn't paste the right part of my code: https://github.com/RarLasebai/reminder3/blob/main/lib/ui/Screens/homeScreen.dart
i have cloned your project and did a little changes on the HomeScreen
here is how u should do it
import 'package:flutter/material.dart';
import 'package:backdrop/backdrop.dart';
import 'package:untitled/helper.dart';
import 'package:untitled/models/reminder.dart';
import 'package:untitled/ui/widgets/ReminderCard.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
TextEditingController nameController = TextEditingController();
TextEditingController detailsController = TextEditingController();
final _formKey = GlobalKey<FormState>();
late ReminderCard card;
RHelper helper = RHelper();
late Future<List<Reminder>> _reminders;
late List<Reminder> _currentReminders;
//-------------------------Functions----------------
bool status = true;
#override
void initState() {
super.initState();
helper.initializeDatabase().then((value) => {print("------------donne?")});
_loadReminders();
}
void _loadReminders() {
_reminders = helper.getReminders();
if (mounted) setState(() {});
}
//Screen and appBar frontend
#override
Widget build(BuildContext context) {
return BackdropScaffold(
backgroundColor: Colors.white,
appBar: BackdropAppBar(
centerTitle: true,
title: (Text(
'قائمة التذكيرات',
style: Theme.of(context).textTheme.headline1,
)),
),
headerHeight: 110.0,
frontLayer: FutureBuilder<List<Reminder>>(
future: _reminders,
builder: (context, snapshot) {
if (snapshot.hasData) {
_currentReminders = snapshot.data!;
return ListView(children: [
Column(
children: _currentReminders.map<Widget>((reminder) {
return ReminderCard(
name: reminder.name, details: reminder.details);
}).toList(),
),
Padding(
padding: const EdgeInsets.all(8.0),
),
]);
}
return Center(child: Text("Loading>>.."));
},
),
backLayer: BackdropNavigationBackLayer(
items: [
ListTile(
leading: ImageIcon(AssetImage('icons/to-do-list.png')),
title: Align(
alignment: Alignment.centerRight,
child: Text("التذكيرات",
style: Theme.of(context).textTheme.bodyText2)),
onTap: () {
Navigator.of(context).pushReplacementNamed('home');
}),
Divider(),
ListTile(
leading: ImageIcon(AssetImage('icons/athkar.png')),
title: Align(
alignment: Alignment.centerRight,
child: Text("الأذكار",
style: Theme.of(context).textTheme.bodyText2)),
onTap: () {
Navigator.of(context).pushReplacementNamed('athkar');
}),
Divider(),
ListTile(
leading: ImageIcon(AssetImage('icons/mosque.png')),
title: Align(
alignment: Alignment.centerRight,
child: Text("مواقيت الصلاة",
style: Theme.of(context).textTheme.bodyText2)),
onTap: () {
Navigator.of(context).pushReplacementNamed('adhan');
},
),
Divider(),
ListTile(
leading: ImageIcon(AssetImage('icons/Tasbeeh.png')),
title: Align(
alignment: Alignment.centerRight,
child: Text("تسبيح",
style: Theme.of(context).textTheme.bodyText2)),
onTap: () {
Navigator.of(context).pushReplacementNamed('tasbeeh');
},
),
Divider(),
ListTile(
leading: ImageIcon(AssetImage('icons/quran.png')),
title: Align(
alignment: Alignment.centerRight,
child: Text("مصحف",
style: Theme.of(context).textTheme.bodyText2)),
onTap: () {
Navigator.of(context).pushReplacementNamed('moshaf');
},
),
Divider(),
ListTile(
leading: ImageIcon(AssetImage('icons/tadabur.png')),
title: Align(
alignment: Alignment.centerRight,
child: Text("وقفات تدبرية ",
style: Theme.of(context).textTheme.bodyText2)),
onTap: () {
Navigator.of(context).pushReplacementNamed('tadabur');
}),
Divider(),
ListTile(
leading: ImageIcon(AssetImage('icons/information.png')),
title: Align(
alignment: Alignment.centerRight,
child: Text("تواصل معنا",
style: Theme.of(context).textTheme.bodyText2)),
onTap: () {
Navigator.of(context).pushReplacementNamed('contact');
})
],
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
showModalBottomSheet(
useRootNavigator: true,
context: context,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(24),
),
),
builder: (context) {
return StatefulBuilder(
builder: (context, setModalState) {
return Container(
padding: const EdgeInsets.all(32),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
validator: (String? value) {
if (value!.isEmpty)
return 'Please enter name';
},
controller: detailsController,
style: TextStyle(
color: Colors.black, fontSize: 15.0),
decoration: InputDecoration(
errorStyle: TextStyle(
color: Colors.red, fontSize: 15.0),
labelText: 'اسم التذكير',
labelStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 15.0,
),
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(5.0)),
),
),
SizedBox(
height: 10,
),
TextFormField(
controller: nameController,
style: TextStyle(
color: Colors.black, fontSize: 15.0),
decoration: InputDecoration(
labelText: 'التفاصيل',
labelStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 15.0,
),
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(5.0)),
),
),
SizedBox(
height: 10,
),
ElevatedButton(
onPressed: () {
setState(() {
if (_formKey.currentState!
.validate()) {
_save();
Navigator.pop(context);
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
content: Text(
'تم حفظ التذكير')));
}
});
},
child: Text('حفظ'),
)
],
),
),
);
});
},
);
})
);
}
void _save() {
var _reminder = Reminder(
name: nameController.text, details: detailsController.text, save: 0);
helper.insertReminder(_reminder);
_loadReminders();
}
}
and for a athkar project i really suggest that you use provider or riverpod , or any kind of state management

Navigator.pop shows me a black screen

It's been a while since I've been blocking backtracking on my flutter application, I tried the Navigator.pop (context) but I still ran into a black screen, I searched the forums for success but I'm still stuck. I want that when I click on return that it brings me back to my previous page without initializing the page
import 'package:MerchantIsland/log/database.dart';
import 'package:MerchantIsland/pages/home.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class productPage extends StatefulWidget {
final String productId;
const productPage({Key key, this.productId}) : super(key: key);
#override
_productPageState createState() => _productPageState();}
class _productPageState extends State<productPage> {
#override
Widget build(BuildContext context) {
ProductService productService = ProductService();
return WillPopScope(
onWillPop: (){
MovetoPreviousScreen();},
child: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: (){
MovetoPreviousScreen();
},
),
centerTitle: true,
title: Text(
'Merchant island',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
),
body: Stack(
children: [
FutureBuilder(
future: productService.ProductData.doc(widget.productId).get(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Scaffold(
body: Center(
child: Text("Error: ${snapshot.error}"),
),
);
}
if(snapshot.connectionState==ConnectionState.done){
Map<String, dynamic> documentData=snapshot.data.data();
return ListView(
children: [
Container(
height: 400.0,
child: Image.network(
"${documentData['pictures'][0]}",
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0,horizontal: 24.0),
child: Text('${documentData['productName']}'??"Nom du produit",
style:TextStyle(
fontSize: 28.0,
fontWeight: FontWeight.bold,
) ,),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0,horizontal: 24.0),
child: Text('${documentData['price']}',
style:TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold,
color:Colors.red
) ),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0,horizontal: 24.0),
child: Text('${documentData['description']}',
style:TextStyle(
fontSize: 18
) ),
)
],
);
}
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}),
],
),
),
); }
// ignore: non_constant_identifier_names
void MovetoPreviousScreen() {
Navigator.of(context).pop(); }}
return page
import 'package:MerchantIsland/log/database.dart';
import 'package:MerchantIsland/log/loginUI.dart';
import 'package:MerchantIsland/pages/Sellproduct.dart';
import 'package:MerchantIsland/pages/bidPage.dart';
import 'package:MerchantIsland/products/productPage.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:MerchantIsland/pages/profil.dart';
import 'package:MerchantIsland/pages/balance.dart';
import 'package:MerchantIsland/pages/Settings.dart';
import 'package:google_sign_in/google_sign_in.dart';
// ignore: camel_case_types
class home extends StatefulWidget {
#override
_homeState createState() => _homeState();}
// ignore: camel_case_types
class _homeState extends State<home> {
ProductService productService = ProductService();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: false,
title: Text("Merchant Island"),
actions: [
IconButton(
icon: Icon(Icons.search, color: Colors.white,), onPressed: null,),
],
),
body: Stack(
children: [
FutureBuilder<QuerySnapshot>(
future: productService.ProductData.get(),
builder:(context,snapshot){
if(snapshot.hasError){
return Scaffold(
body: Center(
child: Text("Error: ${snapshot.error}"),
),
);
}
if(snapshot.connectionState==ConnectionState.done){
return Container(
child: ListView(
children: snapshot.data.docs.map((documents){
return Container(
child: GestureDetector(
onTap: (){
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context)=>productPage(productId: documents.id,)));
},
child: Container(
child: productCard(documents.data()["productName"],documents.data()["category"], documents.data()["price"],documents.data()["pictures"]) ,
),
),
);
}).toList(),
),
);
}
return Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}),
],
),
drawer: BDrawer(context),
); }}
// ignore: non_constant_identifier_names
Drawer BDrawer(BuildContext context) {
FirebaseAuth _auth = FirebaseAuth.instance;
GoogleSignIn _googleSignIn = GoogleSignIn();
Future <void> signOut() async {
await _auth.signOut();
await _googleSignIn.disconnect();
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => LoginUI()));}
return Drawer(
child: ListView(
children: [
UserAccountsDrawerHeader(
accountName: Text('TITAN', style: TextStyle(
fontSize: 18.0,
),),
accountEmail: Text('philippetankoano#gmail.com'),
currentAccountPicture: GestureDetector(
child: CircleAvatar(
backgroundColor: Colors.grey,
child: Icon(
Icons.person, color: Colors.white
),
),
),
otherAccountsPictures: [
InkWell(
onTap: () =>
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => profil(),)),
child: (
Icon(
Icons.mode_edit, size: 30.0,
)
),
)
],
),
InkWell(
onTap: () =>
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => balancepage())),
child: ListTile(
leading: Icon(
Icons.account_balance, size: 30.0, color: Colors.blue,),
title: Text(' Balance', style: TextStyle(
fontSize: 18.0,
),),
),
),
InkWell(
onTap: () =>
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => home())),
child: ListTile(
leading: Icon(Icons.home, size: 30.0, color: Colors.blue,),
title: Text(' Home', style: TextStyle(
fontSize: 18.0,
),),
),
),
InkWell(
onTap: () =>
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => SellProduct())),
child: ListTile(
leading: Icon(
Icons.account_balance, size: 30.0, color: Colors.blue,),
title: Text(' Sell product', style: TextStyle(
fontSize: 18.0,
),),
),
),
InkWell(
onTap: () {},
child: ListTile(
leading: Icon(
Icons.shopping_basket_outlined, size: 40.0,
color: Colors.blue,),
title: Text('Sale', style: TextStyle(
fontSize: 18.0,
),),
),
),
InkWell(
onTap: () {},
child: ListTile(
leading: Icon(Icons.category, size: 30.0, color: Colors.blue,),
title: Text(' Categories', style: TextStyle(
fontSize: 18.0,
),),
),
),
InkWell(
onTap: () =>
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => bidPage())),
child: ListTile(
leading: Icon(
Icons.event_available, size: 40.0, color: Colors.blue,),
title: Text(' Bid', style: TextStyle(
fontSize: 18.0,
),),
),
),
Divider(),
InkWell(
onTap: () =>
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => Settingpage(),)),
child: ListTile(
leading: Icon(Icons.settings, size: 30.0, color: Colors.blue,),
title: Text(' Setting', style: TextStyle(
fontSize: 18.0,
),),
),
),
InkWell(
onTap: () {},
child: ListTile(
leading: Icon(Icons.help, size: 30.0, color: Colors.blue,),
title: Text(' Help', style: TextStyle(
fontSize: 18.0,
),),
),
),
InkWell(
onTap: () async {
signOut();
},
child: ListTile(
leading: Icon(Icons.exit_to_app, size: 30.0, color: Colors.blue,),
title: Text(' Deconnexion', style: TextStyle(
fontSize: 18.0,
),),
),
),
]
), );}
Padding productCard(String name,String category,String price,List imageUrl){
return Padding(
padding: const EdgeInsets.all(6.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10.0),
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(-2,-1),
blurRadius: 5
)
] ),
child: GestureDetector(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(7.0),
child: Image.network(
"${imageUrl[0]}",
height: 500,
width: 450,
),
),
],
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(' $name ',style: TextStyle(fontSize: 24.0,fontWeight: FontWeight.bold)),
Text('$price ',style: TextStyle(fontSize: 20.0,fontWeight: FontWeight.bold,color: Colors.red)),
],
),
),
Text('Categorie: $category \n',style: TextStyle(fontSize: 24.0,)),
],
),
), ),);}
Method One(Recommended)
First check if there is more than one Material App in your project if found then remove all except the root one (Child of MyApp) if that does not work or you have only one MaterialApp in your project then only try second method
Method Two(Try only if method one doesn't solved your issue or you don't have more than one MaterialApp in your project)
Replace Navigator.of(context).pop(); with Navigator.of(context,rootNavigator:true).pop(context)
If you got a black screen, it's probably because you are popping the only screen in your stack.
If you want that Navigator.of(context).pop() remove only the last screen, you have to display the current screen with a Navigator.of(context).push()
When clicking on the custom back icon Leading with in flutter
Replace Navigator.of(context).pop(); with Navigator.of(context,rootNavigator:true).pop(context)
appBar: AppBar(
automaticallyImplyLeading: true,
backgroundColor: ColorConstants.kBlackColor,
leading: BackButton(
color: ColorConstants.kWhiteColor,
onPressed: (){
Navigator.of(context,rootNavigator:true).pop(context);
},
),
),
In my case the problem was having some Navigator.pop(context) inside other callback functions.
When I clicked the back button, a socket would close, and consequently call the callback function (that also called pop()), so I would have Navigator.pop(context) called more than one time. And since my Page widget was the second element of the stack, calling it 2 times would pop also the root, therefore generating the black screen.
What I did to fix it, even though I think there might be better solutions, was substituting all the Navigator.pop(context) calls with the following:
if (Navigator.canPop(context)) {
Navigator.pop(context);
}
Another possible solution would be to initialize a bool variable (or a some kind of counter) and then call pop() only if that variable is true, then set it to false.:
// init
bool variable = true;
if (variable) {
Navigator.pop(context);
variable = false;
}

Selecting a specific BottomNavigationBar when routing from another widget (Flutter)

Please, help. This is my first project using Flutter. I am making an app for pets.
I have Homepage widget that has 4 bottom Navbar (Home, Photos, Medical, Profile). In Profile I have a button "About", which opens a widget about us.
But when I am trying to return to back from About, it returns to "Home" NavBottombar. I am trying to select Profile NavBottomBar.
I think that is related to current index in Homepage, which equals 0 at the beginning. But how can I change from 0 to 2 while routing?
homepage.dart
import 'package:flutter/material.dart';
import 'placeholder_widget.dart';
import 'dashboard.dart';
import 'medical.dart';
import 'profile.dart';
import 'about.dart';
void main() => runApp(MaterialApp(
home: Homepage(),
));
class Homepage extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<Homepage> {
int _currentIndex = 0;
final List<Widget> _children = [
Dashboard(),
PlaceholderWidget(Colors.deepOrange),
PlaceholderWidget(Colors.red),
// Medical(),
Profile()
];
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Furball Tales'),
backgroundColor: Colors.cyanAccent[400],
),
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTabTapped,
currentIndex: _currentIndex,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.perm_media),
title: Text('Photos'),
),
BottomNavigationBarItem(
icon: Icon(Icons.local_hospital),
title: Text('Medical'),
),
BottomNavigationBarItem(
icon: Icon(Icons.perm_identity),
title: Text('Profile'),
),
],
selectedItemColor: Colors.cyanAccent[400],
unselectedItemColor: Colors.grey[600],
),
),
);
}
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
}
about.dart
import 'package:flutter/material.dart';
import 'profile.dart';
import 'homepage.dart';
class About extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('About FurBallTales'),
backgroundColor: Colors.cyanAccent[400],
leading: GestureDetector(
onTap: () {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) {
return Homepage();
}), ModalRoute.withName('/'));
},
child: Icon(
Icons.arrow_back,
)),
),
body: ListView(
padding: const EdgeInsets.all(2),
children: <Widget>[
Container(
decoration:
BoxDecoration(border: Border.all(color: Colors.blueAccent)),
child: Column(
children: <Widget>[
Container(
height: 30,
margin: EdgeInsets.all(5),
child: Text(
'OUR MISSION',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.tealAccent[400]),
),
),
Container(
height: 25,
margin: EdgeInsets.all(5),
child: Text(
'Strengthening the bond of owners and pets, more than ever',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.black),
),
),
],
),
),
Container(
height: 50,
color: Colors.amber[600],
child: const Center(child: Text('Entry A')),
),
Container(
height: 50,
color: Colors.amber[500],
child: const Center(child: Text('Entry B')),
),
Container(
height: 50,
color: Colors.amber[100],
child: const Center(child: Text('Entry C')),
),
],
),
);
}
}
profile.dart
import 'package:flutter/material.dart';
import 'sign_in.dart';
import 'login_page.dart';
import 'about.dart';
import 'donation.dart';
class Profile extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircleAvatar(
radius: 80,
backgroundImage: NetworkImage(
'https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcSxDoD5caxFUy_dn0w6wl01m882CeJHNVOCRg&usqp=CAU'),
),
Text(
'<$name>',
style: TextStyle(
fontFamily: 'SourceSansPro',
fontSize: 25,
),
),
Text(
'<$email>',
style: TextStyle(
fontSize: 20,
fontFamily: 'SourceSansPro',
color: Colors.red[400],
letterSpacing: 2.5,
),
),
SizedBox(
height: 20.0,
width: 200,
child: Divider(
color: Colors.teal[200],
),
),
// this is about page-----------------------------------------
InkWell(
onTap: () {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) {
return About();
}), ModalRoute.withName('/about'));
},
child: Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Icon(
Icons.help,
color: Colors.teal[900],
),
title: Text(
'About',
style:
TextStyle(fontFamily: 'BalooBhai', fontSize: 20.0),
),
)),
),
InkWell(
onTap: () {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) {
return Donation();
}), ModalRoute.withName('/about'));
},
child: Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Icon(
Icons.monetization_on,
color: Colors.teal[900],
),
title: Text(
'Donation',
style: TextStyle(fontSize: 20.0, fontFamily: 'Neucha'),
),
),
),
),
InkWell(
onTap: () {
signOutGoogle();
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) {
return LoginPage();
}), ModalRoute.withName('/'));
},
child: Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Icon(
Icons.account_circle,
color: Colors.teal[900],
),
title: Text(
'LOGOUT',
style: TextStyle(fontSize: 20.0, fontFamily: 'Neucha'),
),
),
),
),
],
),
),
),
);
}
}
Instead of using pushAndRemoveUntil in your About page, you can use Navigator.pop(context)( which removes the view from the Navigator stack):
I added a demo using your code as an example:
class About extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('About FurBallTales'),
backgroundColor: Colors.cyanAccent[400],
leading: GestureDetector(
onTap: () {
Navigator.pop(context); // pop the view
},
child: Icon(
Icons.arrow_back,
)),
),
...
);
}
}
NOTE:
With this approach, the state of the BottomNavigationBar is reserved.
Thank you for everyone, who helped me.
The problem has been solved this way:
First, I pushed to new page.
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => About()));
}
Then made pop context.
onTap: () {
Navigator.pop(context);
},
It returned initial position.
Where it says return Homepage(); in about.dart you could change that to return the profile widget.