I'm building a Messenger app on Flutter using Firebase and when I click to chat with another user - I get this exception before the previous messages are loaded.
======== Exception caught by widgets library =======================================================
The following LateError was thrown building ChatRoom(dirty, state: _ChatRoomState#be2bb):
LateInitializationError: Field 'chatRoomsStream' has not been initialized.
The relevant error-causing widget was:
ChatRoom file:///D:/Android/chat_app/lib/main.dart:47:55
When the exception was thrown, this was the stack:
#0 _ChatRoomState.chatRoomsStream (package:chat_app/views/chatRoomsScreen.dart)
#1 _ChatRoomState.chatRoomList (package:chat_app/views/chatRoomsScreen.dart:29:15)
#2 _ChatRoomState.build (package:chat_app/views/chatRoomsScreen.dart:83:15)
#3 StatefulElement.build (package:flutter/src/widgets/framework.dart:4691:27)
#4 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4574:15)
...
====================================================================================================
This is the chatRoomsScreen.dart page that is causing the issue, this is the page that is loaded every time a user wants to chat with another user:
import 'package:chat_app/helper/authenticate.dart';
import 'package:chat_app/helper/constants.dart';
import 'package:chat_app/helper/helperfunctions.dart';
import 'package:chat_app/services/auth.dart';
import 'package:chat_app/services/database.dart';
import 'package:chat_app/views/conversationScreen.dart';
import 'package:chat_app/views/search.dart';
import 'package:chat_app/views/signin.dart';
import 'package:chat_app/widgets/widgets.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class ChatRoom extends StatefulWidget {
const ChatRoom({Key? key}) : super(key: key);
#override
_ChatRoomState createState() => _ChatRoomState();
}
class _ChatRoomState extends State<ChatRoom> {
AuthMethods authMethods = new AuthMethods();
DatabaseMethods databaseMethods = new DatabaseMethods();
late Stream<QuerySnapshot> chatRoomsStream;
Widget chatRoomList() {
return StreamBuilder(
stream: chatRoomsStream,
builder: (context, snapshot) {
return snapshot.hasData ? ListView.builder(
itemCount: (snapshot.data as QuerySnapshot).docs.length,
itemBuilder: (context, index) {
return ChatRoomsTile(
(snapshot.data as QuerySnapshot).docs[index]["chatroomid"]
.toString().replaceAll("_", "")
.replaceAll(Constants.myName, ""),
(snapshot.data as QuerySnapshot).docs[index]["chatroomid"]
);
},
) : Container();
},
);
}
#override
void initState() {
getUserInfo();
super.initState();
}
getUserInfo() async {
Constants.myName = (await HelperFunctions.getUserNameSharedPreference())!;
databaseMethods.getChatRooms(Constants.myName).then((value) {
setState(() {
chatRoomsStream = value;
});
});
setState(() {
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Image.asset("assets/images/logo.png", height: 50.0),
actions: [
GestureDetector(
onTap: () {
authMethods.signOut();
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => Authenticate()
));
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(Icons.exit_to_app)),
),
],),
body: chatRoomList(),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (context) => SearchScreen()
));
},
child: Icon(Icons.search),
),
);
}
}
class ChatRoomsTile extends StatelessWidget {
late final String userName;
late final String chatRoomId;
ChatRoomsTile(this.userName,this.chatRoomId);
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => ConversationScreen(chatRoomId: chatRoomId)
));
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 20),
child: Row(
children: [
Container(
height: 40,
width: 40,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(30)),
child: Text(userName.substring(0, 1),
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontFamily: 'OverpassRegular',
fontWeight: FontWeight.w300)),
),
SizedBox(width: 12,),
Text(userName, style: mediumTextStyle(),),
],
),
),
);
}
}
What am I doing wrong with chatRoomsStream? I'm initializing it as early as I can and to me, it's done as it should be. Perhaps one of you can point out why I'm getting this exception every time this page is loaded - help would be greatly appreciated, thanks.
instead of late Stream<QuerySnapshot> chatRoomsStream;
use Stream<QuerySnapshot>? chatRoomsStream;
and when you call the chatRoomStream
call it as chatRoomStream!
this is null safety
know about null safety
For your kind information, Using late keyword means that the instant will be initialized when you use it for the first time.
Like:
late int value = 5;
late int value; // you got the error
For more about sound null safety
More about lazy initialization
N.B: In your case, you can remove late, otherwise initialize it.
Related
I am building a setting widget in my flutter app and I am getting this error :
Error: Could not find the correct Provider above this SettingsForm Widget
Update Adding whole debug snippet:
Launching lib\main.dart on AOSP on IA Emulator in debug mode...
════════ Exception caught by widgets library ═══════════════════════════════════
The following ProviderNotFoundException was thrown building SettingsForm(dirty, state: _SettingsFormState#c73b8):
Error: Could not find the correct Provider<MyUser> above this SettingsForm Widget
This happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:
- You added a new provider in your `main.dart` and performed a hot-reload.
To fix, perform a hot-restart.
- The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
- You used a `BuildContext` that is an ancestor of the provider you are trying to read.
Make sure that SettingsForm is under your MultiProvider/Provider<MyUser>.
This usually happens when you are creating a provider and trying to read it immediately.
For example, instead of:
```
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// Will throw a ProviderNotFoundError, because `context` is associated
// to the widget that is the parent of `Provider<Example>`
child: Text(context.watch<Example>()),
),
}
```
consider using `builder` like so:
```
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// we use `builder` to obtain a new `BuildContext` that has access to the provider
builder: (context) {
// No longer throws
return Text(context.watch<Example>()),
}
),
}
```
If none of these solutions work, consider asking for help on StackOverflow:
https://stackoverflow.com/questions/tagged/flutter
The relevant error-causing widget was
SettingsForm
When the exception was thrown, this was the stack
#0 Provider._inheritedElementOf
#1 Provider.of
#2 _SettingsFormState.build
#3 StatefulElement.build
#4 ComponentElement.performRebuild
...
════════════════════════════════════════════════════════════════════════════════
i UPDATED IT AND ADDED SOME EXTRA CODE SO YOU CAN SEE BETTER
setting.dart:
class SettingsForm extends StatefulWidget {
#override
_SettingsFormState createState() => _SettingsFormState();
}
class _SettingsFormState extends State<SettingsForm> {
final _formKey = GlobalKey<FormState>();
final List<String> sugars = ['0', '1', '2', '3', '4'];
final List<int> strengths = [100, 200, 300, 400, 500, 600, 700, 800, 900];
// form values
String? _currentName;
String? _currentSugars;
int? _currentStrength;
#override
Widget build(BuildContext context) {
MyUser user = Provider.of<MyUser>(context);
return StreamBuilder<UserData>(
stream: DatabaseService(uid: user.uid).userData,
builder: (context, snapshot) {
if (snapshot.hasData) {
UserData? userData = snapshot.data;
return Form(
key: _formKey,
child: Column(
children: <Widget>[
Text(
'Update your brew settings.',
style: TextStyle(fontSize: 18.0),
),
SizedBox(height: 20.0),
TextFormField(
initialValue: userData!.name,
decoration: textInputDecoration,
validator: (val) =>
val!.isEmpty ? 'Please enter a name' : null,
onChanged: (val) => setState(() => _currentName = val),
),
SizedBox(height: 10.0),
DropdownButtonFormField<String>(
value: _currentSugars ?? userData.sugars,
decoration: textInputDecoration,
items: sugars.map((sugar) {
return DropdownMenuItem(
value: sugar,
child: Text('$sugar sugars'),
);
}).toList(),
onChanged: (val) => setState(() => _currentSugars = val),
),
SizedBox(height: 10.0),
Slider(
value: (_currentStrength ?? userData.strength).toDouble(),
activeColor:
Colors.brown[_currentStrength ?? userData.strength],
inactiveColor:
Colors.brown[_currentStrength ?? userData.strength],
min: 100.0,
max: 900.0,
divisions: 8,
onChanged: (val) =>
setState(() => _currentStrength = val.round()),
),
ElevatedButton(
style:
ElevatedButton.styleFrom(primary: Colors.pink[400]),
child: Text(
'Update',
style: TextStyle(color: Colors.white),
),
onPressed: () async {
if (_formKey.currentState!.validate()) {
await DatabaseService(uid: user.uid).updateUserData(
_currentSugars ?? snapshot.data!.sugars,
_currentName ?? snapshot.data!.name,
_currentStrength ?? snapshot.data!.strength);
Navigator.pop(context);
}
}),
],
),
);
} else {
return Loading();
}
});
}
}
UPDATE: I AM INCLUDING THE HOME.DART FILE THAT INCLUDES THE 'SETTINGFORM' WIDGET
home.dart :
class Home extends StatelessWidget {
final AuthService _auth = AuthService();
#override
Widget build(BuildContext context) {
void _showSettingsPanel() {
showModalBottomSheet(context: context, builder: (context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 60.0),
child: SettingsForm(), <-- Here
);
});
}
return StreamProvider<List<Brew>?>.value(
value: DatabaseService(uid: '').brews,
initialData: null,
child: Scaffold(
backgroundColor: Colors.brown[50],
appBar: AppBar(
title: Text('Brew Crew'),
backgroundColor: Colors.brown[400],
elevation: 0.0,
actions: <Widget>[
TextButton.icon(
icon: Icon(Icons.person),
label: Text('logout'),
onPressed: () async {
await _auth.signOut();
},
),
TextButton.icon(
icon: Icon(Icons.settings),
label: Text('settings'),
onPressed: () => _showSettingsPanel(),
)
],
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/coffee_bg.png'),
fit: BoxFit.cover,
),
),
child: BrewList()
),
),
);
}
}
user.dart:
class MyUser {
final String uid;
MyUser({ required this.uid });
}
class UserData {
final String uid;
final String name;
final String sugars;
final int strength;
UserData({ required this.uid, required this.sugars, required this.strength, required this.name });
}
Update Update 2 Error
Because you have to declare the provider class above the class were your using it , if u find this ans crt mark it as crt
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (ctx) => MyUser(),),
],
child: MaterialApp());
You have to warp the parent class with the provider class you are using inside. For doing so the easiest way is to add a static method in widget havingMaterialPageRoute which helps to navigate to SettingsForm screen.
class SettingsForm extends StatefulWidget {
static Widget getWidget() {
return new Provider(
create: (_) => MyUser(),
child: ChangeNotifierProvider(
create: (BuildContext context) => MyUser(),
builder: (_,_) => SettingsForm()
),
);
}
#override
_SettingsFormState createState() => _SettingsFormState();
}
To open SettingsForm screen just call getRoute function on button pressed. Check the below code.
Open SettingsForm screen from Home screen
void _showSettingsPanel() {
showModalBottomSheet(context: context, builder: (context) {
return Container(
padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 60.0),
child: SettingsForm.getWidget(), <-- Here
);
});
}
As I mentioned at the title, I got this error:
Exception caught by widgets library
Closure call with mismatched arguments: function '[]'
Receiver: Closure: () => Map<String, dynamic> from Function 'data':.
Tried calling: []("imageURL")
Found: []() => Map<String, dynamic>
I have been trying to use it to get data from firestore and show it on my app page. But I can't get the data from collection, especially for images. I referenced this tutorial from youtube. Even though I've done everything same but I couldn't handle it. Maybe bc of version. I'd be glad if you help me.
class _HomeState extends State<Home> {
PostService postService = new PostService();
Stream postStream;
//Stream postsStream;
Widget postsList() {
return SingleChildScrollView(
child: postStream != null
? Column(
children: <Widget>[
StreamBuilder(
//stream: postStream,
stream: postStream,
builder: (context, snapshot)
{
if(snapshot.data == null) return CircularProgressIndicator();
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal:16.0),
itemCount: snapshot.data.docs.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return PostTile(
imgUrl: snapshot.data.docs[index].data['imageURL'],
title: snapshot.data.docs[index].data['postTitle'],
desc: snapshot.data.docs[index].data['postDesc'],
city: snapshot.data.docs[index].data['cityName'],
);
});
}),
],
): Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
),
);
}
#override
void initState() {
postService.getPostData().then((result) {
setState(() {
postStream = result;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Ana Sayfa'),
backgroundColor: Colors.amber,
elevation: 0.0,
actions: <Widget>[
FlatButton.icon(
icon: Icon(Icons.group_rounded),
label: Text(''),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => KullaniciSayfasi()));
},
),
],
),
body: postsList(),
floatingActionButton: Container(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
onPressed: () {
//Ekleme butonuna basıldığında
Navigator.push(context,
MaterialPageRoute(builder: (context) => CreatePost()));
},
child: Icon(Icons.add),
)
],
),
),
);
}
}
Code for post service
import 'package:cloud_firestore/cloud_firestore.dart';
class PostService{
Future<void> addData(postData) async{
FirebaseFirestore.instance.collection("posts").add(postData).catchError((e){
print(e);
});
}
getPostData() async{
return await FirebaseFirestore.instance.collection("posts").snapshots();
}
}
There was a breaking change on firebase plugins and many things have changed. E.g i see you're doing snapshot.data.docs[index].data['imageURL'] this has been changed to snapshot.data.docs[index].data()['imageURL']. Kindly check the docs for the updated API refrences
I got a quick question about a flutter/dart app I am making throwing this certain error.
It has something to do with my showadddialog class. When I press the flatbutton with the text "save" in _showAddDialog() it works fine but my app crashes if I tap out of the alert dialog window without entering anything or if I press the flatbutton named "delete", and both actions give the same error. however, when I restart I can see that the delete button still worked to delete the events from the shared preferences, it just crashed afterward. What could be causing this in my code? Idk where it could be calling a map on null...
Screenshot reference: https://gyazo.com/f894ae742ea50cd714026b1bbe753678
════════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building HomePage(dirty, dependencies: [_LocalizationsScope-[GlobalKey#42494], _InheritedTheme], state: _HomePageState#acde6):
The method 'map' was called on null.
Receiver: null
Tried calling: map<Widget>(Closure: (dynamic) => ListTile)
The relevant error-causing widget was
HomePage
package:hello_world/main.dart:16
When the exception was thrown, this was the stack
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 _HomePageState.build
package:hello_world/main.dart:135
#2 StatefulElement.build
package:flutter/…/widgets/framework.dart:4334
#3 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4223
#4 Element.rebuild
package:flutter/…/widgets/framework.dart:3947
...
════════════════════════════════════════════════════════════════════════════════
Code here:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:table_calendar/table_calendar.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Calendar',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
CalendarController _controller;
Map<DateTime, List<dynamic>> _events;
List<dynamic> _selectedEvents;
TextEditingController _eventController;
SharedPreferences prefs;
#override
void initState() {
super.initState();
_controller = CalendarController();
_eventController = TextEditingController();
_events = {};
_selectedEvents = [];
initPrefs();
}
initPrefs() async {
prefs = await SharedPreferences.getInstance();
setState(() {
_events = Map<DateTime, List<dynamic>>.from(
decodeMap(json.decode(prefs.getString("events") ?? "{}"))
);
});
}
Map<String, dynamic> encodeMap(Map<DateTime, dynamic> map) {
Map<String, dynamic> newMap = {};
map.forEach((key, value) {
newMap[key.toString()] = map[key];
});
return newMap;
}
Map<DateTime, dynamic> decodeMap(Map<String, dynamic> map) {
Map<DateTime, dynamic> newMap = {};
map.forEach((key, value) {
newMap[DateTime.parse(key)] = map[key];
});
return newMap;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Calendar'),
),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TableCalendar(
events: _events,
initialCalendarFormat: CalendarFormat.week,
calendarStyle: CalendarStyle(
canEventMarkersOverflow: true,
todayColor: Colors.orange,
selectedColor: Theme.of(context).primaryColor,
todayStyle: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18.0,
color: Colors.white
)
),
headerStyle: HeaderStyle(
centerHeaderTitle: true,
formatButtonDecoration: BoxDecoration(
color: Colors.orange,
borderRadius: BorderRadius.circular(20.0),
),
formatButtonTextStyle: TextStyle(color: Colors.white),
formatButtonShowsNext: false,
),
startingDayOfWeek: StartingDayOfWeek.sunday,
onDaySelected: (date, events) {
setState(() {
_selectedEvents = events;
});
},
builders: CalendarBuilders(
selectedDayBuilder: (context, date, events) => Container(
margin: const EdgeInsets.all(4.0),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.circular(10.0)
),
child: Text(
date.day.toString(),
style: TextStyle(color: Colors.white),
)
),
todayDayBuilder: (context, date, events) => Container(
margin: const EdgeInsets.all(4.0),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.orange,
borderRadius: BorderRadius.circular(10.0)
),
child: Text(
date.day.toString(),
style: TextStyle(color: Colors.white),
)
),
),
calendarController: _controller,
),
..._selectedEvents.map((event) => ListTile(
title: Text(event),
)),
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: _showAddDialog,
),
);
}
_showAddDialog() async {
await showDialog(
context: context,
builder: (context) => AlertDialog(
content: TextField(
controller: _eventController,
),
actions: <Widget>[
FlatButton(
child: Text("Save"),
onPressed: () {
if (_eventController.text.isEmpty) return;
if (_events[_controller.selectedDay] != null) {
_events[_controller.selectedDay].add(_eventController.text);
} else {
_events[_controller.selectedDay] = [
_eventController.text
];
}
prefs.setString("events", json.encode(encodeMap(_events)));
_eventController.clear();
Navigator.pop(context);
},
),
FlatButton(
child: Text("Delete Events"),
onPressed: () {
setState(() {
_events.remove(_controller.selectedDay);
prefs.setString("events", json.encode(encodeMap(_events)));
_eventController.clear();
Navigator.pop(context);
},
);
}
)
],
)
);
setState(() {
_selectedEvents = _events[_controller.selectedDay];
});
}
}
I have gone through your code, and handled delete event null exception as per below.
Change your last setState code with below:
setState(() {
_selectedEvents = _events[_controller.selectedDay] ?? [];
});
Conclusion:
_selectedEvents null value can be handled by ?? [] in your code.
Whenever I try to tap the button created in the code below when I load the app,the debug console gives me this error.
════════ Exception caught by gesture ═══════════════════════════════════════════
Could not find a generator for route RouteSettings("/1000hz_route", null) in the _WidgetsAppState.
Here's the code I am attempting to run. How would I go about fixing this error?
import 'package:flutter/material.dart';
import 'package:audiotest/UI/player_widget.dart';
import 'package:flutter/material.dart';
import 'package:audiotest/UI/homepage1.dart';
const flutaud1 =
'https://audio.jukehost.co.uk/694139d474ee606401cc3aa8160159ac14662cd8/093232dd0c4';
void main() => runApp(new MaterialApp(
title: "TestAudio",
initialRoute: '/audio_selection',
routes: {
'/audio_selection': (context) => AudioSelection(),
'/1000hz_route': (context) => MainPersistentTabBar1(),
}));
class AudioSelection extends StatefulWidget {
#override
IntroScreenstate2 createState() => IntroScreenstate2();
}
class IntroScreenstate2 extends State<AudioSelection> {
Widget _tab(List<Widget> children) {
return Center(
child: new Container(
child: new SingleChildScrollView(
padding: EdgeInsets.all(16.0),
child: Column(
children: children
.map((w) => Container(child: w, padding: EdgeInsets.all(6.0)))
.toList(),
),
),
));
}
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: _tab([
Text(
'Audio 1000 HZ',
style: TextStyle(fontWeight: FontWeight.bold),
),
PlayerWidget(url: flutaud1),
new MaterialButton(
child: new Text('Select 1000 hz'),
onPressed: () {
Navigator.pushNamed(context, '/1000hz_route');
},
),
])
)
);
}
}
I am not sure, but the way I am telling you will get your project up and running. Let me know if it works for you.
Do this inside your onPressed
Navigator.push(context, new MaterialPageRoute(
builder: (context) => MainPersistentTabBar1())
);
Instead of
Navigator.pushNamed(context, '/1000hz_route');
I'm using Flutter for first time for one of my projects which is a Newspaper App.
The problem takes place when I try to navigate from main.dart to newsfeed_for_other_category.dart using MaterialPageRoute from my Drawer. In that screen it shows the news but with a black background. But in the screen newsfeed_screen.dart which is called in the body in my main.dart it shows perfectly.
I'm posting the codes below.
main.dart
import 'package:flutter/material.dart';
import './SizeConfig.dart';
import './screens/newsfeed_screen.dart';
import 'package:curved_navigation_bar/curved_navigation_bar.dart';
import 'factory/widget_factory.dart';
import 'widgets/top_news_widget.dart';
import 'package:splashscreen/splashscreen.dart';
import './widgets/drawer.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Newspaper App',
theme: ThemeData(
primarySwatch: Colors.blue,
//backgroundColor: Colors.lightGreenAccent,
),
home: MyHomePage(title: 'The Business Standard'),
routes: <String, WidgetBuilder> {
'/screen1': (BuildContext context) => new NewsFeedScreen(216, 5, "Top News"),
'/screen2' : (BuildContext context) => new NewsFeedScreen(4, 7, "National"),
'/screen3' : (BuildContext context) => new NewsFeedScreen(13, 70, "International"),
/*'/screen4' : (BuildContext context) => new Screen4()*/
},
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(debugLabel: '_MainScreenKey');
Widget build(BuildContext context) {
return SplashScreen(
seconds: 3,
navigateAfterSeconds: AfterSplash(),
title: Text(
'The Business Standard',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0
),
),
image: Image.asset(
'assets/TBS_logo.jpg',
),
backgroundColor: Colors.white,
styleTextUnderTheLoader: TextStyle(),
photoSize: 100.0,
onClick: ()=>print("Flutter Egypt"),
loaderColor: Colors.red
);
}
}
class AfterSplash extends StatefulWidget {
#override
_AfterSplashState createState() => _AfterSplashState();
}
class _AfterSplashState extends State<AfterSplash> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(debugLabel: '_MainScreenKey');
#override
Widget build(BuildContext context) {
SizeConfig().init(context);
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
backgroundColor: Colors.white,
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Image.asset(
'assets/TBS.png',
fit: BoxFit.cover,
height: 45,
)
],
),
leading: IconButton(
icon: Icon(Icons.dehaze),
color: Colors.black,
onPressed: () => _scaffoldKey.currentState.openDrawer(),
),
),
drawer: SideDrawer(),
body: NewsFeedScreen(22, 71, "Sports"),
bottomNavigationBar: CurvedNavigationBar(
backgroundColor: const Color(0xFF2b4849),
items: <Widget>[
Icon(Icons.bookmark, size: 30,),
Icon(Icons.perm_identity, size: 30,),
Icon(Icons.settings, size: 30,),
],
onTap: (index) {
if(index == 2) {
_scaffoldKey.currentState.showSnackBar(const SnackBar(
content: const Text('Will open Settings menu')));
} else if(index == 0) {
_scaffoldKey.currentState.showSnackBar(const SnackBar(
content: const Text('Implement Bookmark function')));
} else {
_scaffoldKey.currentState.showSnackBar(const SnackBar(
content: const Text('Will show User profile and information')));
}
},
),
);
}
}
newsfeed_for_other_category.dart, the page to which I'm navigating and this is where the black background shows up.
import 'package:flutter/material.dart';
import '../SizeConfig.dart';
import '../widgets/headlines.dart';
import '../widgets/secondary_headlines.dart';
import '../widgets/listed_news.dart';
import '../models/NewsPost.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:developer';
import '../screens/newsPost_details.dart';
import '../screens/newsfeed_for_specific_category.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
import '../transition_animation_routes/ScaleTransitionRoute.dart';
import '../widgets/top_news_widget.dart';
class NewsfeedForOtherCategory extends StatefulWidget {
int categoryId;
int childrenCategoryId;
String categoryName;
NewsfeedForOtherCategory(this.categoryId, this.childrenCategoryId, this.categoryName);
#override
_NewsfeedForOtherCategoryState createState() => _NewsfeedForOtherCategoryState(this.categoryId, this.childrenCategoryId, this.categoryName);
}
class _NewsfeedForOtherCategoryState extends State<NewsfeedForOtherCategory> {
int categoryId;
int childrenCategoryId;
String categoryName;
_NewsfeedForOtherCategoryState(this.categoryId, this.childrenCategoryId, this.categoryName);
bool _isRequestSent = false;
List<NewsPost> newsPostList = [];
#override
Widget build(BuildContext context) {
SizeConfig().init(context);
if(!_isRequestSent) {
_sendRequest();
}
return Container(
alignment: Alignment.center,
child: !_isRequestSent
? CircularProgressIndicator()
: Container(
child: ListView.builder(
itemCount: newsPostList.length,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
return _getNewsPostWidgets(index);
}
),
),
);
}
void _sendRequest() async {
String url = "https://tbsnews.net/json/category/news/"+this.categoryId.toString()+"/"+this.childrenCategoryId.toString()+"";
http.Response response = await http.get(url);
List<dynamic> decode = json.decode(response.body);
log('response: $response');
List results = decode[0]['items'];
for (var jsonObject in results) {
var post = NewsPost.getNewsPostFromAPI(jsonObject);
newsPostList.add(post);
print(post);
}
setState(() => _isRequestSent = true);
}
Widget _getNewsPostWidgets(int index) {
var newsPost = newsPostList[index];
if(index < this.newsPostList.length) {
if(index == 0) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
ScaleTransitionRoute(
page: NewsPostDetails(newsPostList, index)
)
);
},
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(10, 0, 0, 0),
//constraints: BoxConstraints(minWidth: double.infinity, maxWidth: double.infinity),
constraints: BoxConstraints.expand(
width: double.infinity,
height: 40
),
color: const Color(0xFF2b4849),
child: Text(
this.categoryName,
style: TextStyle(
fontSize: 33,
color: Colors.white
),
),
),
BlockHeadline(newsPost)
],
)
);
}
else {
return GestureDetector(
onTap: () {
Navigator.push(
context,
ScaleTransitionRoute(
page: NewsPostDetails(newsPostList, index)
)
);
},
child: ListedNews(newsPost),
);
}
}
else {
return Container(
color: const Color(0xFF2b4849),
child: index == 3 ? FlatButton(
child: Text(
"Load More",
style: TextStyle(
color: Colors.white
),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => NewsFeedForSpecificCategory(newsPostList)
)
);
},
) : Container(),
);
}
}
openNewsPostDetails(List<NewsPost> newsPostList, int index) {
Navigator.push(
context,
ScaleTransitionRoute(
page: NewsPostDetails(newsPostList, index)
)
);
}
}
drawer.dart
import 'package:flutter/material.dart';
import '../SizeConfig.dart';
import '../screens/newsfeed_for_other_category.dart';
class SideDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
SizeConfig().init(context);
return SizedBox(
width: SizeConfig.safeBlockHorizontal*50,
child: Theme(
data: Theme.of(context).copyWith(canvasColor: const Color(0xFF2b4849)),
child: Drawer(
child: ListView(
children: <Widget>[
ListTile(
title: Text(
'Top News',
style: TextStyle(
fontSize: 20,
color: Colors.white
),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => NewsfeedForOtherCategory(216, 5, "Top News")
)
);
},
),
],
),
),
),
);
}
}
In my home screen which is newsfeed_screen.dart called in the body of AfterSplashState widget in main.dart it looks like below, this is what it should look like.
But in the screen NewsfeedForOtherCategory to which I navigate using drawer looks like below with the black background.
I have tried using Navigator.of(context, rootNavigator: true).pushNamed('/route') and pushReplacementNamed() also instead of MaterialPageRoute. But of no use.
Here is a related question that I found, I tried the solutions they gave, but did not work for me.
Also to mention, the page I'm navigating to does not have MaterialApp widget, only the main.dart has it. So there should not be an issue.
I'm using a Ubuntu 16.04 machine.
Some clue from you would be priceless. Thanks a lot for your time.
NewsfeedForOtherCategory page is black because it doesn't have Material container.
You can simply wrap it with Material widget or Scaffold(which has some additional features like drawer, floating action button).
And from your screenshot I can see some widgets are overflowed by notification bar. You can use SafeArea inside Material or inside body of the Scaffold to overcome this.
Wrap the main Container in NewsfeedForOtherCategory with a scaffold and you have your solution.
...
return Scaffold(
body: Container(
alignment: Alignment.center,
child: !_isRequestSent
? CircularProgressIndicator()
: Container(
child: ListView.builder(
itemCount: newsPostList.length,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
return _getNewsPostWidgets(index);
}
),
),
);
);
...
In the build function of your NewsfeedForOtherCategory widget,
try wrapping what you have there in a Scaffold.
Like:
return Scaffold(
body: Container(
alignment: Alignment.center,
child: !_isRequestSent
? CircularProgressIndicator()
: Container(
child: ListView.builder(
itemCount: newsPostList.length,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
return _getNewsPostWidgets(index);
}),
),
),
),
when we navigate between two screen both screen parent should be scafold
if you don't want to use scaffold u can use container color property also
Try wrapping your container in scaffold in NewsfeedForOtherCategory screen Like this
...
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
),
);
}
...
Or u can set container color white like this
...
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child:
//enter code here
);
}
...