I want to mark the event once every 4 days.
example today is the 1st, mark the event will be available on the 5th, 10th, 15th, 20th, 25th, 30th, etc.
if today is the 3rd, the event will be available on the 8th, 13th, 18th, etc.
how does that function work?
I use this calendar plugin
https://pub.dev/packages/flutter_calendar_carousel
Following is the function to mark event manually:
EventList<Event> _markedDateMap = new EventList<Event>();
build(){
_calendarCarouselNoHeader = CalendarCarousel<Event>(
...
markedDatesMap: _markedDateMap,
...
),
}
#override
void initState() {
_markedDateMap.add(
new DateTime(2020, 2, 26),
new Event(
date: new DateTime(2020, 2, 26),
title: 'Event 5',
icon: _eventIcon,
));
_markedDateMap.add(
new DateTime(2020, 2, 26),
new Event(
date: new DateTime(2020, 2, 26),
title: 'Event 5',
icon: _eventIcon,
));
super.initState();
}
Any anwser will appreciated.
You can copy paste run full code below
working demo show when pass start date time with
addMarker(DateTime(2020, 2, 01));
addMarker(DateTime(2020, 2, 03));
code snippet
addMarker(DateTime startEventDateTime) {
var eventDateTime = startEventDateTime;
for(int i=0; i<5; i++) {
if(eventDateTime.day == 1) {
eventDateTime = eventDateTime.add(Duration(days: (4)));
} else {
eventDateTime = eventDateTime.add(Duration(days: (5)));
}
print(eventDateTime.toLocal());
_markedDateMap.add(
eventDateTime,
Event(
date: eventDateTime,
title: 'Event $i',
icon: _eventIcon,
));
}
}
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter_calendar_carousel/flutter_calendar_carousel.dart'
show CalendarCarousel;
import 'package:flutter_calendar_carousel/classes/event.dart';
import 'package:flutter_calendar_carousel/classes/event_list.dart';
import 'package:intl/intl.dart' show DateFormat;
void main() => runApp( MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'dooboolab flutter calendar',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Calendar Carousel Example'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
DateTime _currentDate = DateTime(2020, 2, 17);
DateTime _currentDate2 = DateTime(2020, 2, 17);
String _currentMonth = DateFormat.yMMM().format(DateTime(2020, 2, 17));
DateTime _targetDateTime = DateTime(2020, 2, 17);
// List<DateTime> _markedDate = [DateTime(2018, 9, 20), DateTime(2018, 10, 11)];
static Widget _eventIcon = Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(1000)),
border: Border.all(color: Colors.blue, width: 2.0)),
child: Icon(
Icons.person,
color: Colors.amber,
),
);
EventList<Event> _markedDateMap = EventList<Event>();
CalendarCarousel _calendarCarousel, _calendarCarouselNoHeader;
#override
void initState() {
addMarker(DateTime(2020, 2, 03));
super.initState();
}
addMarker(DateTime startEventDateTime) {
var eventDateTime = startEventDateTime;
for(int i=0; i<5; i++) {
if(eventDateTime.day == 1) {
eventDateTime = eventDateTime.add(Duration(days: (4)));
} else {
eventDateTime = eventDateTime.add(Duration(days: (5)));
}
print(eventDateTime.toLocal());
_markedDateMap.add(
eventDateTime,
Event(
date: eventDateTime,
title: 'Event $i',
icon: _eventIcon,
));
}
}
#override
Widget build(BuildContext context) {
/// Example with custom icon
_calendarCarousel = CalendarCarousel<Event>(
onDayPressed: (DateTime date, List<Event> events) {
this.setState(() => _currentDate = date);
events.forEach((event) => print(event.title));
},
weekendTextStyle: TextStyle(
color: Colors.red,
),
thisMonthDayBorderColor: Colors.grey,
// weekDays: null, /// for pass null when you do not want to render weekDays
headerText: 'Custom Header',
// markedDates: _markedDate,
weekFormat: true,
markedDatesMap: _markedDateMap,
height: 200.0,
selectedDateTime: _currentDate2,
showIconBehindDayText: true,
// daysHaveCircularBorder: false, /// null for not rendering any border, true for circular border, false for rectangular border
customGridViewPhysics: NeverScrollableScrollPhysics(),
markedDateShowIcon: true,
markedDateIconMaxShown: 2,
selectedDayTextStyle: TextStyle(
color: Colors.yellow,
),
todayTextStyle: TextStyle(
color: Colors.blue,
),
markedDateIconBuilder: (event) {
return event.icon;
},
minSelectedDate: _currentDate.subtract(Duration(days: 360)),
maxSelectedDate: _currentDate.add(Duration(days: 360)),
todayButtonColor: Colors.transparent,
todayBorderColor: Colors.green,
markedDateMoreShowTotal:
false, // null for not showing hidden events indicator
// markedDateIconMargin: 9,
// markedDateIconOffset: 3,
);
/// Example Calendar Carousel without header and custom prev & next button
_calendarCarouselNoHeader = CalendarCarousel<Event>(
todayBorderColor: Colors.green,
onDayPressed: (DateTime date, List<Event> events) {
this.setState(() => _currentDate2 = date);
events.forEach((event) => print(event.title));
},
daysHaveCircularBorder: true,
showOnlyCurrentMonthDate: false,
weekendTextStyle: TextStyle(
color: Colors.red,
),
thisMonthDayBorderColor: Colors.grey,
weekFormat: false,
// firstDayOfWeek: 4,
markedDatesMap: _markedDateMap,
height: 420.0,
selectedDateTime: _currentDate2,
targetDateTime: _targetDateTime,
customGridViewPhysics: NeverScrollableScrollPhysics(),
markedDateCustomShapeBorder: CircleBorder(
side: BorderSide(color: Colors.yellow)
),
markedDateCustomTextStyle: TextStyle(
fontSize: 18,
color: Colors.blue,
),
showHeader: false,
// markedDateIconBuilder: (event) {
// return Container(
// color: Colors.blue,
// );
// },
todayTextStyle: TextStyle(
color: Colors.blue,
),
todayButtonColor: Colors.yellow,
selectedDayTextStyle: TextStyle(
color: Colors.yellow,
),
minSelectedDate: _currentDate.subtract(Duration(days: 360)),
maxSelectedDate: _currentDate.add(Duration(days: 360)),
prevDaysTextStyle: TextStyle(
fontSize: 16,
color: Colors.pinkAccent,
),
inactiveDaysTextStyle: TextStyle(
color: Colors.tealAccent,
fontSize: 16,
),
onCalendarChanged: (DateTime date) {
this.setState(() {
_targetDateTime = date;
_currentMonth = DateFormat.yMMM().format(_targetDateTime);
});
},
onDayLongPressed: (DateTime date) {
print('long pressed date $date');
},
);
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
//custom icon
Container(
margin: EdgeInsets.symmetric(horizontal: 16.0),
child: _calendarCarousel,
), // This trailing comma makes auto-formatting nicer for build methods.
//custom icon without header
Container(
margin: EdgeInsets.only(
top: 30.0,
bottom: 16.0,
left: 16.0,
right: 16.0,
),
child: Row(
children: <Widget>[
Expanded(
child: Text(
_currentMonth,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24.0,
),
)),
FlatButton(
child: Text('PREV'),
onPressed: () {
setState(() {
_targetDateTime = DateTime(_targetDateTime.year, _targetDateTime.month -1);
_currentMonth = DateFormat.yMMM().format(_targetDateTime);
});
},
),
FlatButton(
child: Text('NEXT'),
onPressed: () {
setState(() {
_targetDateTime = DateTime(_targetDateTime.year, _targetDateTime.month +1);
_currentMonth = DateFormat.yMMM().format(_targetDateTime);
});
},
)
],
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 16.0),
child: _calendarCarouselNoHeader,
), //
],
),
));
}
}
Related
I am implementing a calendar where I want events to be stored and that they are always available to view, currently I can store them but when I exit the application they are deleted and I can no longer see them I tried to store them in the database but they are still deleted
class control_prenatal extends StatefulWidget {
final BaseAuth auth;
const control_prenatal(this.auth);
#override
State<control_prenatal> createState() => _control_prenatalState();
}
class _control_prenatalState extends State<control_prenatal> {
CollectionReference users = FirebaseFirestore.instance.collection('dates');
late Map<DateTime, List<Event>> selectedEvents;
CalendarFormat formart = CalendarFormat.month;
DateTime selectedDay = DateTime.now();
DateTime focusedDay = DateTime.now();
final databaseRef = FirebaseDatabase.instance.ref();
var _eventController = TextEditingController();
#override
void initState() {
selectedEvents = {};
super.initState();
}
List<Event> _getEventsfromDay(DateTime date) {
return selectedEvents[date] ?? [];
}
#override
void dispose() {
_eventController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Control Prenatal'),
backgroundColor: Color.fromARGB(255, 230, 57, 137),
centerTitle: true,
),
body: SingleChildScrollView(
child: Column(
children: [
TableCalendar(
firstDay: DateTime.utc(2010, 10, 16),
lastDay: DateTime.utc(2030, 3, 14),
focusedDay: selectedDay,
calendarFormat: formart,
onFormatChanged: (CalendarFormat _formart) {
setState(() {
formart = _formart;
});
},
startingDayOfWeek: StartingDayOfWeek.sunday,
daysOfWeekVisible: true,
//Day changed
onDaySelected: (DateTime selectDay, DateTime focusDay) {
setState(() {
selectedDay = selectDay;
focusedDay = focusDay;
});
print(focusDay);
},
selectedDayPredicate: (DateTime date) {
return isSameDay(selectedDay, date);
},
eventLoader: _getEventsfromDay,
//To style the calendar
calendarStyle: CalendarStyle(
isTodayHighlighted: true,
selectedDecoration: BoxDecoration(
color: Color.fromARGB(255, 230, 57, 137),
shape: BoxShape.circle,
),
selectedTextStyle: TextStyle(color: Colors.white),
todayDecoration: BoxDecoration(
color: Colors.amber,
shape: BoxShape.circle,
),
defaultDecoration: BoxDecoration(
shape: BoxShape.circle,
),
weekendDecoration: BoxDecoration(
shape: BoxShape.circle,
),
),
headerStyle: HeaderStyle(
formatButtonVisible: true,
titleCentered: true,
formatButtonShowsNext: false,
formatButtonDecoration: BoxDecoration(
color: Color.fromARGB(255, 230, 57, 137),
borderRadius: BorderRadius.circular(5.0),
),
formatButtonTextStyle: TextStyle(
color: Colors.white,
),
leftChevronVisible: true,
rightChevronVisible: true,
headerPadding: EdgeInsets.symmetric(
horizontal: 4.0,
vertical: 5.0,
),
),
),
..._getEventsfromDay(selectedDay).map(
(Event event) => ListTile(
title: Text(event.title),
),
)
],
),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () => showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Agregar Cita'),
content: Container(
padding: const EdgeInsets.fromLTRB(30, 0, 30, 0),
child: TextField(
controller: _eventController,
decoration: const InputDecoration(
hintText: 'Nota',
labelText: 'Ingrese nota',
border: OutlineInputBorder(),
),
)),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('Cancelar')),
TextButton(
onPressed: () {
widget.auth.currentUser().then((userId) {
inserData(_eventController.text, userId);
});
if (_eventController.text.isEmpty) {
} else {
if (selectedEvents[selectedDay] != null) {
selectedEvents[selectedDay]?.add(
Event(title: _eventController.text),
);
} else {
selectedEvents[selectedDay] = [
Event(title: _eventController.text)
];
}
}
Navigator.pop(context);
_eventController.clear();
setState(() {});
return;
},
child: Text('Agendar')),
],
),
),
label: Text('Agendar Cita'),
icon: Icon(Icons.add),
backgroundColor: Color.fromARGB(255, 230, 57, 137),
),
);
}
void inserData(String date, String? userId) {
String? key = databaseRef.child("path").push().key;
databaseRef
.child("path")
.child(key!)
.set({'id': key, 'Ingrese nota': date});
}
}
As you can see in the image I can store them in a date and it shows me at the bottom
but when you leave and re-enter, what you entered is no longer there
I am new to flutter, I have built a quizz app that takes 5 questions randomly from a pool of questions and presents them to the user one after the other, then displays the total score at the end (on a different) screen with the option of retaking the quiz (with another set of randomly picked questions).
My issue I am facing is that when I choose to retake the quiz, if in the pool of questions presented there is a question from the past quiz, it still has its options highlighted (marked either wrong or correct as per the previous selection).
Can someone help me on how to totally dismiss previous choices after taking a quiz ?
This is an example of question answered in the previous quiz, and it came back with the option already highlighted (my previous answer).
[enter image description here][1]
[1]: https://i.stack.imgur.com/U1YFf.png[enter image description here][1]
Here is my code:
import 'package:flutter/material.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'package:schoolest_app/widgets/quizz/quizz_image_container.dart';
import '../../models/quizz.dart';
import '../../widgets/quizz/options_widget.dart';
import '../../widgets/quizz/quizz_border_container.dart';
import '../../widgets/quizz/result_page.dart';
class QuizzDisplayScreen extends StatefulWidget {
const QuizzDisplayScreen({
Key? key,
}) : super(key: key);
static const routeName = '/quizz-display';
#override
State<QuizzDisplayScreen> createState() => _QuizzDisplayScreenState();
}
class _QuizzDisplayScreenState extends State<QuizzDisplayScreen> {
enter code here
late String quizzCategoryTitle;
late List<Question> categoryQuestions;
late List<Question> quizCategoryQuestions;
var _loadedInitData = false;
#override
void didChangeDependencies() {
if (!_loadedInitData) {
final routeArgs =
ModalRoute.of(context)!.settings.arguments as Map<String, String>;
quizzCategoryTitle = (routeArgs['title']).toString();
// final categoryId = routeArgs['id'];
categoryQuestions = questions.where((question) {
return question.categories.contains(quizzCategoryTitle);
}).toList();
quizCategoryQuestions =
(categoryQuestions.toSet().toList()..shuffle()).take(5).toList();
_loadedInitData = true;
}
super.didChangeDependencies();
}
late PageController _controller;
int _questionNumber = 1;
int _score = 0;
int _totalQuestions = 0;
bool _isLocked = false;
void _resetQuiz() {
for (var element in quizCategoryQuestions) {
setState(()=> element.isLocked == false);
}
}
#override
void initState() {
super.initState();
_controller = PageController(initialPage: 0);
}
#override
void dispose() {
_controller.dispose();
_resetQuiz();
super.dispose();
}
#override
Widget build(BuildContext context) {
final myPrimaryColor = Theme.of(context).colorScheme.primary;
final mySecondaryColor = Theme.of(context).colorScheme.secondary;
double answeredPercentage =
(_questionNumber / quizCategoryQuestions.length);
return quizCategoryQuestions.isEmpty
? Scaffold(
appBar: AppBar(
title: Text(
'Quizz - $quizzCategoryTitle',
style: TextStyle(color: myPrimaryColor),
),
iconTheme: IconThemeData(
color: myPrimaryColor,
),
centerTitle: true,
backgroundColor: Colors.transparent,
elevation: 0,
flexibleSpace: Container(
decoration: BoxDecoration(`enter code here`
borderRadius: const BorderRadius.only(`enter code here`
bottomLeft: Radius.circular(15),
bottomRight: Radius.circular(15),
),
color: mySecondaryColor,
border: Border.all(color: myPrimaryColor, width: 1.0),
),
),
),
body: const Center(
child: Text('Cette catégorie est vide pour l\'instant'),
))
: Scaffold(
appBar: AppBar(
title: Text(
'Quizz - $quizzCategoryTitle',
style: TextStyle(color: myPrimaryColor),
),
iconTheme: IconThemeData(
color: myPrimaryColor,
),
centerTitle: true,
backgroundColor: Colors.transparent,
elevation: 0,
flexibleSpace: Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(15),
bottomRight: Radius.circular(15),
),
color: mySecondaryColor,
border: Border.all(color: myPrimaryColor, width: 1.0),
),
),
),
body: Container(
// height: 600,
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
children: [
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(
'Question $_questionNumber/${quizCategoryQuestions.length}',
style: const TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
),
CircularPercentIndicator(
radius: 40,
// animation: true,
// animationDuration: 2000,
percent: answeredPercentage,
progressColor: myPrimaryColor,
backgroundColor: Colors.cyan.shade100,
circularStrokeCap: CircularStrokeCap.round,
center: Text(
// ignore: unnecessary_brace_in_string_interps
'${(answeredPercentage * 100).round()} %',
style: const TextStyle(
fontSize: 10, fontWeight: FontWeight.bold),
),
// lineWidth: 10,
)
],
),
const SizedBox(height: 10),
Divider(
thickness: 1,
color: myPrimaryColor,
),
Expanded(
child: PageView.builder(
itemCount: quizCategoryQuestions.length,
controller: _controller,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
final _question = quizCategoryQuestions[index];
return buildQuestion(_question);
},
),
),
_isLocked
? buildElevatedButton(context)
: const SizedBox.shrink(),
const SizedBox(height: 10),
],
),
),
);
}
Column buildQuestion(Question question) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 10),
question.text!.isNotEmpty
? QuizzBorderContainer(
childWidget: Text(
question.text!,
style: const TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
),
)
: const SizedBox.shrink(),
question.imagePath!.isNotEmpty
? QuizzImageContainer(imagePath: question.imagePath!)
: const SizedBox.shrink(),
Expanded(
child: OptionsWidget(
question: question,
onClickedOption: (option) {
if (question.isLocked) {
return;
} else {
setState(() {
question.isLocked = true;
question.selectedOption = option;
});
_isLocked = question.isLocked;
if (question.selectedOption!.isCorrect) {
_score++;
}
}
},
),
),
],
);
}
ElevatedButton buildElevatedButton(BuildContext context) {
final mySecondaryColor = Theme.of(context).colorScheme.secondary;
return ElevatedButton(
onPressed: () {
if (_questionNumber < quizCategoryQuestions.length) {
_controller.nextPage(
duration: const Duration(milliseconds: 1000),
curve: Curves.easeInExpo,
);
setState(() {
_questionNumber++;
_isLocked = false;
});
} else {
setState(() {
// _isLocked = false;
_totalQuestions = quizCategoryQuestions.length;
});
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) =>
ResultPage(score: _score, totalQuestions: _totalQuestions),
),
);
}
},
child: Text(
_questionNumber < quizCategoryQuestions.length
? 'Suivant'
: 'Voir le résultat',
style: TextStyle(
color: mySecondaryColor,
fontWeight: FontWeight.bold,
),
),
);
}
}
I don't seem to the solution to this.
And this is the code on the result page:
import 'package:flutter/material.dart';
import '../../screens/quizz/quizz_screen.dart';
class ResultPage extends StatefulWidget {
final int score;
final int totalQuestions;
const ResultPage({
Key? key,
required this.score,
required this.totalQuestions,
}) : super(key: key);
#override
State<ResultPage> createState() => _ResultPageState();
}
class _ResultPageState extends State<ResultPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
height: 150,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
'You got ${widget.score}/${widget.totalQuestions}',
style: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const QuizzScreen(),
),
);
},
child: const Text('OK'),
),
],
),
),
),
);
}
}
I don't know what is missing to get the reset right.
When you want to take retest try to dispose all the answers which are saved in the memory. Or you can use these navigators to which might help you in solving the issue. Try using pushReplacement or pushAndRemoveUntil when navigating to retest, this will clear the memory of last pages and you will achive the goal which you want.
I am trying to make a simple calendar app in Flutter. He had no problems installing the dependencies, but when he tried to add events he couldn't. It used Date.Time.now with no problem, but when it tried to do it with a specific date it failed. I would appreciate someone who could help me. Thanks a lot
import 'package:flutter_clean_calendar/flutter_clean_calendar.dart';
class MoonCalendar extends StatefulWidget {
#override
_MoonCalendarState createState() => _MoonCalendarState();
}
class _MoonCalendarState extends State<MoonCalendar> {
DateTime selectedDay;
List <CleanCalendarEvent> selectedEvent;
final Map<DateTime,List<CleanCalendarEvent>> events = {
DateTime (DateTime.utc(2022).year,DateTime.utc(07).month,DateTime.utc(15).day):
[
CleanCalendarEvent(
'Event A',
startTime: DateTime(
DateTime.utc(2022).year,DateTime.utc(7).month,DateTime.utc(15).day,10,0),
endTime: DateTime(
DateTime.utc(2022).year,DateTime.utc(7).month,DateTime.utc(15).day,12,0),
description: 'A special event',
color: Colors.blue[700]),
],
};
void _handleData(date){
setState(() {
selectedDay = date;
selectedEvent = events[selectedDay] ?? [];
});
print(selectedDay);
}
#override
void initState() {
// TODO: implement initState
selectedEvent = events[selectedDay] ?? [];
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Calendario",
style: TextStyle(fontSize: 22),
),
Text(
" Lunar",
style: TextStyle(fontSize: 22, color: Color.fromRGBO(56, 215, 199, 1)),
)
],
),
),
body: SafeArea(
child: Container(
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [
Color.fromRGBO(61, 138, 146, 0.2),
Color.fromRGBO(56, 215, 199, 0.1)
]
)
),
child: Calendar(
startOnMonday: true,
selectedColor: Colors.blue,
todayColor: Colors.red,
eventColor: Colors.green,
eventDoneColor: Colors.amber,
bottomBarColor: Colors.deepOrange,
onRangeSelected: (range) {
print('selected Day ${range.from},${range.to}');
},
onDateSelected: (date){
return _handleData(date);
},
events: events,
isExpanded: true,
dayOfWeekStyle: TextStyle(
fontSize: 15,
color: Colors.black12,
fontWeight: FontWeight.w100,
),
bottomBarTextStyle: TextStyle(
color: Colors.black87,
),
hideBottomBar: false,
hideArrows: false,
weekDays: ['Lun','Mar','Mié','Jue','Vie','Sáb','Dom'],
),
),
),
);
}
} ```
I'm implementing some custom buttons using this package:
bottom_bar_with_sheet 2.1.0
I added the following code snippet below, but I am not able to remove the default selection of the button when clicking on the child buttons I have been trying in many ways but not being able to progress.
bottomNavigationBar: BottomBarWithSheet(
// selectedIndex: selectedPosition > 3 ? 4 : _selectedIndex,
selectedIndex: _selectedIndex,
controller: _bottomBarController,
onSelectItem: (index) {
setState(() {
_selectedIndex = selectedPosition > 3 ? -1 : index;
});
},
and in the action button of the child I did like this:
setState(() {
selectedPosition = posicao;
_selectedIndex = posicao;
});
Thanks in advance for all the help.
One of my problems was solved how can I add navigation where each button would lead to a parent route of a view, and this view will have other screen possibilities, where it will have routes too, what better way to do that in this plugin
using good practice like mobx?
this is the code in a single file, but I would like to separate the components.
import 'package:bottom_bar_with_sheet/bottom_bar_with_sheet.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
iconTheme: IconThemeData(
color: Colors.blue,
),
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _bottomBarController = BottomBarWithSheetController(initialIndex: -1);
int selectedPosition = 4;
int _selectedIndex = -1;
#override
void initState() {
_bottomBarController.itemsStream.listen((i) {
if( i < 4 )
{
setState(() {
selectedPosition = -1;
_selectedIndex = i;
});
}
switch(i)
{
// case "HOME" : FutureBuilder: Navigator.pushReplacement(context, MaterialPageRoute(builder: (context)=> Home())); break;
case 0: print("Acesso rápido 0");break;
case 1: print("Acesso rápido 1");break;
case 2: print("Acesso rápido 2");break;
case 3: print("Acesso rápido 3");break;
}
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue,
body: Center(
child: Text(
"Criar navegacao aqui",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w900,
),
),
),
bottomNavigationBar: BottomBarWithSheet(
selectedIndex:_selectedIndex,
controller: _bottomBarController,
bottomBarTheme: BottomBarTheme(
mainButtonPosition: MainButtonPosition.middle, // posicao do botao de 'mais -> (+)'
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(25)),
),
itemIconColor: Colors.grey,
itemTextStyle: TextStyle(
color: Colors.grey,
fontSize: 10.0,
),
selectedItemTextStyle: TextStyle(
color: Colors.blue,
fontSize: 10.0,
),
),
onSelectItem: (index) {
setState(() {
_selectedIndex = index;
});
},
sheetChild: Padding(
padding: EdgeInsets.only(top:10,bottom:6),
child:Column(
children: <Widget>[
Divider(
height: 10,
thickness: 2,
color: Colors.blue,
indent: 0,
),
Expanded(
child: GridView.count(
physics: NeverScrollableScrollPhysics(), //kill scrollable
// shrinkWrap: true,
crossAxisCount: 4,
children: <Widget>[
_createBottomBarSheetChild(context, 'Home', Icons.api_sharp, _routeMenu, 4),
_createBottomBarSheetChild(context, 'Produto', Icons.apartment, _routeMenu, 5),
_createBottomBarSheetChild(context, 'Cliente', Icons.person, _routeMenu, 6),
_createBottomBarSheetChild(context, 'Proposta', Icons.account_balance_wallet_outlined, _routeMenu, 7),
],
),
),
Expanded(
child: GridView.count(
physics: NeverScrollableScrollPhysics(), //kill scrollable
// shrinkWrap: true,
crossAxisCount: 4,
children: <Widget>[
_createBottomBarSheetChild(context, 'Reservas', Icons.add_location_rounded, _routeMenu, 8),
_createBottomBarSheetChild(context, 'Unidade', Icons.workspaces_filled, _routeMenu, 9),
_createBottomBarSheetChild(context, 'Contratos', Icons.work, _routeMenu, 10),
_createBottomBarSheetChild(context, 'Tarefas', Icons.calendar_today, _routeMenu, 11),
],
),
),
],
),
),
items: [
BottomBarWithSheetItem(label: "Notas",icon: Icons.notes),
BottomBarWithSheetItem(label: "Perfil",icon: Icons.account_circle),
BottomBarWithSheetItem(label: "Configurações",icon: Icons.settings),
BottomBarWithSheetItem(label: "Alertas",icon: Icons.add_alert),
],
),
);
}
#override
Widget _createBottomBarSheetChild(BuildContext context, String name, IconData icon, Function action, posicao)
{
return GestureDetector(
child: Card(
elevation: 0,
margin: EdgeInsets.only(
left: 3.0,
top: 25,
right: 3.0
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(
icon,
size: 26,
color: selectedPosition == posicao ? Colors.blue : Colors.grey,
),
Container(
margin: EdgeInsets.only(top: 4, bottom: 6, ),
child: Column(
children: [
Text(
name,
// textAlign: TextAlign.center,
style: TextStyle(
color: selectedPosition == posicao ?
Colors.blue :
Colors.grey,
),
),
Divider(
height: 16,
thickness: 2,
color: selectedPosition == posicao ? Colors.blue : Colors.grey,
indent: 30,
endIndent:30
),
],
)
),
],
),
),
onTap: () {
// Navigator.pop(context);
setState(() {
selectedPosition = posicao;
_bottomBarController.selectItem(posicao);
});
Navigator.of(context);
action(context, name, posicao);
},
);
}
_routeMenu(context, rota, posicao)
{
print("rota ${rota.toUpperCase()}");
switch(rota.toUpperCase())
{
case "HOME" :""; posicao = 5;break;
case "PRODUTO":"";posicao = 6;break;
case "CLIENTE": "";posicao = 7; break;
case "PROPOSTA": "";posicao = 8; break;
case "RESERVA": "";posicao = 9; break;
case "UNIDADE": "";posicao = 10; break;
case "NOVIDADE": "";posicao = 11; break;
case "TAREFAS": "";posicao = 12; break;
}
}
}
NOTE: The code may seem very long, but for this question you don't need to understand every part of it.
I have an app, which gets data from an API to build a chart with it. I use the Syncfusion cartesian chart package. This is an economic indicator, so it brings a date and a value, for example:
[[2015 Oct, 0.24],[2015 Nov, 0.26],[2015 Dec, 0.32],[2016 Jan, 0.35],[2016 Feb, 0.40],[2016 Mar, 0.48]]
So, once the data arrives (It has a loading screen for waiting the data form the HTTP request), I build the chart with it.
So in this case, my Parent widget is named ChartScreen. Here's the code:
class ChartScreen extends StatefulWidget {
#override
State<ChartScreen> createState() => _ChartScreenState();
}
class _ChartScreenState extends State<ChartScreen> {
String dropdownValue = '';
initState() {
dropdownValue = '2016';
return super.initState();
}
#override
Widget build(BuildContext context) {
final enterpriseProvider = Provider.of<EnterpriseProvider>(context);
final resp = enterpriseProvider.indicator;
List<IpcData> data = _createIpcList(resp, dropdownValue);
if( data.length == 0 ) {
return Scaffold(
appBar: AppBar(
title: Text('Obteniendo datos...'),
),
body: Container(
color: Colors.black,
width: double.infinity,
height: double.infinity,
child: Center(
child: CircularProgressIndicator(),
),
),
);
}
return
Scaffold(
appBar: AppBar(
title: Text('IPC'),
actions:[
Padding(
padding: const EdgeInsets.all(8.0),
child: DropdownButton(
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.white,
),
onChanged: (String? newValue) {
dropdownValue = newValue!;
data = _createIpcList(resp, dropdownValue);
setState(() {});
},
items: <String>['2016', '2017', '2018', '2019']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList()
),
)
]
),
drawer: SideMenu(),
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Container(
child: ResultChart( formattedData: data )###############################
),
),
],
)
);
}
_createIpcList(List<List<dynamic>> resp, [String? year]) {
print('EL AÑOO');
print(year);
List<IpcData>finalList = [];
if(resp.length != 0) {
for(int i = 0; i < resp.length; i++) {
try {
resp[i][0] = DateFormat.yMMM().format(DateTime.parse(resp[i][0]));
} catch(e) {}
}
}
List<IpcData> ipcList = resp.map((e) => IpcData(e[0], e[1])).toList();
if (year!= null) {
for(int i = 0; i < ipcList.length; i++){
if (ipcList[i].date.contains(year)){
finalList.add(ipcList[i]);
}
}
}
return finalList;
}
}
With the _createIpcList I format the JSON data, so the chart can use it. I highlighted the line in which I call the child whose state I want to update. But before that, you can se that I added a dropdown menu, to select a year from a (hardcoded) list. When the dropdown menu selected item changes (see onChanged), I call the SetState and pass the 'year parameter' to the _createIpcList, which filters the data and returns the items that belong to the selected year. Here's the child code:
class ResultChart extends StatefulWidget {
final List<IpcData> formattedData;
const ResultChart({
Key? key,
required this.formattedData
}) : super(key: key);
#override
_ResultChartState createState() => _ResultChartState();
}
class _ResultChartState extends State<ResultChart> {
late List<IpcData> _chartData;
#override
void initState() {
_chartData = widget.formattedData;
super.initState();
}
#override
Widget build(BuildContext context) {
return Container(
child: SfCartesianChart(
backgroundColor: Colors.black,
enableAxisAnimation: false,
trackballBehavior: TrackballBehavior(
enable: true,
shouldAlwaysShow: true,
tooltipSettings: InteractiveTooltip(
borderWidth: 2,
borderColor: Colors.grey,
color: Colors.grey[400],
format: 'point.x : point.y'
)
),
zoomPanBehavior: ZoomPanBehavior(
enablePanning: true,
enablePinching: true,
enableDoubleTapZooming: true,
zoomMode: ZoomMode.xy,
),
primaryXAxis: CategoryAxis(
labelRotation: 90,
labelStyle: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.grey[400]
),
axisLine: AxisLine(
width: 2,
color: Colors.grey
),
majorGridLines: MajorGridLines(width: 1),
),
primaryYAxis: NumericAxis(
labelStyle: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.grey[400]
),
axisLine: AxisLine(
width: 2,
color: Colors.grey
),
title: AxisTitle( text: 'IPC', textStyle: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
majorGridLines: MajorGridLines(width: 1),
),
series: <ChartSeries>[
LineSeries<IpcData, String>(
color: Colors.blue,
dataSource: _chartData,
xValueMapper: (IpcData data, _) => data.date,
yValueMapper: (IpcData data, _) => data.value
)
],)
);
}
}
class IpcData {
final String date;
final double value;
IpcData(this.date, this.value);
}
My problem is that, no matter which year I select, the chart doesn't change. I know that the 'dropdownValue' changes because I debugged with some prints() but I don´t know how to rebuild or set state of the ResultChart widget.
Well it turn out that I continued debugging, and actually the ResultChart widget was being rebuilt again and again, but I never called the setState function inside the children. Beginner error I know, but I'm new with Flutter.