What is the use of BlocSelector in flutter_bloc - flutter

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

Related

black screen with Dismissible

i am trying to call Navigator.pop(context); from Dismissible like following
#override
Widget build(BuildContext context) {
return Dismissible(
key: const Key('some key here'),
direction: DismissDirection.down,
onDismissed: (l) {
Navigator.pop(context);
},
child: const Scaffold(
backgroundColor: Colors.yellowAccent,
),
);
}
}
it is work fine but the problem is once i swipe i see black screen !
how could i make it transparent so i can see the previous page instead of black screen ..
if it is not possible with Dismissible please suggest to me any other way to make it done
import 'package:flutter/material.dart';
class myFirstPag extends StatefulWidget {
const myFirstPag({Key? key}) : super(key: key);
#override
myFirstPagState createState() => myFirstPagState();
}
class myFirstPagState extends State<myFirstPag> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: (){
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return mySecPag();
}
)
);
},
child: const Scaffold(
backgroundColor: Colors.red,
body: Center(child: Text('my First Page')
),
),
);
}
}
class mySecPag extends StatefulWidget {
const mySecPag({Key? key}) : super(key: key);
#override
mySecPagState createState() => mySecPagState();
}
class mySecPagState extends State<mySecPag> {
#override
Widget build(BuildContext context) {
return Dismissible(
key: const Key('some key here'),
direction: DismissDirection.down,
onDismissed: (l) {
Navigator.pop(context);
},
child: const Scaffold(
backgroundColor: Colors.yellowAccent,
body: Center(child: Text('my sec page'),),
),
);
}
}
I don't think you will able to achive it by Dismissible widget:
I have modified your code slightly to this:
import 'package:flutter/material.dart';
class myFirstPag extends StatefulWidget {
const myFirstPag({Key? key}) : super(key: key);
#override
myFirstPagState createState() => myFirstPagState();
}
class myFirstPagState extends State<myFirstPag> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return mySecPag();
}));
},
child: const Scaffold(
backgroundColor: Colors.red,
body: Center(child: Text('my First Page')),
),
);
}
}
class mySecPag extends StatefulWidget {
const mySecPag({Key? key}) : super(key: key);
#override
mySecPagState createState() => mySecPagState();
}
class mySecPagState extends State<mySecPag> {
#override
Widget build(BuildContext context) {
return Dismissible(
key: const Key('some key here'),
direction: DismissDirection.down,
background: Container(color: Colors.red),
onDismissed: (l) {
Navigator.pop(context);
},
child: const Scaffold(
backgroundColor: Colors.yellowAccent,
body: Center(
child: Text('my sec page'),
),
),
);
}
}
I have added background property in Dismisible Widget, now whenever you swipe you can see that color will be shown.
But the style you want to achieve, you can do it with CupertinoRoutes.
Example of your code using CupertinoRoutes routes:
class myFirstPag extends StatefulWidget {
const myFirstPag({Key? key}) : super(key: key);
#override
myFirstPagState createState() => myFirstPagState();
}
class myFirstPagState extends State<myFirstPag> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(mySecPag.route());
},
child: const Scaffold(
backgroundColor: Colors.red,
body: Center(child: Text('my First Page')),
),
);
}
}
class mySecPag extends StatefulWidget {
const mySecPag({Key? key}) : super(key: key);
static Route<dynamic> route() {
return CupertinoPageRoute(
builder: (BuildContext context) {
return mySecPag();
},
);
}
#override
mySecPagState createState() => mySecPagState();
}
class mySecPagState extends State<mySecPag> {
#override
Widget build(BuildContext context) {
return const Scaffold(
backgroundColor: Colors.yellowAccent,
body: Center(
child: Text('my sec page'),
),
);
}
}
Here's the full tutorial for it: Link
i found solution finally ..
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
class FirstRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: Center(
child: RaisedButton(
child: Text('Open route'),
onPressed: () {
showGeneralDialog(
barrierLabel: "Label",
barrierDismissible: false,
barrierColor: Colors.black.withOpacity(0.5),
transitionDuration: Duration(milliseconds: 400),
context: context,
pageBuilder: (context, anim1, anim2) {
return SecondRoute();
},
transitionBuilder: (context, anim1, anim2, child) {
return SlideTransition(
position: Tween(begin: Offset(0, 1), end: Offset(0, 0))
.animate(anim1),
child: child,
);
},
);
},
),
),
);
}
}
class SecondRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Dismissible(
direction: DismissDirection.vertical,
key: const Key('key'),
onDismissed: (_) => Navigator.of(context).pop(),
child: Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Align(
alignment: Alignment.center,
child: Container(
height: 300,
width: 300,
child: SizedBox.expand(child: FlutterLogo()),
margin: EdgeInsets.only(bottom: 50, left: 12, right: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(40),
),
),
),
),
);
}
}
Try This Code:
it is work fine!
import 'package:flutter/material.dart';
class mySecPag extends StatefulWidget {
const mySecPag({Key? key}) : super(key: key);
#override
mySecPagState createState() => mySecPagState();
}
class mySecPagState extends State<mySecPag> {
#override
Widget build(BuildContext context) {
return Dismissible(
background: Container(
color: Colors.red,
),
key: const Key('some key here'),
direction: DismissDirection.down,
onDismissed: (l) {
},
child: const Scaffold(
backgroundColor: Colors.yellowAccent,
body: Center(child: Text('my Contents'),),
),
);
}
}
You can try this code:
First screen
import 'package:flutter/material.dart';
import 'package:surplus_construction/screens/trash/trash_file.dart';
class NewTrash extends StatefulWidget {
const NewTrash({super.key});
#override
State<NewTrash> createState() => _TrashViewState();
}
class _TrashViewState extends State<NewTrash> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.yellowAccent,
body: Center(
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => TrashView()),
);
},
child: Text('Press me')),
),
),
);
}
}
Second screen:
import 'package:flutter/material.dart';
class TrashView extends StatefulWidget {
const TrashView({super.key});
#override
State<TrashView> createState() => _TrashViewState();
}
class _TrashViewState extends State<TrashView> {
#override
Widget build(BuildContext context) {
return Dismissible(
background: Container(
color: Colors.grey,
),
key: const Key('some key here'),
direction: DismissDirection.down,
onDismissed: (l) {
Navigator.pop(context);
},
child: const Scaffold(
backgroundColor: Colors.red,
),
);
}
}

flutter/dart: 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 5140 pos 12: '_history.isNotEmpty': is not true

I have used persistent_bottom_nav_bar: ^5.0.2 and I have used bunch of pages and every page has app bar and on app bar is logout button when I try to logout It throw this mentioned exception.(Long story short).
any help would be appreciated thanks.
the following is scenario like which I have implemented :
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
#override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
GlobalKey<FormState> formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: ListView(
children: [
Form(
key: formKey,
child: Column(
children: [
FloatingActionButton(
onPressed: () async {
if (formKey.currentState!.validate()) {
if (accessToken != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MultiProvider(
providers: [
ChangeNotifierProvider<DashboardProvider>(
create: (context) => DashboardProvider()),
],
child: Dashboard(),
),
),
);
}
}
},
),
],
),
),
],
),
),
);
}
}
////////////////////////////////////////////////////////////////////////////////
class Dashboard extends StatefulWidget {
Dashboard({Key? key}) : super(key: key);
static PersistentTabController controller =
PersistentTabController(initialIndex: 0);
#override
State<Dashboard> createState() => _DashboardState();
}
class _DashboardState extends State<Dashboard> {
List<Widget> _buildScreen() {
return [
HomePage(),
FoTotalOrdersLocation(),
];
}
List<PersistentBottomNavBarItem> _navigationBarItems() {
return [
PersistentBottomNavBarItem(
icon: Icon(
Icons.home,
size: 30,
),
textStyle: TextStyle(fontSize: 20),
title: ("Home"),
),
PersistentBottomNavBarItem(
icon: Icon(
Icons.location_on,
size: 30,
),
textStyle: TextStyle(fontSize: 20),
title: ("Location"),
),
];
}
#override
void initState() {
super.initState();
if (Dashboard.controller.index == 0) {}
}
#override
Widget build(BuildContext context) {
print("build called");
return Scaffold(
body: ChangeNotifierProvider(
create: (context) => FoHomePageProvider(context),
child: PersistentTabView(
context,
controller: Dashboard.controller,
screens: _buildScreen(),
items: _navigationBarItems(),
onItemSelected: (val) async {},
),
),
);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
Navigator.popUntil(
context,
ModalRoute.withName(' /loginPage'),
);
},
icon: Icon(Icons.logout),
),
),
body:ElevatedButtonWidget(
text: "Next",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UsersPage(),
),
),
);
}
),
);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
import 'package:flutter/material.dart';
class UsersPage extends StatelessWidget {
const UsersPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
Navigator.popUntil(
context,
ModalRoute.withName(' /loginPage'),
);
},
icon: Icon(Icons.logout),
),
),
body: Text("Users page"),
);
}
}
when I try to logout the following exception is thrown :
════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building Navigator(dirty, dependencies: [UnmanagedRestorationScope, HeroControllerScope], state: NavigatorState#5900b(tickers: tracking 0 tickers)):
'package:flutter/src/widgets/navigator.dart': Failed assertion: line 5140 pos 12: '_history.isNotEmpty': is not true.
package:flutter/…/widgets/navigator.dart:5140
2

RangeError: Invalid value: Not in inclusive range 0..2: 3 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

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(),
);
}
}

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);
},
),
),
);
}