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,
),
);
Related
I ran into problem attempting to refresh the ListView inside a FutureBuilder, I can't get it to refresh, not by using setState, not anything else, could someone more experienced with flutter suggest what is wrong with the way I utilize FutureBuilder or setState?
Here is the code that I am running into the problem with:
class ChatScreen extends StatefulWidget {
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
String contact_name;
int contact_id;
String str_id;
List<Align> messagesList = [];
Align messageUnit;
int ownID;
String ownName;
double height;
double width;
final TextEditingController messageGetter = TextEditingController();
#override
void initState() {
super.initState();
final res = Variables.getContactName();
contact_name = res;
final res_2 = Variables.getContactID();
contact_id = res_2;
str_id = res_2.toString();
final res_3 = Variables.getOwnID();
ownID = res_3;
final res_4 = Variables.getOwnName();
ownName = res_4;
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future:getMessages(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
final data = snapshot.data;
width = MediaQuery
.of(context)
.size
.width;
height = MediaQuery
.of(context)
.size
.height;
print(data);
return Scaffold(
appBar:
AppBar(
title: Text(contact_name),
backgroundColor: Color(0xD3232323),
),
body:
Column(
children: [
Expanded(
child: ListView(
children: messagesList,
reverse: true,
),
),
Container(
child: Row(
children: [
Expanded(
child: Padding(
child: TextField(
controller: messageGetter,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
borderSide: BorderSide(),
),
),
),
padding: EdgeInsets.fromLTRB(8, 8, 8, 8),
),
),
Container(
child: Padding(
child: OutlinedButton(
onPressed: () {
sendMessage();
setState(() {
getMessages();
});
},
child: Text("+"),
style: ButtonStyle(
),
),
padding: EdgeInsets.fromLTRB(8, 8, 8, 8),
),
),
],
),
),
],
)
);
}
if (snapshot.hasError) {
return Scaffold(
appBar: AppBar(
title: Text(contact_name),
backgroundColor: Color(0xD3232323),
),
body:
Container(
child:
Align(alignment: Alignment.center,
child:
Text("Error"),
),
),
);
}
if (snapshot.connectionState != ConnectionState.done) {
return Scaffold(
appBar: AppBar(
title: Text(contact_name),
backgroundColor: Color(0xD3232323),
),
body:
Container(
child:
Align(alignment: Alignment.center,
child:
CircularProgressIndicator(
),
),
),
);
}
else
return Text("Meow");
}
);
}
Future<String> getMessages() async{
final result = await context.read<TelegramService>().send(
TdApi.GetChatHistory(chatId: contact_id, limit: 1, )
);
print(result);
final res = await context.read<TelegramService>().send(
TdApi.GetChatHistory(chatId: contact_id, limit: 999)
);
TdApi.Messages messages = res;
messagesList.clear();
for(var i = 0; i < messages.totalCount; i++) {
TdApi.Message message = messages.messages[i];
TdApi.MessageContent text = message.content;
TdApi.MessageText textContent = text;
TdApi.FormattedText textFinal = textContent.text;
TdApi.MessageSenderUser messageSender = message.sender;
if (messageSender.userId == ownID) {
messageUnit = Align (
alignment: Alignment.centerRight,
child: Padding(
padding: EdgeInsets.fromLTRB(0, 8, 0, 8),
child: OutlinedButton(
child: Text(textFinal.text,
style: TextStyle(
color: Color(0xD3232323),
),
),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Color(0xD300FFEA)),
),
),
),
);
}
else {
messageUnit = Align (
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.fromLTRB(0, 8, 0, 8),
child: OutlinedButton(
child: Text(textFinal.text),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Color(0xD3383838)),
),
),
),
);
}
messagesList.add(messageUnit);
}
return "Messages Retrieved";
}
sendMessage() async {
TdApi.FormattedText messageText = TdApi.FormattedText(text: messageGetter.text, entities: []);
TdApi.MessageSendOptions messageSendOptions = TdApi.MessageSendOptions(disableNotification: false) ;
TdApi.InputMessageText message = TdApi.InputMessageText(text: messageText);
final result = await context.read<TelegramService>().send(
TdApi.SendMessage(chatId: contact_id, inputMessageContent: message, options: messageSendOptions),
);
print(result);
messageGetter.clear();
}
}
Wrap your listview with a stateful builder, like this:
StatefulBuilder(builder: (context, setState) {
return ListView(
children: messagesList,
reverse: true,);
}),
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;
}
}
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'm working on a part of an app that will essentially just be keeping track of physical tokens that are like forms of currency. I'm trying to build a reusable Widget that will take in the state of that token quantity as a parameter, and increment/decrement that based on user interaction. For the sake of clarity, I've just included the decrement part of the Widget. My question: is the state of the token that is getting passed into the widget not updating because it's just a reference to that state? Or am I missing something else.
class RedeemTokensState extends State<RedeemTokens> {
int oneQuantity = 0;
int fiveQuantity = 0;
int tenQuantity = 0;
int total = 0;
Widget _counterWidget(int tokenQuantity) {
return Row(
children: <Widget>[
Expanded(
child: IconButton(
icon: Icon(Icons.remove),
onPressed: () {
setState(() {
tokenQuantity = tokenQuantity - 1;
print(tokenQuantity);
});
},
),
),
),
}
Widget _buildOneField() {
return ListTile(
title: Text('\$1 Token'),
trailing: Container(width: 200.0, child: _counterWidget(oneQuantity)),
);
}
Widget _buildFiveField() {
return ListTile(
title: Text('\$5 Token'),
trailing: Container(width: 200.0, child: _counterWidget(fiveQuantity)),
);
}
Widget _buildTenField() {
return ListTile(
title: Text('\$10 Token'),
trailing: Container(width: 200.0, child: _counterWidget(tenQuantity)),
);
}
}
// main scaffold with build method
... Card(
child: Container(
padding: EdgeInsets.all(10.0),
child: Column(
children: <Widget>[
_buildOneField(),
Divider(),
_buildFiveField(),
Divider(),
_buildTenField(),
Divider(),
_buildFreshConnectField(),
],
),
),
),
A generic solution could look like:
Parent widget
class RedeemTokens extends StatefulWidget {
#override
RedeemTokensState createState() => RedeemTokensState();
}
class RedeemTokensState extends State<RedeemTokens> {
final _quantities = new Map<TokenType, int>.fromIterable(TokenType.values,
key: (k) => k, value: (k) => 0);
Widget build(BuildContext context) {
final widgets = <Widget>[];
for (final type in _quantities.keys) {
widgets
..add(
new TokenQuantity(
tokenType: type,
quantity: _quantities[type],
onQuantityUpdated: (newValue) {
setState(() {
print('\$${type.value}: $newValue');
print(_quantities);
_quantities[type] = newValue;
});
}),
)
..add(Divider());
}
// widgets.add(_buildFreshConnectField());
return Card(
child: Container(
padding: EdgeInsets.all(10.0),
child: Column(
children: widgets,
),
),
);
}
}
Child widget added once per TokenType
class TokenQuantity extends StatelessWidget {
const TokenQuantity(
{#required this.tokenType,
#required this.quantity,
this.onQuantityUpdated})
: assert(quantity != null);
final TokenType tokenType;
final int quantity;
final TokenQuantityUpdatedFn onQuantityUpdated;
Widget _counterWidget() {
return Row(
children: <Widget>[
Text('$quantity'),
Expanded(
child: IconButton(
icon: Icon(Icons.remove),
onPressed: () {
if (onQuantityUpdated != null) {
onQuantityUpdated(quantity - 1);
}
},
),
),
],
);
}
#override
Widget build(BuildContext context) {
return ListTile(
title: Text('\$${tokenType.value} Token'),
trailing: Container(width: 200.0, child: _counterWidget()),
);
}
}
Typedef for the event callback
typedef TokenQuantityUpdatedFn = void Function(int newValue);
"Old-style" enum to be able to set custom values.
class TokenType {
static const one = const TokenType(1);
static const fife = const TokenType(5);
static const ten = const TokenType(10);
static const values = const <TokenType>[one, fife, ten];
final int value;
const TokenType(this.value);
#override
String toString() => 'TokenType $\$value';
}