Unsupported operation: Cannot add to an unmodifiable list - flutter

I have an app that has a splash screen and an onboarding screen. There are no errors or warnings anywhere; the app runs to show the splash screen but then crashes instead of displaying the onboarding screen.
======== Exception caught by widgets library =======================================================
The following UnsupportedError was thrown building BoardingPage(dirty, state: _BoardingScreenState#e3368):
Unsupported operation: Cannot add to an unmodifiable list
The relevant error-causing widget was:
BoardingPage BoardingPage:file:///C:/Users/Srishti/AndroidStudioProjects/App-mini-project-1/lib/splash.dart:22:78
Here's my code :
splash.dart
import 'package:flutter/material.dart';
import 'boarding_screen.dart';
class Splash extends StatefulWidget {
const Splash({Key? key}) : super(key: key);
#override
State<Splash> createState() => _SplashState();
}
class _SplashState extends State<Splash> {
#override
void initState(){
super.initState();
_navigatetohome();
}
_navigatetohome() async {
await Future.delayed(Duration(milliseconds: 2500), (){});
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => BoardingPage()));
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child: Text('Your Scheduler',
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.normal,
),
),
),
),
);
}
}
slide.dart
class Slide {
String image;
String heading;
Slide(this.image, this.heading);
}
boarding_screen.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gradient_widgets/gradient_widgets.dart';
import 'package:schedule_management/slide.dart';
import 'login_screen.dart';
class BoardingPage extends StatefulWidget {
const BoardingPage({Key? key}) : super(key: key);
#override
_BoardingScreenState createState() => _BoardingScreenState();
}
class _BoardingScreenState extends State<BoardingPage> {
int _currentPage = 0;
List<Slide> _slides = [];
PageController _pageController = PageController();
#override
void initState() {
_currentPage = 0;
_slides = [
Slide("images/slide-1.png", "Manage your time"),
Slide("images/slide-2.png", "Schedule your tasks"),
Slide("images/slide-3.png", "Never miss out on any task"),
];
_pageController = PageController(initialPage: _currentPage);
super.initState();
}
// the list which contain the build slides
List<Widget> _buildSlides() {
return _slides.map(_buildSlide).toList();
}
// building single slide
Widget _buildSlide(Slide slide) {
return Column(
children: <Widget>[
Expanded(
child: Container(
margin: const EdgeInsets.all(1),
child: Image.asset(slide.image, fit: BoxFit.contain),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 70),
child: Text(
slide.heading,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.w900,
),
),
),
const SizedBox(
height: 230,
)
],
);
}
// handling the on page changed
void _handlingOnPageChanged(int page) {
setState(() => _currentPage = page);
}
// building page indicator
Widget _buildPageIndicator() {
Row row = Row(mainAxisAlignment: MainAxisAlignment.center, children: const []);
for (int i = 0; i < _slides.length; i++) {
row.children.add(_buildPageIndicatorItem(i));
if (i != _slides.length - 1) {
row.children.add(const SizedBox(
width: 12,
));
}
}
return row;
}
Widget _buildPageIndicatorItem(int index) {
return Container(
width: index == _currentPage ? 8 : 5,
height: index == _currentPage ? 8 : 5,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: index == _currentPage
? const Color.fromRGBO(136, 144, 178, 1)
: const Color.fromRGBO(206, 209, 223, 1)),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
children: <Widget>[
PageView(
controller: _pageController,
onPageChanged: _handlingOnPageChanged,
physics: BouncingScrollPhysics(),
children: _buildSlides(),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Column(
children: <Widget>[
_buildPageIndicator(),
SizedBox(height: 32,),
Container(
// see the page indicators
margin: EdgeInsets.symmetric(horizontal: 10000000),
child: SizedBox(
width: double.infinity,
child: GradientButton(
callback: () => {},
gradient: LinearGradient(colors: const [
Color.fromRGBO(11, 198, 200, 1),
Color.fromRGBO(68, 183, 183, 1)
]),
elevation: 0,
increaseHeightBy: 28,
increaseWidthBy: double.infinity,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
),
child: Text(
"",
style: TextStyle(
letterSpacing: 4,
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
)),
),
SizedBox(height: 10,),
CupertinoButton(
child: Text(
"Sign In",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
color: Colors.grey,
),
),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => LoginScreen()));
}),
SizedBox(height: 30,),
],
),
)
],
),
);
}
}
I have tried restarting Android Studio and running flutter clean but the app still crashes.

The problem probably because of the following code:
Widget _buildPageIndicator() {
Row row = Row(mainAxisAlignment: MainAxisAlignment.center, children: const []);
for (int i = 0; i < _slides.length; i++) {
row.children.add(_buildPageIndicatorItem(i));
if (i != _slides.length - 1) {
row.children.add(const SizedBox(
width: 12,
));
}
}
return row;
}
where you're trying to change the const row children. So, change it like the following code:
Widget _buildPageIndicator() {
List<Widget> children = [];
for (int i = 0; i < _slides.length; i++) {
children.add(_buildPageIndicatorItem(i));
if (i != _slides.length - 1) {
children.add(const SizedBox(
width: 12,
));
}
}
return Row(mainAxisAlignment: MainAxisAlignment.center,
children: children,
);
}

Related

How to reset my quiz app questions choices

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.

Get all the scores from all widgets

I am building a quiz app and I created a custom widget to save me a lot of time as I have a lot of questions for the quiz. Everything works apart from the scoring system. If I create multiple instances of the same widget the score will not be incremented and it will stay on 1. Is there any way I can pass each score of the widgets to a global variable in my main widget so then I can add all the scores? (I'm new to flutter).
Custom Widget
class Questions extends StatefulWidget {
final String imagePath;
final String question;
final String answer1;
final String answer2;
final String answer3;
final String answer4;
final bool iscorrectAnswer1;
final bool iscorrectAnswer2;
final bool iscorrectAnswer3;
final bool iscorrectAnswer4;
int score = 0;
bool questionsAnswered = false;
Questions(
this.imagePath,
this.question,
this.answer1,
this.answer2,
this.answer3,
this.answer4,
this.iscorrectAnswer1,
this.iscorrectAnswer2,
this.iscorrectAnswer3,
this.iscorrectAnswer4,
);
#override
_QuestionsState createState() => _QuestionsState();
}
class _QuestionsState extends State<Questions> {
disableButton() {
setState(() {
widget.questionsAnswered = true;
Quiz().score += widget.score;
});
}
#override
#override
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(
width: 600,
height: 600,
child: Image.asset(widget.imagePath),
),
Align(
alignment: Alignment.topCenter,
child: Padding(
padding: EdgeInsets.only(
top: 20,
),
child: Text(
widget.question,
style: TextStyle(
color: Colors.white,
fontSize: 38,
),
),
)),
Padding(
padding: EdgeInsets.only(
top: 40,
),
child: SizedBox(
width: 500,
height: 60,
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(15)),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
Color(0xFF304e60),
),
),
child: Text(
widget.answer1,
style: TextStyle(
color: Colors.white,
fontSize: 15,
),
),
onPressed: widget.questionsAnswered == false
? () {
setState(() {
if (widget.iscorrectAnswer1 == true) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Correct!'),
),
);
disableButton();
widget.score += 1;
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
content: Text('Wrong Answer!'),
));
}
});
print(widget.iscorrectAnswer1);
print(widget.score);
}
: null),
),
)),
Padding(
padding: EdgeInsets.only(
top: 10,
),
child: SizedBox(
width: 500,
height: 60,
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(15)),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Color(0xFF565462))),
child: Text(
widget.answer2,
style: TextStyle(
color: Colors.white,
fontSize: 15,
),
),
onPressed: widget.questionsAnswered == false
? () {
setState(() {
if (widget.iscorrectAnswer2 == true) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Correct!'),
),
);
widget.score += 1;
} else {
disableButton();
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
content: Text('Wrong Answer!'),
));
}
});
}
: null),
),
)),
Padding(
padding: EdgeInsets.only(
top: 10,
),
child: SizedBox(
width: 500,
height: 60,
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(15)),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Color(0xFF84693b))),
child: Text(
widget.answer3,
style: TextStyle(
color: Colors.white,
fontSize: 15,
),
),
onPressed: widget.questionsAnswered == false
? () {
setState(() {
if (widget.iscorrectAnswer3 == true) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Correct!'),
),
);
widget.score += 1;
} else {
disableButton();
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
content: Text('Wrong Answer!'),
));
}
});
}
: null),
),
),
)
],
);
}
}
Main widget where I call this custom widget
class Quiz extends StatefulWidget {
Quiz({Key? key}) : super(key: key);
int score = 0;
#override
_QuizState createState() => _QuizState();
}
class _QuizState extends State<Quiz> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('CyberQuiz'),
),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Questions(
'images/malware_quiz.jpeg',
'1. What is a malware?',
'Designed to damage computers, servers or any other devices',
"Used to get user's credentials",
"It's used to destroy networks",
'',
true,
false,
false,
false,
),
],
)));
}
}
As you suggest in your question, you could create a global variable and increment/decrease/reset that.
Basic example code:
import 'package:flutter/material.dart';
class Score {
static int score = 0;
}
class ScoreCounter extends StatefulWidget {
const ScoreCounter({Key? key}) : super(key: key);
#override
State<ScoreCounter> createState() => _ScoreCounterState();
}
class _ScoreCounterState extends State<ScoreCounter> {
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: ElevatedButton(
onPressed: () {
setState(() {
Score.score++;
});
},
child: Text('increase score'),
),
),
Expanded(child: Text(Score.score.toString()))
],
);
}
}
Another option is to use the Provider package - link here which has an example
Provider Package

Null check operator used on a null value Carousel Flutter

Good Morning,
I'm trying to put a Carousel on the home page looking for Firebase data, but for some reason, the first time I load the application it appears the message below:
════════ Exception caught by widgets library ═════════════════════════════════════ ══════════════════
The following _CastError was thrown building DotsIndicator (animation: PageController # 734f9 (one client, offset 0.0), dirty, state: _AnimatedState # 636ca):
Null check operator used on a null value
and the screen looks like this:
After giving a hot reload the error continues to appear, but the image is loaded successfully, any tips of what I can do?
HomeManager:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provantagens_app/models/section.dart';
class HomeManager extends ChangeNotifier{
HomeManager({this.images}){
_loadSections();
images = images ?? [];
}
void addSection(Section section){
_editingSections.add(section);
notifyListeners();
}
final List<dynamic> _sections = [];
List<String> images;
List<dynamic> newImages;
List<dynamic> _editingSections = [];
bool editing = false;
bool loading = false;
int index, totalItems;
final Firestore firestore = Firestore.instance;
Future<void> _loadSections() async{
loading = true;
firestore.collection('home').snapshots().listen((snapshot){
_sections.clear();
for(final DocumentSnapshot document in snapshot.documents){
_sections.add( Section.fromDocument(document));
images = List<String>.from(document.data['images'] as List<dynamic>);
}
});
loading = false;
notifyListeners();
}
List<dynamic> get sections {
if(editing)
return _editingSections;
else
return _sections;
}
void enterEditing({Section section}){
editing = true;
_editingSections = _sections.map((s) => s.clone()).toList();
defineIndex(section: section);
notifyListeners();
}
void saveEditing() async{
bool valid = true;
for(final section in _editingSections){
if(!section.valid()) valid = false;
}
if(!valid) return;
loading = true;
notifyListeners();
for(final section in _editingSections){
await section.save();
}
for(final section in List.from(_sections)){
if(!_editingSections.any((s) => s.id == section.id)){
await section.delete();
}
}
loading = false;
editing = false;
notifyListeners();
}
void discardEditing(){
editing = false;
notifyListeners();
}
void removeSection(Section section){
_editingSections.remove(section);
notifyListeners();
}
void onMoveUp(Section section){
int index = _editingSections.indexOf(section);
if(index != 0) {
_editingSections.remove(section);
_editingSections.insert(index - 1, section);
index = _editingSections.indexOf(section);
}
notifyListeners();
}
HomeManager clone(){
return HomeManager(
images: List.from(images),
);
}
void onMoveDown(Section section){
index = _editingSections.indexOf(section);
totalItems = _editingSections.length;
if(index < totalItems - 1){
_editingSections.remove(section);
_editingSections.insert(index + 1, section);
index = _editingSections.indexOf(section);
}else{
}
notifyListeners();
}
void defineIndex({Section section}){
index = _editingSections.indexOf(section);
totalItems = _editingSections.length;
notifyListeners();
}
}
HomeScreen:
import 'package:carousel_pro/carousel_pro.dart';
import 'package:flutter/material.dart';
import 'package:provantagens_app/commom/custom_drawer.dart';
import 'package:provantagens_app/commom/custom_icons_icons.dart';
import 'package:provantagens_app/models/home_manager.dart';
import 'package:provantagens_app/models/section.dart';
import 'package:provantagens_app/screens/home/components/home_carousel.dart';
import 'package:provantagens_app/screens/home/components/menu_icon_tile.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
// ignore: must_be_immutable
class HomeScreen extends StatelessWidget {
HomeManager homeManager;
Section section;
List<Widget> get children => null;
String videoUrl = 'https://www.youtube.com/watch?v=VFnDo3JUzjs';
int index;
var _tapPosition;
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(colors: const [
Colors.white,
Colors.white,
], begin: Alignment.topCenter, end: Alignment.bottomCenter)),
child: Scaffold(
backgroundColor: Colors.transparent,
drawer: CustomDrawer(),
appBar: AppBar(
backgroundColor: Colors.transparent,
iconTheme: IconThemeData(color: Colors.black),
title: Text('Página inicial', style: TextStyle(color: Color.fromARGB(255, 30, 158, 8))),
centerTitle: true,
actions: <Widget>[
Divider(),
],
),
body: Consumer<HomeManager>(
builder: (_, homeManager, __){
return ListView(children: <Widget>[
AspectRatio(
aspectRatio: 1,
child:HomeCarousel(homeManager),
),
Column(
children: <Widget>[
Container(
height: 50,
),
Divider(
color: Colors.black,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Padding(
padding: const EdgeInsets.only(left:12.0),
child: MenuIconTile(title: 'Parceiros', iconData: Icons.apartment, page: 1,),
),
Padding(
padding: const EdgeInsets.only(left:7.0),
child: MenuIconTile(title: 'Beneficios', iconData: Icons.card_giftcard, page: 2,),
),
Padding(
padding: const EdgeInsets.only(right:3.0),
child: MenuIconTile(title: 'Suporte', iconData: Icons.help_outline, page: 6,),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
MenuIconTile(iconData: Icons.assignment,
title: 'Dados pessoais',
page: 3)
,
MenuIconTile(iconData: Icons.credit_card_outlined,
title: 'Meu cartão',
page: 4)
,
MenuIconTile(iconData: Icons.account_balance_wallet_outlined,
title: 'Pagamento',
page: 5,)
,
],
),
Divider(
color: Colors.black,
),
Container(
height: 50,
),
Consumer<HomeManager>(
builder: (_, sec, __){
return RaisedButton(
child: Text('Teste'),
onPressed: (){
Navigator.of(context)
.pushReplacementNamed('/teste',
arguments: sec);
},
);
},
),
Text('Saiba onde usar o seu', style: TextStyle(color: Colors.black, fontSize: 20),),
Text('Cartão Pró Vantagens', style: TextStyle(color: Color.fromARGB(255, 30, 158, 8), fontSize: 30),),
AspectRatio(
aspectRatio: 1,
child: Image.network(
'https://static.wixstatic.com/media/d170e1_80b5f6510f5841c19046f1ed5bca71e4~mv2.png/v1/fill/w_745,h_595,al_c,q_90,usm_0.66_1.00_0.01/Arte_Cart%C3%83%C2%B5es.webp',
fit: BoxFit.fill,
),
),
Divider(),
Container(
height: 150,
child: Row(
children: [
AspectRatio(
aspectRatio: 1,
child: Image.network(
'https://static.wixstatic.com/media/d170e1_486dd638987b4ef48d12a4bafee20e80~mv2.png/v1/fill/w_684,h_547,al_c,q_90,usm_0.66_1.00_0.01/Arte_Cart%C3%83%C2%B5es_2.webp',
fit: BoxFit.fill,
),
),
Padding(
padding: const EdgeInsets.only(left:20.0),
child: RichText(
text: TextSpan(children: <TextSpan>[
TextSpan(
text: 'Adquira já o seu',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
TextSpan(
text: '\n\CARTÃO PRÓ VANTAGENS',
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 30, 158, 8)),
),
]),
),
),
],
),
),
Divider(),
tableBeneficios(),
Divider(),
Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Text(
'O cartão Pró-Vantagens é sediado na cidade de Hortolândia/SP e já está no mercado há mais de 3 anos. Somos um time de profissionais apaixonados por gestão de benefícios e empenhados em gerar o máximo de valor para os conveniados.'),
FlatButton(
onPressed: () {
launch(
'https://www.youtube.com/watch?v=VFnDo3JUzjs');
},
child: Text('SAIBA MAIS')),
],
),
),
Container(
color: Color.fromARGB(255, 105, 190, 90),
child: Column(
children: <Widget>[
Row(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Text(
'© 2020 todos os direitos reservados a Cartão Pró Vantagens.',
style: TextStyle(fontSize: 10),
),
)
],
),
Divider(),
Row(
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Text(
'Rua Luís Camilo de Camargo, 175 -\n\Centro, Hortolândia (piso superior)',
style: TextStyle(fontSize: 10),
),
),
Padding(
padding: const EdgeInsets.only(left: 16),
child: IconButton(
icon: Icon(CustomIcons.facebook),
color: Colors.black,
onPressed: () {
launch(
'https://www.facebook.com/provantagens/');
},
),
),
Padding(
padding: const EdgeInsets.only(left: 16),
child: IconButton(
icon: Icon(CustomIcons.instagram),
color: Colors.black,
onPressed: () {
launch(
'https://www.instagram.com/cartaoprovantagens/');
},
),
),
],
),
],
),
)
],
),
]);
},
)
),
);
}
tableBeneficios() {
return Table(
defaultColumnWidth: FlexColumnWidth(120.0),
border: TableBorder(
horizontalInside: BorderSide(
color: Colors.black,
style: BorderStyle.solid,
width: 1.0,
),
verticalInside: BorderSide(
color: Colors.black,
style: BorderStyle.solid,
width: 1.0,
),
),
children: [
_criarTituloTable(",Plus, Premium"),
_criarLinhaTable("Seguro de vida\n\(Morte Acidental),X,X"),
_criarLinhaTable("Seguro de Vida\n\(Qualquer natureza),,X"),
_criarLinhaTable("Invalidez Total e Parcial,X,X"),
_criarLinhaTable("Assistência Residencial,X,X"),
_criarLinhaTable("Assistência Funeral,X,X"),
_criarLinhaTable("Assistência Pet,X,X"),
_criarLinhaTable("Assistência Natalidade,X,X"),
_criarLinhaTable("Assistência Eletroassist,X,X"),
_criarLinhaTable("Assistência Alimentação,X,X"),
_criarLinhaTable("Descontos em Parceiros,X,X"),
],
);
}
_criarLinhaTable(String listaNomes) {
return TableRow(
children: listaNomes.split(',').map((name) {
return Container(
alignment: Alignment.center,
child: RichText(
text: TextSpan(children: <TextSpan>[
TextSpan(
text: name != "X" ? '' : 'X',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
TextSpan(
text: name != 'X' ? name : '',
style: TextStyle(
fontSize: 10.0,
fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 30, 158, 8)),
),
]),
),
padding: EdgeInsets.all(8.0),
);
}).toList(),
);
}
_criarTituloTable(String listaNomes) {
return TableRow(
children: listaNomes.split(',').map((name) {
return Container(
alignment: Alignment.center,
child: RichText(
text: TextSpan(children: <TextSpan>[
TextSpan(
text: name == "" ? '' : 'Plano ',
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
TextSpan(
text: name,
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 30, 158, 8)),
),
]),
),
padding: EdgeInsets.all(8.0),
);
}).toList(),
);
}
void _storePosition(TapDownDetails details) {
_tapPosition = details.globalPosition;
}
}
I forked the library to create a custom carousel for my company's project, and since we updated flutter to 2.x we had the same problem.
To fix this just update boolean expressions like
if(carouselState.pageController.position.minScrollExtent == null ||
carouselState.pageController.position.maxScrollExtent == null){ ... }
to
if(!carouselState.pageController.position.hasContentDimensions){ ... }
Here is flutter's github reference.
This worked for me
So I edited scrollposition.dart package
from line 133
#override
//double get minScrollExtent => _minScrollExtent!;
// double? _minScrollExtent;
double get minScrollExtent {
if (_minScrollExtent == null) {
_minScrollExtent = 0.0;
}
return double.parse(_minScrollExtent.toString());
}
double? _minScrollExtent;
#override
// double get maxScrollExtent => _maxScrollExtent!;
// double? _maxScrollExtent;
double get maxScrollExtent {
if (_maxScrollExtent == null) {
_maxScrollExtent = 0.0;
}
return double.parse(_maxScrollExtent.toString());
}
double? _maxScrollExtent;
Just upgrade to ^3.0.0 Check here https://pub.dev/packages/carousel_slider
I faced the same issue.
This is how I solved it
class PlansPage extends StatefulWidget {
const PlansPage({Key? key}) : super(key: key);
#override
State<PlansPage> createState() => _PlansPageState();
}
class _PlansPageState extends State<PlansPage> {
int _currentPage = 1;
late CarouselController carouselController;
#override
void initState() {
super.initState();
carouselController = CarouselController();
}
}
Then put initialization the carouselController inside the initState method I was able to use the methods jumpToPage(_currentPage ) and animateToPage(_currentPage) etc.
I use animateToPage inside GestureDetector in onTap.
onTap: () {
setState(() {
_currentPage = pageIndex;
});
carouselController.animateToPage(_currentPage);
},
I apologize in advance if this is inappropriate.
I solved the similar problem as follows. You can take advantage of the Boolean variable. I hope, help you.
child: !loading ? HomeCarousel(homeManager) : Center(child:ProgressIndicator()),
or
child: isLoading ? HomeCarousel(homeManager) : SplashScreen(),
class SplashScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('Loading...')
),
);
}
}

Solving the exception: The getter 'iterator' was called on null

I'm trying to solve an issue where I get the runtime exception:
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The getter 'iterator' was called on null.
Receiver: null
Tried calling: iterator
The relevant error-causing widget was:
RecordTile AndroidStudioProjects/abc/lib/screens/clinical_records_screen.dart:80:31
════════════════════════════════════════════════════════════════════════════════════════════════════
The exception is in the line:
return loading
? LoadingAnimation()
: RecordTile(
records: clinical_records,
position: position,
);
and is being generated even after I have wrapped it in a try/catch block. How do I get to the root of this? I tried checking whether an element in the list is null.
My code is as follows:
class PreviousRecordsSummaryScreen extends StatefulWidget {
static const String id = 'ClinicalRecordsScreen';
List<CheckinNew> clinical_records;
Customer customer;
PreviousRecordsSummaryScreen({
this.clinical_records,
this.customer,
});
#override
_PreviousRecordsSummaryScreenState createState() =>
_PreviousRecordsSummaryScreenState();
}
class _PreviousRecordsSummaryScreenState
extends State<PreviousRecordsSummaryScreen> {
List<CheckinNew> clinical_records;
Customer customer;
bool loading;
List<CheckinNew> sortedRecords(List<CheckinNew> initialList) {
print("Sorting by date.. newest first");
List<CheckinNew> sortList = initialList;
sortList.sort((b, a) => a.actualDate.compareTo(b.actualDate));
print(sortList); // [two, four, three]
return sortList;
}
#override
void initState() {
clinical_records = widget.clinical_records;
customer = widget.customer;
print("Customer: ${customer.name} ${customer.cstid}");
loading = false;
super.initState();
}
#override
Widget build(BuildContext context) {
print("In ClinicalRecordsScreen");
print("clinical_records is $clinical_records");
clinical_records = sortedRecords(clinical_records);
return Scaffold(
appBar: AppBar(title: Text("${widget.customer.name}'s visits")),
body: Container(
child: ListView(
shrinkWrap: true,
children: [
clinical_records == null
? Container()
: ListView.builder(
shrinkWrap: true,
itemCount: (clinical_records == null)
? 0
: clinical_records.length,
itemBuilder: (BuildContext context, int position) {
print(
"Before calling RecordTile, position:$position clinical_records:$clinical_records ");
print("Printing each element");
int index = 0;
for (CheckinNew el in clinical_records) {
print("el: $el $index");
index++;
}
try {
return loading
? LoadingAnimation()
: RecordTile(
records: clinical_records,
position: position,
);
} catch (e) {
return Container();
}
},
),
],
),
),
);
}
}
class RecordTile extends StatefulWidget {
RecordTile({
this.records,
this.position,
this.expanded = false,
});
List<CheckinNew> records;
int position;
bool expanded;
#override
_RecordTileState createState() => _RecordTileState();
}
class _RecordTileState extends State<RecordTile> {
bool expanded;
List<CheckinNew> records;
int position;
#override
void initState() {
expanded = widget.expanded;
records = widget.records;
position = widget.position;
super.initState();
}
Widget medicines(List<MedsResponse> meds) {
List<Widget> mylist = [];
for (MedsResponse presc in meds) {
print(presc.brand);
mylist.add(Divider(
height: 10,
));
mylist.add(
Wrap(
alignment: WrapAlignment.start,
crossAxisAlignment: WrapCrossAlignment.start,
children: [
CircleAvatar(
radius: 10,
backgroundColor: Colors.grey.shade800,
child: Text((meds.indexOf(presc) + 1).toString()),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 2),
),
Text(
presc.brand,
style: TextStyle(color: Colors.black),
),
],
),
);
mylist.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 2),
),
);
mylist.add(
Row(
children: [
Padding(padding: EdgeInsets.symmetric(horizontal: 10)),
Text(
'${presc.dose} ${presc.unit} ${presc.freq} x ${presc.durn} ${presc.durnunit}',
style: TextStyle(color: Colors.black),
),
],
),
);
mylist.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 2),
),
);
mylist.add(
Wrap(
children: [
Padding(padding: EdgeInsets.symmetric(horizontal: 10)),
Text(
'(${presc.generic})',
style: TextStyle(
color: Colors.black,
),
),
],
),
);
mylist.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 2),
),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: mylist,
);
}
#override
Widget build(BuildContext context) {
print("Is expanded");
return Card(
child: InkWell(
onTap: () {
print("expanded is $expanded");
setState(() {
expanded = !expanded;
});
},
child: ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${widget.records[widget.position].dateLong()} ${widget.records[widget.position].time}'),
Text('Checkin #${records[widget.position].checkinno}'),
],
),
subtitle: !expanded
? Text(
records[position].clinicalRecord.diagnosis_as_string(),
textAlign: TextAlign.left,
style: TextStyle(
// color: Colors.white,
),
)
: Container(
// color: Colors.pink,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(padding: EdgeInsets.symmetric(vertical: 3)),
Text(
records[position].clinicalRecord.diagnosis_as_string(),
textAlign: TextAlign.left,
style: TextStyle(
color: Colors.black,
decorationThickness: 10,
),
),
Padding(padding: EdgeInsets.symmetric(vertical: 3)),
Text(records[position].clinicalRecord.history),
Padding(padding: EdgeInsets.symmetric(vertical: 3)),
Text(records[position].clinicalRecord.examination),
Padding(padding: EdgeInsets.symmetric(vertical: 3)),
Text("Treatment:"),
medicines(records[position].prescribedDrugs),
],
),
),
),
),
);
}
}

RangeError (index): Invalid value: Not in range 0..8, inclusive: 9 in Gridview.Count

I found a solution ListView.builder "You should pass the itemCount parameter to the ListView.builder to allow it to know the item count" but not working for GridView.count.
Another exception was thrown: RangeError (index): Invalid value: Not in range 0..8, inclusive: 9
import 'package:thunder_mobile/screens/dashboard-page/common-list-page/common_list.dart';
import 'package:thunder_mobile/screens/dashboard-page/parent-views/materials/material_list.dart';
import 'package:thunder_mobile/utils/all_api_calls.dart';
import 'package:thunder_mobile/widgets/app-bar/app_bar_tabs.dart';
import 'package:thunder_mobile/widgets/icons/thunder_svg_icons.dart';
import 'package:thunder_mobile/widgets/loading/custom-loading.dart';
import 'teacher_homework_classes_modal.dart';
class SubjectWiseHomework extends StatefulWidget {
final String title;
const SubjectWiseHomework({Key key, this.title}) : super(key: key);
#override
State<StatefulWidget> createState() {
return new GridViewSubjectsState();
}
}
class GridViewSubjectsState extends State<SubjectWiseHomework> {
List<SubjectList> subjectList;
var _isLoading = true;
var jsonApiService = JsonApiHelper();
#override
void initState() {
super.initState();
getSubjectList();
}
getSubjectList() {
jsonApiService.fetchMaster().then((res) {
print(res);
setState(() {
subjectList = res.subjectList;
_isLoading = false;
});
});
}
List<String> headerTitles = [
"Science",
"Economics",
"Accounts",
"Mathematic",
"Economics",
"Accounts",
"Mathematic",
"Economics",
"Accounts"
];
List<String> headerIcons = [
'assets/Science.svg',
'assets/Economics.svg',
'assets/Economics_1.svg',
'assets/Mathematic.svg',
'assets/Economics.svg',
'assets/Economics_1.svg',
'assets/Mathematic.svg',
'assets/Economics.svg',
'assets/Economics_1.svg',
];
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: _appBarView(),
body: _isLoading ? CommonLoading().loadingWidget() : _bodyView());
}
_appBarView() {
return PreferredSize(
child: CustomAppBar(
titleText: 'Subject List',
firstIcons: "search",
bottom: false,
),
preferredSize: Size(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height / 10.5),
);
}
_bodyView() {
return new Container(
padding: EdgeInsets.only(top: 30.0, left: 20.0, right: 20.0),
child: new GridView.count(
crossAxisCount: 3,
children: List.generate(subjectList.length, (index) {
return new Center(
child:
Container(
decoration: BoxDecoration(
border: Border.all(
width: 0.5,
// style: BorderStyle.solid,
color: Theme.of(context).textSelectionColor),
borderRadius: BorderRadius.all(Radius.circular(5.0))),
width: MediaQuery.of(context).size.width / 3.8,
height: MediaQuery.of(context).size.height / 5,
child: new Column(
children: <Widget>[
new Container(
height: 30.0,
color: Theme.of(context).highlightColor,
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'Subject List',
style: TextStyle(
color: Theme.of(context).textSelectionColor,
fontSize: 15.0,
fontWeight: FontWeight.w600),
)
],
),
),
new Container(
child: new Expanded(
child: IconButton(
icon: ThunderSvgIcons(
path: headerIcons[index],
height: 60.0,
color: Theme.of(context).primaryColor,
),
iconSize: 60.0,
onPressed: () => {}
),
)),
],
),
),
);
})),
);
}
You are using List.generate(subjectList.length, (index) {...}); to create list of widgets (children) for your GridView. Therefore, the max value of index equals (subjectList.length - 1).
Then you use the index to get headerIcons here:
path: headerIcons[index]
The headerIcons has 9 items (max index of headerIcons array is 8), but the index from subjectList could be larger than 8. In that case you get the exception.
Hot fix:
path: headerIcons[index % headerIcons.length],