RangeError: Invalid value: Not in inclusive range 0..2: 3 flutter - flutter

I want to add text to the list when the onPressedButton is pressed. But I get the following error: RangeError: Invalid value: Not in inclusive range 0..2: 3 flutter
In some related answers, I confirmed that it was because 'itemCount: name.length' was not added, and I added it, but the result was the same. What is the problem?
The coding is as follows.
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var total = 3;
var name = ['김영숙', '홍길동', '피자집'];
var like = [0, 0, 0];
addName(a) {
setState(() {
name.add(a);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Text(total.toString()),
onPressed: () {
print(context.findAncestorWidgetOfExactType<MaterialApp>());
showDialog(
context: context,
builder: (context) {
return DialogUI(addName: addName);
});
},
),
appBar: AppBar(
title: Text(total.toString()),
),
body: ListView.builder(
itemCount: name.length,
itemBuilder: (context, i) {
return ListTile(
leading: Text(like[i].toString()),
title: Text(name[i]),
trailing: TextButton(
style: TextButton.styleFrom(
padding: const EdgeInsets.all(16.0),
primary: Colors.white,
backgroundColor: Colors.blue,
),
child: Text('좋아요'),
onPressed: () {
setState(() {
like[i]++;
});
},
),
);
},
),
bottomNavigationBar: BtmBar(),
);
}
}
class DialogUI extends StatelessWidget {
DialogUI({Key? key, this.addName}) : super(key: key);
final addName;
var inputData = TextEditingController();
var inputData2 = {};
#override
Widget build(BuildContext context) {
return Dialog(
child: Container(
padding: EdgeInsets.all(20),
width: 300,
height: 300,
child: Column(
children: [
TextField(
controller: inputData,
),
TextButton(
child: Text('OK'),
onPressed: () {
addName(inputData.text);
},
),
TextButton(
child: Text('Cancel'),
onPressed: () {
Navigator.pop(context);
},
)
],
),
),
);
}
}
class BtmBar extends StatelessWidget {
const BtmBar({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return BottomAppBar(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(Icons.phone),
Icon(Icons.message),
Icon(Icons.access_alarms),
],
),
);
}
}

RangeError comes up when we try to access the member of an array(here list) that doesn't exist.
Here, please check while accessing the members of name & like at a particular index do exist.

the problem is that you make name grow but not like
So you need to do
addName(a) {
setState(() {
name.add(a);
like.add(0);
});
}
so new names also have an entry for likes.
another tip is to just remove total and where you use total.toString() use name.length.toString() instead so that also shows the correct amount at all times

Related

Unable to navigate from GetX Dialog to another screen

I have follow dialog box. When I click 'Next' I want it to navigate to GamePage() screen. But unfortunately it doesn't work.
Following is the GamePage Widget
class GamePage extends StatelessWidget {
final homeCtrl = Get.find<HomeController>();
GamePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFF8fb1ca),
body: SafeArea(
child: ListView(
children: [
Padding(
padding: EdgeInsets.all(3.0.wp),
child: Row(
children: [
IconButton(
onPressed: () {
Get.back();
},
icon: const Icon(Icons.arrow_back),
),
],
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 4.0.wp),
child: Column(
children: [
SizedBox(
height: 2.0.wp,
),
Center(
child: Text(
'What ${homeCtrl.currentWord.first.wordtype} is this?',
style: TextStyle(
fontSize: 18.0.sp,
color: Colors.grey[800],
),
),
),
SizedBox(height: 10.0.wp),
WordsWidget(currentWord: homeCtrl.currentWord.first),
],
),
),
],
),
),
);
}
}
Following is the Word Widget being called from GamePage Widget
class WordsWidget extends StatelessWidget {
final currentWord;
WordsWidget({Key? key, this.currentWord}) : super(key: key);
final homeCtrl = Get.find<HomeController>();
#override
Widget build(BuildContext context) {
// var currentWord = homeCtrl.nextWord();
var shuffleword = [].obs;
shuffleword.addAll(homeCtrl.shuffleWord(currentWord.word));
TextToSpeech tts = TextToSpeech();
String language = 'en-US';
tts.setLanguage(language);
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
print('pressed here');
Get.defaultDialog(
title: 'Go to next page',
content: Container(
child: Column(
children: [
Text('You are about to move to another screen'),
ElevatedButton.icon(
onPressed: () {
Get.to(() => GamePage());
},
icon: Icon(
Icons.arrow_right,
),
label: Text('Go'))
],
),
));
},
child: Text('Open Dialog')),
],
);
}
}
Get.back() is working but not Get.to
Try
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return const GamePage();
},
),
);
},
child: Text("Next Word"),
)
Try this code -
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_memory/next_page.dart';
import 'package:image_picker/image_picker.dart';
void main() {
//check getMaterialApp is used
runApp(const GetMaterialApp(
title: 'Temp',
home: const MyApp(),
));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Image Picker'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
print('pressed here');
Get.defaultDialog(
title: 'Go to next page',
content: Container(
child: Column(
children: [
Text('You are about to move to another screen'),
ElevatedButton.icon(
onPressed: () {
Get.to(() => NextPage());
},
icon: Icon(
Icons.arrow_right,
),
label: Text('Go'))
],
),
));
},
child: Text('Open Dialog')),
),
);
}
}
and next page is -
import 'package:flutter/material.dart';
class NextPage extends StatefulWidget {
const NextPage({ Key? key }) : super(key: key);
#override
State<NextPage> createState() => _NextPageState();
}
class _NextPageState extends State<NextPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Next Page'),
),
body: Container(
child: Center(
child: Text("this is next page"),
),
),
);
}
}
And yes, you need to insure that you are using 'GetMaterialApp'.
If you want to use GetX navigation system, you should wrap your application in a GetMaterialApp instead of MaterialApp.
So in your main use this:
class GetxApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GetMaterialApp(
home: HomePage(),
);
}
}
Instead of this:
class NormalApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}

There are multiple heroes that share the same tag within a subtree in Flutterr

I have this error when I navigate from one page to another page using getx library, in first page I use indexed stack and second page using scaffold, I don't know what to do. Please help me solve this problem, I found many solutions in here but these does not same my problem.
First page:
class HomePage extends StatefulWidget {
HomePage({Key? key}) : super(key: key);
static String route = '/home';
final ScrollController _scrollController = ScrollController();
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _isVisible = true;
void _hideFloationgButton(UserScrollNotification notification) {
final ScrollDirection direction = notification.direction;
setState(() {
if (direction == ScrollDirection.reverse) {
_isVisible = false;
} else if (direction == ScrollDirection.forward) {
_isVisible = true;
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFEDF0F3),
appBar: HomeAppBar('DAK'),
body: NotificationListener<UserScrollNotification>(
onNotification: (notification) {
_hideFloationgButton(notification);
return true;
},
child: SingleChildScrollView(
controller: widget._scrollController,
child: Column(
children: const [
StoryList(),
SizedBox(
height: 30,
),
SocialList(),
SizedBox(
height: 30,
),
MiddleNavList(),
SizedBox(
height: 30,
),
PostList(),
],
),
),
),
floatingActionButton: Visibility(
visible: _isVisible,
child: FloatingActionButton(
backgroundColor: prototypeColor,
onPressed: () {
Get.toNamed(Routes.POST);
},
child: const Icon(
Icons.add_box,
color: Colors.white,
),
)));
}
}
And the second page:
class PostPage extends StatelessWidget {
const PostPage({Key? key}) : super(key: key);
static String route = '/post';
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: backgroundColor,
appBar: AppBar(
leading: InkWell(
onTap: () {
Get.back();
},
child: const Icon(
Icons.arrow_back_ios,
color: accentColor,
),
),
title: const Text(
'Create post',
style: TextStyle(color: accentColor),
),
backgroundColor: backgroundColor,
elevation: 0,
),
body: const PostBody(),
);
}
}

flutter/dart Undefined name 'context'. Try correcting the name to one that is defined, or defining the name

I have done IconButton in my main.dart appBar and I want to Navigate using this Icon to my second page named OneDice. When im trying to push it by using
Navigator.of(context).push(MaterialPageRoute(builder: (_) => OneDice(),),);
it doesnt work and I have no idea why.... Can u help me plis? The problem is with (context). Error name is in the topic. And here is mine code. Thanks for all!
import 'package:dicee/OneDice.dart';
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
return runApp(
MaterialApp(
home: Scaffold(
backgroundColor: Colors.green.shade300,
body: const DicePage(),
appBar: AppBar(
title: const Center(child: Text('Dicee')),
backgroundColor: Colors.purple,
elevation: 10.0,
actions: [
IconButton(
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => OneDice(),),);
},
icon: const Icon(
Icons.indeterminate_check_box,
size: 40,
),
),
],
),
),
),
);
}
class DicePage extends StatefulWidget {
const DicePage({Key? key}) : super(key: key);
#override
State<DicePage> createState() => _DicePageState();
}
class _DicePageState extends State<DicePage> {
int leftDiceNumber = 1;
int rightDiceNumber = 3;
void rollDice() {
setState(() {
leftDiceNumber = Random().nextInt(6) + 1;
rightDiceNumber = Random().nextInt(6) + 1;
});
}
#override
Widget build(BuildContext context) {
return Center(
child: Row(
children: [
Expanded(
child: TextButton(
onPressed: () {
// when i will press dice it calls Widget build to rebuild
rollDice();
},
child: Image.asset('images/dice$leftDiceNumber.png'),
),
),
Expanded(
child: TextButton(
onPressed: () {
rollDice();
},
child: Image.asset('images/dice$rightDiceNumber.png'),
),
),
],
),
);
}
}
You can only access context in the build method. You could do it like this.
void main() {
return runApp(
MaterialApp(
home:MyWidget(),
),
);
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.green.shade300,
body: const DicePage(),
appBar: AppBar(
title: const Center(child: Text('Dicee')),
backgroundColor: Colors.purple,
elevation: 10.0,
actions: [
IconButton(
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => OneDice(),),);
},
icon: const Icon(
Icons.indeterminate_check_box,
size: 40,
),
),
],
),
),
}
}
class DicePage extends StatefulWidget {
const DicePage({Key? key}) : super(key: key);
#override
State<DicePage> createState() => _DicePageState();
}
class _DicePageState extends State<DicePage> {
int leftDiceNumber = 1;
int rightDiceNumber = 3;
void rollDice() {
setState(() {
leftDiceNumber = Random().nextInt(6) + 1;
rightDiceNumber = Random().nextInt(6) + 1;
});
}
#override
Widget build(BuildContext context) {
return Center(
child: Row(
children: [
Expanded(
child: TextButton(
onPressed: () {
// when i will press dice it calls Widget build to rebuild
rollDice();
},
child: Image.asset('images/dice$leftDiceNumber.png'),
),
),
Expanded(
child: TextButton(
onPressed: () {
rollDice();
},
child: Image.asset('images/dice$rightDiceNumber.png'),
),
),
],
),
);
}
}
Just Use
Navigator.push(
context,
MaterialPageRoute(builder: (context) => OneDice()),);
And you can also use this code with GetX package
Get.to(() => OneDice());

flutter dependOnInheritedWidgetOfExactType() returns null

I am trying to use InheritedWidget approach to share state down the Widget tree. For this, I am making a simple counter app. You can add, subtract, multiply or divide the counter however you like.
It's a small demo so best practices are not followed. The line with code context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>() seem to be null for some reason. When looking at samples and doc, it should find the MyInheritedWidget in the widget tree and return it. However, I am getting complaints from flutter tool that it is null. And, in deed it is null when asserted as well.
What is the reasoning here for failed return here? And, how do I need to do it such that I can receive the instance?
File: main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Counter(),
);
}
}
class Counter extends StatefulWidget {
const Counter({Key? key}) : super(key: key);
#override
CounterState createState() => CounterState();
}
class CounterState extends State<Counter> {
int counter = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counter App'),
centerTitle: true,
),
body: MyInheritedWidget(
counterState: this,
child: Builder(
builder: (BuildContext innerContext) {
return CounterViewer(
counterState: MyInheritedWidget.of(context).counterState);
},
),
),
);
}
void addCounter(int value) {
setState(() {
counter++;
});
}
void subtractCounter(int value) {
setState(() {
counter--;
});
}
void multiplyCounter(int value) {
setState(() {
counter *= value;
});
}
void divideCounter(int value) {
setState(() {
counter = (counter / value).toInt();
});
}
}
class MyInheritedWidget extends InheritedWidget {
final CounterState counterState;
const MyInheritedWidget(
{Key? key, required Widget child, required this.counterState})
: super(key: key, child: child);
static MyInheritedWidget of(BuildContext context) {
final MyInheritedWidget? widget =
context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
assert(widget != null);
return widget!;
}
#override
bool updateShouldNotify(covariant InheritedWidget oldWidget) {
return true;
}
}
class CounterViewer extends StatelessWidget {
final CounterState counterState;
const CounterViewer({Key? key, required this.counterState}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
color: Colors.green.shade200,
width: MediaQuery.of(context).size.width,
height: 180,
child: Center(
child: Text(
'220',
style: TextStyle(
color: Colors.grey.shade50,
fontSize: 60,
fontWeight: FontWeight.bold,
),
),
),
),
Container(
color: Colors.grey.shade300,
padding: EdgeInsets.symmetric(vertical: 16),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () {},
child: Text('Add'),
),
ElevatedButton(
onPressed: () {},
child: Text('Subtract'),
),
ElevatedButton(
onPressed: () {},
child: Text('Multiply'),
),
ElevatedButton(
onPressed: () {},
child: Text('Divide'),
),
],
),
)
],
);
}
}
Update: I seem to have passed the wrong context to the dependOnInheritedWidgetOfExactType() method. Changing from context to innerContext fixed the issue.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counter App'),
centerTitle: true,
),
body: MyInheritedWidget(
counterState: this,
child: Builder(
builder: (BuildContext innerContext) {
return CounterViewer(
counterState: MyInheritedWidget.of(innerContext).counterState);
},
),
),
);
}

What is the use of BlocSelector in flutter_bloc

There is no example found for the usage of BlocSelector. Anyone knows the real usage of it?
Using this widget, developers can filter updates based on the current state of the bloc.
I have one solution of number counter-example, maybe its helpful for us
it's my main.dart file
import 'package:flutter/material.dart';
import 'package:untitled/counter_cubit.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
void main() => runApp(const App());
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MultiBlocProvider(
providers: [
BlocProvider<CounterCubit>(
create: (BuildContext context) => CounterCubit(),
),
],
child: const BlocListenerCounterPage(),
),
);
}
}
class BlocListenerCounterPage extends StatelessWidget {
const BlocListenerCounterPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Counter')),
body: BlocSelector<CounterCubit, int, bool>(
selector: (state) => state.isEven ? true : false,
builder: (context, booleanState) {
return Center(
child: booleanState
? Text('$booleanState')
: Icon(Icons.integration_instructions));
},
),
floatingActionButton: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () => context.read<CounterCubit>().increment(),
),
const SizedBox(height: 4),
FloatingActionButton(
child: const Icon(Icons.remove),
onPressed: () => context.read<CounterCubit>().decrement(),
),
],
),
);
}
}
and its my counter_cubit.dart (viewModel) class
import 'package:flutter_bloc/flutter_bloc.dart';
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
void decrement() => emit(state - 1);
}
Basically this example,
I am showing the Text widget when the number is even and when it's not even I am showing the Icon widget.
BlocSelector<AuthViewModel, BaseEntityState, bool>(
selector: (state) => state.user.isAuthenticated,
builder: ((context, isAuthenticated) {
return FloatingActionButton(
onPressed: doSomething,
child: isAuthenticated
? Icon(Icons.logout_outlined)
: Icon(Icons.login_outlined),
);
}
Imagine a bool variable which changes the value onPressed of a widget and rebuilds the specific widget according to the value.
class Sample extends StatefulWidget {
const Sample({Key? key}) : super(key: key);
#override
State<Sample> createState() => _SampleState();
}
class _SampleState extends State<Sample> {
bool foo = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: ElevatedButton(
onPressed: (foo) ? null : () {},
child: (foo) ? const Text('Disabled') : const Text('Enabled'),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
foo = !foo;
});
},
child: Icon(
(foo) ? Icons.flash_off : Icons.flash_auto,
color: Colors.white,
)),
);
}
}
Here, onPressed of FloatingActionButton the ElevatedButton is disabled and enabled. The same can be achieved with BlocSelector.
class Sample extends StatelessWidget {
const Sample({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return BlocSelector<SubjectBloc, SubjectState, bool>(
selector: (foo) {
//Here you change the value according to the states and return it
},
builder: (context, foo) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: ElevatedButton(
onPressed: (foo) ? null : () {},
child: (foo) ? const Text('Disabled') : const Text('Enabled'),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
foo = !foo;
});
},
child: Icon(
(foo) ? Icons.flash_off : Icons.flash_auto,
color: Colors.white,
)),
);
},
);
}
}
The best part is you can change the widget to Stateless
You can find in detail about BlocSelector class here