I am working on an application with Flutter and Dialogflow and I want to make that when I say something specific to the bot, it will take me to a screen. That is, when writing 'depresion', I want it to take me to the context of the id to which 'depresion' corresponds. I have already created an Entitie in Dialogflow 'cual' with the id of the context I want to go to, but now I am not even shown the messages from the bot and it throws me this error.
UPDATE
This is the conversation that I usually have with the bot and it appears before placing the code that appears commented to use the parameters. The idea is that when that "3" appears, it takes me to the context screen that corresponds to that id "3" that I indicate in Navigator.pusnNamed
Flutter error
Dialogflow Entitie
class dialog_flow.dart
class FlutterFactsDialogFlow extends StatefulWidget {
FlutterFactsDialogFlow({Key key, this.title}) : super(key: key);
final String title;
#override
_FlutterFactsDialogFlowState createState() => new _FlutterFactsDialogFlowState();
}
class _FlutterFactsDialogFlowState extends State<FlutterFactsDialogFlow> {
final List<FactsMessage> _messages = <FactsMessage>[];
final TextEditingController _textController = new TextEditingController();
TtsProvider ttsProvider = TtsProvider();
Widget _queryInputWidget(BuildContext context) {
return Container(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 8.0, vertical: 8.0),
child: Row(
children: <Widget>[
Flexible(
child: TextField(
controller: _textController,
onSubmitted: _submitQuery,
decoration: InputDecoration.collapsed(hintText: "Envia un mensaje"),
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 4.0),
child: IconButton(
icon: Icon(Icons.send),
onPressed: () => _submitQuery(_textController.text)),
),
],
),
),
);
}
void _dialogFlowResponse(context, query) async {
_textController.clear();
AuthGoogle authGoogle =
await AuthGoogle(fileJson: "assets/key.json").build();
Dialogflow dialogFlow =
Dialogflow(authGoogle: authGoogle, language: Language.spanish);
AIResponse response = await dialogFlow.detectIntent(query);
print(response.queryResult.parameters['cual']);
int id = int.parse(response.queryResult.parameters['cual']);
Navigator.pushNamed(context, 'home', arguments: id);
FactsMessage message = FactsMessage(
text: response.getMessage() ??
CardDialogflow(response.getListMessage()[0]).title,
name: "PsyBot",
type: false,
);
ttsProvider.hablar(response.getMessage());
setState(() {
_messages.insert(0, message);
});
}
void _submitQuery(String text) {
_textController.clear();
FactsMessage message = new FactsMessage(
text: text,
name: "Tú",
type: true,
);
setState(() {
_messages.insert(0, message);
});
_dialogFlowResponse(context, text);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("PsyBot"),
),
body: Column(children: <Widget>[
Flexible(
child: ListView.builder(
padding: EdgeInsets.all(8.0),
reverse: true, //Para mantener los últimos mensajes al final
itemBuilder: (_, int index) => _messages[index],
itemCount: _messages.length,
)),
Divider(height: 1.0),
Container(
decoration: new BoxDecoration(color: Theme.of(context).cardColor),
child: _queryInputWidget(context),
),
]),
);
}
}
class fact_message.dart
class FactsMessage extends StatelessWidget {
FactsMessage({this.text, this.name, this.type});
final String text;
final String name;
final bool type;
List<Widget> botMessage(context) {
return <Widget>[
Container(
margin: const EdgeInsets.only(right: 16.0),
child: CircleAvatar(child: Text('Bot')),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(this.name,
style: TextStyle(fontWeight: FontWeight.bold)),
Container(
margin: const EdgeInsets.only(top: 5.0),
child: Text(text),
),
],
),
),
];
}
List<Widget> userMessage(context) {
return <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text(this.name, style: Theme.of(context).textTheme.subtitle1),
Container(
margin: const EdgeInsets.only(top: 5.0),
child: Text(text),
),
],
),
),
Container(
margin: const EdgeInsets.only(left: 16.0),
child: CircleAvatar(child: new Text(this.name[0])),
),
];
}
#override
Widget build(BuildContext context) {
return new Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: this.type ? userMessage(context) : botMessage(context),
),
);
}
}
class home_page.dart
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
PageController pageController = PageController(initialPage: 0);
int pageChanged = 0;
TtsProvider ttsProvider = TtsProvider();
#override
Widget build(BuildContext context) {
final preguntaP = Provider.of<PreguntaProvider>(context);
final int idTest = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
actions: [
IconButton(icon: Icon(Icons.arrow_forward_ios), onPressed: (){
pageController.nextPage(duration: Duration(milliseconds: 150), curve: Curves.bounceInOut );
})
],
),
body: FutureBuilder<List<Pregunta>>(
future: preguntaP.fetchPreguntas(idTest),
builder: (context, AsyncSnapshot<List<Pregunta>> snapshot) {
if (snapshot.hasData){
// ttsprovider
//ttsProvider.hablar("Prueba");
List<Pregunta> preg = snapshot.data;
return PageView(
physics: new NeverScrollableScrollPhysics(),
pageSnapping: true,
reverse: false,
controller: pageController,
onPageChanged: (index){
setState(() {
pageChanged = index;
});
},
children: armarPreguntas(preg),
);
} else{
return Center(child: CircularProgressIndicator());
//return Container();
}
}
),
);
}
List<Widget> armarPreguntas(List<Pregunta> listaPreguntas){
final List<Widget> listadoWidget = [];
for (Pregunta item in listaPreguntas) {
listadoWidget.add(Pagina(item, pageController));
}
return listadoWidget;
}
}
Related
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
void main() async {
//Run this first
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Smart Bin',
home: new HomePageWidget(),
);
}
}
class HomePageWidget extends StatefulWidget {
const HomePageWidget({Key key}) : super(key: key);
#override
_HomePageWidgetState createState() => _HomePageWidgetState();
}
class _HomePageWidgetState extends State<HomePageWidget> {
final scaffoldKey = GlobalKey<ScaffoldState>();
final currentBinRecord = FirebaseFirestore.instance.collection("current_bin");
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
appBar: AppBar(
title: Text(
'SmartBin',
),
),
body: SafeArea(
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: StreamBuilder<List<CurrentBinRecord>>(
stream: queryCurrentBinRecord(
queryBuilder: (currentBinRecord) =>
currentBinRecord.orderBy('level', descending: true),
),
builder: (context, snapshot) {
// Customize what your widget looks like when it's loading.
if (!snapshot.hasData) {
return Center(
child: SizedBox(
width: 50,
height: 50,
child: CircularProgressIndicator(),
),
);
}
List<CurrentBinRecord> listViewCurrentBinRecordList =
snapshot.data;
return ListView.builder(
padding: EdgeInsets.zero,
scrollDirection: Axis.vertical,
itemCount: listViewCurrentBinRecordList.length,
itemBuilder: (context, listViewIndex) {
final listViewCurrentBinRecord =
listViewCurrentBinRecordList[listViewIndex];
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
listViewCurrentBinRecord.area,
),
Text(
listViewCurrentBinRecord.level.toString(),
),
],
);
},
);
},
),
),
],
),
),
),
);
}
}
This is the error
First error is on:
child: StreamBuilder<List<CurrentBinRecord>>
The name 'CurrentBinRecord' isn't a type so it can't be used as a type argument.
Try correcting the name to an existing type, or defining a type named 'CurrentBinRecord'.
Second error is on:
stream: queryCurrentBinRecord
The method 'queryCurrentBinRecord' isn't defined for the type '_HomePageWidgetState'.
Try correcting the name to the name of an existing method, or defining a method named 'queryCurrentBinRecord'.
Third error is on:
List<CurrentBinRecord> listViewCurrentBinRecordList =
snapshot.data;
The name 'CurrentBinRecord' isn't a type so it can't be used as a type argument.
Try correcting the name to an existing type, or defining a type named 'CurrentBinRecord'.
These is the syntax try -
return StreamBuilder(
stream: theStreamSource, // Eg a firebase query
builder: (context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, int index) {
return Text(snapshot.data.documents[index]['title']);
}
);
},
);
Hope it helps.
I think the best way to use StreamBuilder is to create separate controller class that can handle all your business logic and update UI.
// your widget class
class UIClass extends StatefulWidget {
const UIClass({Key key}) : super(key: key);
#override
_UIClassState createState() => _UIClassState();
}
class _UIClassState extends State<UIClass> {
UIClassController<List<CurrentBinRecord>> _uiController;
#override
void initState() {
_uiController = UIClassController(StreamController<List<CurrentBinRecord>>());
super.initState();
}
#override
Widget build(BuildContext context) {
return Column(
children: [
Text("Hello Everyone"),
StreamBuilder<List<CurrentBinRecord>>(
stream: _uiController.uiStream,
builder: (context, snapshot) {
if(snapshot.hasError){
return ErrorWidget();
}
else if(snapshot.connectionState == ConnectionState.waiting){
return WaitingWidget();
}
else if(snapshot.hasData){
return ListView.builder(
padding: EdgeInsets.zero,
scrollDirection: Axis.vertical,
itemCount: snapshot.data.length,
itemBuilder: (context, listViewIndex) {
final listViewCurrentBinRecord =
snapshot.data[listViewIndex];
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
listViewCurrentBinRecord.area,
),
Text(
listViewCurrentBinRecord.level.toString(),
),
],
);
},
);
}
else{
return SizedBox();
}
}
),
],
);
}
#override
void dispose() {
super.dispose();
_uiController.dispose();
}
}
// controller class to handle all business logic
// you can also split it into multiple sub controllers
class UIClassController<T> {
final StreamController<T> _controller;
// If you are using this on multiple widgets then use asBroadcastStream()
Stream<T> get uiStream => _controller.stream;
UIClassController(this._controller);
void updateMyUI([dynamic params]){
T t;
// your logic //
//------------//
_controller.sink.add(t);
}
void dispose(){
_controller.close();
}
}
Code I'm Using for StreamBuilder
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import '../door/widgets/Navbar.dart';
import '../door/widgets/sidenav.dart';
import 'package:get/get.dart';
FirebaseAuth auth = FirebaseAuth.instance;
class CartPage extends StatefulWidget {
#override
_CartPageState createState() => _CartPageState();
}
class _CartPageState extends State<CartPage> {
final FirebaseFirestore fb = FirebaseFirestore.instance;
int up = 1;
bool loading = false;
final ScrollController _scrollController = ScrollController();
#override
void initState() {
super.initState();
getCartData();
}
void addMore(qty, documentID) {
int new_qty = qty + 1;
Get.snackbar('Qty! ', new_qty.toString());
String collection_name = "cart_${auth.currentUser?.email}";
FirebaseFirestore.instance
.collection(collection_name)
.doc(documentID)
.update({
'qty': new_qty,
'updated_at': Timestamp.now(),
}) // <-- Your data
.then((_) => print('Added'))
.catchError((error) => Get.snackbar('Failed!', 'Error: $error'));
}
void minusMore(qty, documentID) {
if (qty > 1) {
int new_qty = qty - 1;
String collection_name = "cart_${auth.currentUser?.email}";
FirebaseFirestore.instance
.collection(collection_name)
.doc(documentID)
.update({
'qty': new_qty,
'updated_at': Timestamp.now(),
}) // <-- Your data
.then((_) => print('Subtracted'))
.catchError((error) => Get.snackbar('Failed!', 'Error: $error'));
}
}
Stream<QuerySnapshot> getCartData() {
String collection_name = "cart_${auth.currentUser?.email}";
return FirebaseFirestore.instance
.collection(collection_name)
.orderBy("created_at", descending: false)
.snapshots();
}
final ButtonStyle style = ElevatedButton.styleFrom(
minimumSize: Size(50, 30),
backgroundColor: Color(0xFFFFB61A),
elevation: 6,
textStyle: const TextStyle(fontSize: 11),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(20),
)));
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: Navbar.navbar(),
drawer: Sidenav.sidenav(),
body: Container(
padding: EdgeInsets.all(10.0),
child: StreamBuilder<QuerySnapshot>(
stream: getCartData(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
if (snapshot.hasError) {
return buildText('Something Went Wrong Try later');
} else {
if (!snapshot.hasData) {
return Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 100,
minHeight: 190,
maxWidth: 200,
maxHeight: 200,
),
child: Icon(Icons.shopping_cart, size: 45),
),
title: Text('No Food!'),
subtitle: const Text('Your cart is empty!'),
),
],
),
);
} else {
return ListView.builder(
physics: const BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data?.docs.length,
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 90.0,
child: Card(
elevation: 10,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
const SizedBox(
width: 20,
),
_buildImg('assets/logo.png', '60', '60'),
const SizedBox(
width: 14,
),
SizedBox(
width:
MediaQuery.of(context).size.width *
0.33,
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(
height: 20,
),
Text(
snapshot.data?.docs[index]
["name"],
maxLines: 2,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 14)),
const SizedBox(
height: 5,
),
Text(
"₹${snapshot.data?.docs[index]["price"]}",
style: const TextStyle(
fontWeight: FontWeight.w400,
fontSize: 12)),
],
),
),
const SizedBox(
width: 10,
),
Container(
margin: const EdgeInsets.only(
top: 20.0, bottom: 10.0),
decoration: BoxDecoration(
color: const Color(0xFFFFB61A),
// color: Color(0xFF0A2031),
borderRadius:
BorderRadius.circular(17)),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
crossAxisAlignment:
CrossAxisAlignment.end,
children: <Widget>[
SizedBox(
height: 40,
child: IconButton(
onPressed: () {
minusMore(
snapshot.data
?.docs[index]
["qty"],
snapshot
.data
?.docs[index]
.reference
.id);
},
color: Colors.white,
icon:
const Icon(Icons.remove)),
),
const SizedBox(
width: 5,
),
Container(
margin: const EdgeInsets.only(
bottom: 10.0),
child: Text(
"${snapshot.data?.docs[index]["qty"]}",
style: const TextStyle(
fontWeight:
FontWeight.w400,
color: Colors.white,
fontSize: 16)),
),
const SizedBox(
width: 5,
),
SizedBox(
height: 40,
child: IconButton(
color: Colors.white,
onPressed: () {
addMore(
snapshot.data
?.docs[index]
["qty"],
snapshot
.data
?.docs[index]
.reference
.id);
},
icon: const Icon(Icons.add)),
),
],
),
),
const SizedBox(
width: 10,
),
],
),
),
);
});
}
}
}
},
),
),
);
}
Widget buildText(String text) => Center(
child: Text(
text,
style: TextStyle(fontSize: 24, color: Colors.black),
),
);
_buildImg(img, hei, wid) {
return Container(
alignment: Alignment.center, // use aligment
child: Image.asset(
img,
height: double.parse(hei),
width: double.parse(wid),
fit: BoxFit.cover,
),
);
}
}
The ListView widget which is getting generated as part of the CourseStream Stream Builder isn't getting laid out correctly, as shown in the picture below. I don't see any errors within the Debug Console.
Below is the code for the CourseStream which contains the ListView.
final coursesCollection = FirebaseFirestore.instance.collection('courses').limit(10).where('courseLive', isEqualTo: true);
class CourseStream extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: coursesCollection.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(backgroundColor: kBrandColor),
);
}
}
final courseListStream = snapshot.data!.docs.map((course) {
return CourseData.fromDocument(course);
}).toList();
List<BadgedCourseCard> courseCards = [];
for (var course in courseListStream) {
final courseDocID = course.courseDocID;
final courseID = course.courseID;
final courseTitle = course.courseTitle;
final courseDescription = course.courseDescription;
final courseSubTitle = course.courseSubTitle;
final courseBadge = course.courseBadge;
final courseLevel = course.courseLevel;
final coursePaid = course.coursePaid;
final courseImage = course.courseImage;
final courseBgColor = hexToColor(course.courseBackgroundColor.toString());
final courseBgColor1 = hexToColor(course.courseBgColor1.toString());
final courseBgColor2 = hexToColor(course.courseBgColor2.toString());
final courseFgColor = hexToColor(course.courseFgColor.toString());
final courseDeliveryFormat = course.courseDeliveryFormat;
final courseLive = course.courseLive;
final badgedCourseCard = BadgedCourseCard(
courseTitle: courseTitle.toString(),
courseTitleTextColor: courseFgColor,
cardBackgroundColor: courseBgColor,
courseImage: courseImage.toString(),
courseCardTapped: () => print("Course Card Tapped"),
courseBookmarkTapped: () => print("Course Bookmark Tapped"),
);
return ListView(
physics: BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
children: courseCards,
);
},
);
}
}
Below is the code where the ListView is getting consumed.
class AppHome extends StatefulWidget {
#override
_AppHomeState createState() => _AppHomeState();
}
class _AppHomeState extends State<AppHome> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
leading: Padding(
padding: EdgeInsets.only(left: 2.5.w),
child: IconButton(
onPressed: () => Navigator.of(context).push(ScaledAnimationPageRoute(AppDrawer())),
icon: Icon(
Icons.sort,
color: Theme.of(context).iconTheme.color,
size: 6.5.w,
),
),
),
actions: <Widget>[
Padding(
padding: EdgeInsets.only(right: 2.5.w),
child: IconButton(
onPressed: null,
icon: Icon(
Icons.search,
color: Theme.of(context).iconTheme.color,
size: 6.5.w,
),
),
),
],
),
body: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.w),
child: Column(
children: [
CardHeader(
leadingText: "Courses",
trailingText: "View All",
),
SizedBox(height: 1.h),
Expanded(child: CourseStream()),
SizedBox(height: 2.h),
],
),
),
);
}
}
I'm not sure from where exactly the space is getting added below the Courses row. How can I fix it?
As discussed in the chat, this may be a solution for it.
Remove Expanded from Column() and wrap ListView with SizedBox so that you can limit height.
return SizedBox(
height: 20.5.h,
child: ListView(
physics: BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
children: courseCards,
),
);
My code is as follows:
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<CategoryModel> categories = new List<CategoryModel>();
List<ArticleModel> articles = new List<ArticleModel>();
bool _loading = true;
getNews() async{
News newsClass = News();
await newsClass.getNews();
articles = newsClass.news;
setState(() {
_loading = false;
});
}
#override
void initState() {
getNews();
categories = getCategories();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("News"),
Text("App", style: TextStyle(
color: Colors.blueAccent
),)
],
),
centerTitle: true,
elevation: 0.0,
),
body: _loading ? Center(
child: CircularProgressIndicator(),
) : SingleChildScrollView(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: <Widget>[
/// Categories
Container(
height: 70,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categories.length,
itemBuilder: (context, index){
return CategoryTile(
imageUrl: categories[index].imageUrl,
categoryName: categories[index].categoryName,
);
}),
),
/// Blog
Container(
padding: EdgeInsets.only(top: 16),
child: ListView.builder(
itemCount: articles.length,
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemBuilder: (context, index){
return BlogTile(
imageUrl: articles[index].urlToImage,
title: articles[index].title,
desc: articles[index].description,
);
}),
)
],
),
),
),
);
}
}
class CategoryTile extends StatelessWidget {
final imageUrl, categoryName;
CategoryTile({this.imageUrl, this.categoryName});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: (){
},
child: Container(
margin: EdgeInsets.only(right: 16),
child: Stack(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: CachedNetworkImage(
imageUrl: imageUrl, width: 120, height: 60, fit: BoxFit.cover,)
),
Container(
alignment: Alignment.center,
width: 120, height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
color: Colors.black26,
),
child: Text(categoryName, style: TextStyle(
color: Colors.white,
fontSize: 14,
fontWeight: FontWeight.w500
),),
)
],
),
),
);
}
}
class BlogTile extends StatelessWidget {
final String imageUrl, title, desc;
BlogTile({#required this.imageUrl,#required this.title,#required this.desc});
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.network(imageUrl)
),
SizedBox(height: 8,),
Text(title, style: TextStyle(
fontSize: 17, color: Colors.black87, fontWeight: FontWeight.w500
),),
SizedBox(height: 8,),
Text(desc, style: TextStyle(
color: Colors.black54
),)
],
),
);
}
}
When I run the code it shows the loading screen which is not going off, the content which i want to display is not showing. Please help by providing your valuable answer. Thank you in advance.
The error I am getting is as follows:
E/flutter ( 5339): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Failed assertion: boolean expression must not be null
Since you are initialising your _loading variable inside the first statement of the initState. You can as well initialise it directly when declaring it.
Like this:
bool _loading = true;
Try the code below:
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<CategoryModel> categories = new List<CategoryModel>();
List<ArticleModel> articles = new List<ArticleModel>();
bool _loading = true;
getNews() async{
News newsClass = News();
await newsClass.getNews();
articles = newsClass.news;
}
#override
void initState() {
getNews();
categories = getCategories();
setState(() {
_loading = false;
});
super.initState();
}
I hope this helps.
I have a problem, I have a main activity where I have loaded several widget classes so far so good.
now what I want to do is refresh the main page after closing a page that has been triggered in a Drawer menu.
It works if the button is directly on the main page, but if the action is triggered from the Drawer menu it does not work.
Example of screen or it works very well
Option 2
It should look like this. but it doesn't work when I call the page from the Drawer menu
reference link:
How to go back and refresh the previous page in Flutter?
How to refresh a page after back button pressed
Would anyone have an idea.
Here is the code to use for option 1 with the button on the main page:
new RaisedButton(
onPressed: ()=>
Navigator.of(context).push(new MaterialPageRoute(builder: (_)=>new PageHomeContent()),)
.then((val)=>{getRefreshRequests()}),
child: Text('Refresh', style: TextStyle(color: Colors.white), ), color: Colors.purple,
elevation: 2.0,
),
It is important to know that I have created a class for the Drawer menu here. it is a little long but I you essential
final Color primaryColor = Colors.white;
final Color activeColor = Colors.grey.shade800;
final Color dividerColor = Colors.grey.shade600;
class BuildDrawer extends StatefulWidget{
#override
_BuildDrawer createState() => _BuildDrawer();
}
class _BuildDrawer extends State<BuildDrawer> {
//region [ ATTRIUTS ]
final String image = 'https://avatars2.githubusercontent.com/u/3463865?s=460&u=c0fab43e4b105e9745dc3b5cf61e21e79c5406c2&v=4';
List<dynamic> menuGroupList = [];
Future<List<dynamic>> _futureMenuGroupList;
bool _infiniteStop;
//MenuItemGroupModel menuItemGroup = new MenuItemGroupModel();
List<dynamic> menuItemList = [];
Future<List<dynamic>> _futureMenuItemList;
//Future<MenuItemGroupModel> _futureMenuItemGroup;
bool _infiniteItemStop;
//endregion
#override
void initState() {
_futureMenuGroupList = fetchMenuWPList();
_infiniteStop = false;
}
#override
Widget build(BuildContext context) {
return ClipPath(
clipper: OvalRightBorderClipper(),
child: Drawer(
child: Container(
padding: const EdgeInsets.only(left: 16.0, right: 40),
decoration: BoxDecoration(
color: primaryColor,
boxShadow: [BoxShadow(color: Colors.black45)]),
width: 300,
child: SafeArea(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: InkWell(
onTap: () {
//Navigator.push( context, MaterialPageRoute(builder: (context) => PageHomeContent(),),);
Navigator.of(context).push(new MaterialPageRoute(builder: (_)=>new PageHomeContent()),)
.then((val)=>{ new MainPage() });
},
child:
Column(
children: <Widget>[
Row(
children: [
Icon(
Icons.format_list_bulleted,
color: activeColor,
),
SizedBox(width: 10.0),
Text("Home Content", ),
Spacer(),
]
),
],
),
),
),
Divider(
color: dividerColor,
),
],
),
),
),
),
),
);
}
}
//end Class
//region [ MENU ITEM PAGE ]
//endregion
Main Page Class [ MainPage ]
class MainPage extends StatefulWidget {
//MainPage({Key key, this.title}): super(key: key);
//final String title;
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<WPMainPage> {
//region [ ATTRIBUTS ]
List<dynamic> featuredArticles = [];
List<dynamic> latestArticles = [];
List<dynamic> pageList = [];
List<dynamic> menuGroupList = [];
List<dynamic> categoryHomeList = [];
Future<List<dynamic>> _futurePageList;
Future<List<dynamic>> _futureFeaturedArticles;
Future<List<dynamic>> _futureLastestArticles;
Widget widgetCategoryBuilder=new Container();
final _categoryRepository = CategoryRepository();
ScrollController _controller;
int page = 1;
bool _showLoadingPage = true;
bool _showLoadingCategoryHome = true;
bool _infiniteStop;
double heightNoInternet = 280.0;
// Firebase Cloud Messeging setup
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
//endregion
#override
void initState() {
super.initState();
_futureFeaturedArticles = fetchFeaturedArticles(1);
_futureLastestArticles = fetchLatestArticles(1);
_futurePageList = fetchPageList();
getCategoriesOnLocal();
_controller = ScrollController(initialScrollOffset: 0.0, keepScrollOffset: true);
_controller.addListener(_scrollListener);
_infiniteStop = false;
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(Constant.APP_NAME_LONG),
actions: getActionAppBarButton(context: context),
),
drawer: BuildDrawer(),
body: Container(
decoration: BoxDecoration(color: Colors.white70),
child: SingleChildScrollView(
controller: _controller,
scrollDirection: Axis.vertical,
child: Column(
children:
getWidgetList()
),
),
));
}
getRefreshRequests() async {
getCategoriesOnLocal();
//Tools.mySnackBar(context, ' m s g TEST 1 ');
}
getWidgetList() {
List<Widget> itemList = new List<Widget>();
itemList.add(
new Column(
children: <Widget>[
new RaisedButton(
onPressed: ()=>
Navigator.of(context).push(new MaterialPageRoute(builder: (_)=>new PageHomeContent()),)
.then((val)=>{ getRefreshRequests() }),
child: Text('Refresh', style: TextStyle(color: Colors.white), ), color: Colors.purple,
elevation: 2.0,
),
],
)
);
itemList.add(
getPagebuilderList(isShowTitle: false)
);
itemList.add(
featuredPostBuildSlider(_futureFeaturedArticles)
);
/*itemList.add(
featuredPost(_futureFeaturedArticles),
);*/
itemList.add(
widgetCategoryBuilder
);
itemList.add(
latestPosts(_futureLastestArticles)
);
return itemList;
}
_scrollListener() {
var isEnd = _controller.offset >= _controller.position.maxScrollExtent &&
!_controller.position.outOfRange;
if (isEnd) {
setState(() {
page += 1;
_futureLastestArticles = fetchLatestArticles(page);
});
}
}
//region [ ALL POST | RECENTS POST ]
//endregion
//region [ POST FEATURED | Swiper ]
//endregion
//region [ PAGES ]
//endregion
//region [ CATEGORIES LOCAL --> ON LIGNE ]
void getCategoriesOnLocal() async {
try {
await _categoryRepository.getCategories().then((itemList) {
if (itemList != null) {
setState(() {
categoryHomeList = itemList;
});
getCategoryBuilder();
}
});
} catch (e) {
Tools.println("Error: getCategoriesOnLocal: $e");
}
}
getCategoryBuilder() {
List<Widget> itemWidgetList=[];
if( _showLoadingCategoryHome) {
if (categoryHomeList.length > 0) {
for (Category category in categoryHomeList) {
if (category.count > 0) {
itemWidgetList.add(
getItemArticle(category: category)
);
}
}
widgetCategoryBuilder= Column( children: itemWidgetList );
} else {
widgetCategoryBuilder= Container();
}
} else {
widgetCategoryBuilder= Container();
}
setState(() {
widgetCategoryBuilder = widgetCategoryBuilder;
});
return widgetCategoryBuilder;
}
Widget getItemArticle({Category category}) {
return
Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 8.0, right: 8.0),
child: Row(
children: <Widget>[
Text('${category.name}',
style: homeTitleTextStyle,
textAlign: TextAlign.left,),
Spacer(),
InkWell(
onTap: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CategoryArticles(category.id, category.name),
),
);
},
child: Text('See More',
textAlign: TextAlign.right,
style: TextStyle(color: Colors.red),),
),
],),
),
new CategoryHomeBuilder( categorieId: category.id),
],
);
}
//endregion
}
Does anyone have a suggestion.
Thanks for your help
Waiting for a better response.
I replaced the BuildDrawer class with a getBuildDrawer() method in the main class.
And it works very well but I would have preferred to put it in a separate class, so that I can use it in another page ...
getBuildDrawer() {
return ClipPath(
clipper: OvalRightBorderClipper(),
child: Drawer(
child: Container(
padding: const EdgeInsets.only(left: 16.0, right: 40),
decoration: BoxDecoration(
color: primaryColor,
boxShadow: [BoxShadow(color: Colors.black45)]),
width: 300,
child: SafeArea(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: InkWell(
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).push(new MaterialPageRoute(builder: (_)=>new PageHomeContent()),)
.then((val)=>{ getRefreshRequests() });
},
child:
Column(
children: <Widget>[
Row(
children: [
Icon(
Icons.format_list_bulleted,
color: activeColor,
),
SizedBox(width: 10.0),
Text("Home Content", ),
Spacer(),
]
),
],
),
),
),
Divider(
color: dividerColor,
),
],
),
),
),
),
),
);
}
you have to refresh the page just putting setState(getRefreshRequests()) when you return from navigator, that's because the page don't know that you put a new widget on screen
I create a Switch widget in ListView for each element. When i click on switch, the value change for all elements.
I check in flutter docs, dart docs... I think, i don't recup the element position in onChanged method.
But how do ?
My value isSwitched changed when i clicked.
I recup the lignes when i cliked thanks to : snapshot.data[index].name
Theme screen :
class _ThemePage extends State<ThemePage> {
bool isSwitched = false;
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: Text("Blackbox"),
leading: Image.asset(
'assets/img/logo_ineat.png',
fit: BoxFit.contain,
height: 32,
),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new Container(
margin: EdgeInsets.only(top: 10.0, bottom: 10.0),
child: new Text('Sélection du profil',
style: new TextStyle(
fontSize: 24, fontWeight: FontWeight.bold)),
alignment: Alignment.topCenter),
new Flexible(
child: new Container(
child: new FutureBuilder<List<t.Theme>>(
future: t.Theme().getThemes(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
if (snapshot.data != null) {
return new Column(
children: <Widget>[
new Expanded(
child: new ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, index) {
return ListTile(
title:
new Text(snapshot.data[index].name),
trailing: new Switch(
value: isSwitched,
activeColor: Colors.pink,
activeTrackColor: Colors.pinkAccent,
onChanged: (value){
setState(() {
isSwitched = value;
if(value==true) {
print(snapshot.data[index].name);
}
});
},
),
);
},
),
),
],
);
}
} else {
new Text("Loading...");
return new CircularProgressIndicator();
}
}),
),
),
new Container(
margin: EdgeInsets.only(right: 10.0),
child: new RaisedButton.icon(
/*onPressed: () {
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => Technologies()));
},*/
label: Text('Suivant'),
icon: Icon(Icons.navigate_next),
),
alignment: Alignment.bottomRight,
),
],
),
),
);
}
}
you are controlling switched value with single property isSwitched
you can
create another stateful widget put your switch logic there (and if you want to read the value use a callback ) (cleaner)
create a list of bool instead of single property
your code with first solution:
class YourListViewItem extends StatefulWidget {
final String title;
const YourListViewItem({Key key, this.title}) : super(key: key);
#override
_YourListViewItemState createState() => _YourListViewItemState();
}
class _YourListViewItemState extends State<YourListViewItem> {
bool isSwitched = false;
#override
Widget build(BuildContext context) {
return ListTile(
title:
new Text(widget.title),
trailing: new Switch(
value: isSwitched,
activeColor: Colors.pink,
activeTrackColor: Colors.pinkAccent,
onChanged: (value){
setState(() {
isSwitched = value;
});
},
),
);
}
}
class _ThemePage extends State<ThemePage> {
bool isSwitched = false;
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: Text("Blackbox"),
leading: Image.asset(
'assets/img/logo_ineat.png',
fit: BoxFit.contain,
height: 32,
),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new Container(
margin: EdgeInsets.only(top: 10.0, bottom: 10.0),
child: new Text('Sélection du profil',
style: new TextStyle(
fontSize: 24, fontWeight: FontWeight.bold)),
alignment: Alignment.topCenter),
new Flexible(
child: new Container(
child: new FutureBuilder<List<t.Theme>>(
future: t.Theme().getThemes(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
if (snapshot.data != null) {
return new Column(
children: <Widget>[
new Expanded(
child: new ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, index) {
return YourListViewItem(title: snapshot.data[index].name);
},
),
),
],
);
}
} else {
new Text("Loading...");
return new CircularProgressIndicator();
}
}),
),
),
new Container(
margin: EdgeInsets.only(right: 10.0),
child: new RaisedButton.icon(
/*onPressed: () {
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => Technologies()));
},*/
label: Text('Suivant'),
icon: Icon(Icons.navigate_next),
),
alignment: Alignment.bottomRight,
),
],
),
),
);
}
}