Opening a text field causes the parrent widget to rebuild - flutter

my app is structured like this:
class MainPage extends StatefulWidget {
MainPage({Key? key}) : super(key: key);
#override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
#override
Widget build(BuildContext context) {
BlocProvider.of<NavigationBloc>(context).add(const DashboardEvent());
int _selectedIndex = 0;
return Scaffold(
appBar: AppBar(
elevation: 0,
The Main Page is responsible for navigation via the navigation bloc. Different buttons add different events depending on what page I want to show. Up to this point everything was working normally but all of sudden when I open any TextField in my app, it causes this main page to rebuild, calling the DashboardEvent and the page with the text field disappear.
I know that opening a TextField causes flutter to call the build method, but up to this point, in only caused the page to rebuild, not the parent widget. I have no idea why is it behaving like this all of sudden. Is there any setting I could toggle that I don't remember that could cause this behavior ? Thank you

class MainPage extends StatefulWidget {
MainPage({Key? key}) : super(key: key);
#override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
#override
initState(){
BlocProvider.of<NavigationBloc>(context).add(const DashboardEvent());
int _selectedIndex = 0;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,

Related

three clases use setState callback to update var on other class

I have next thre classes:
Shortly the scenario: have two classes MyApp1, MyApp2 and MyApp3,
MyApp3 updates the var count with callback (indeed updated), I would like to print it (count) on MyApp2, how can I setState also on MyApp2 so it will take effect?
my_app1.dart
class MyApp1 extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp1> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final int count = 0;
void callbakc() {
setState(() {
count++;
});
}
#override
Widget build(BuildContext context) {
return Container(
Row(
children:[
MyApp2(),
MyApp3(callback: callback), //suppose I have button on MyApp3, pressed it, and indded count increased by 1
]
),
);
}
}
my_app2.dart
class MyApp2 extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp2> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return Container(
child: Text(count), how can I see the update count? from MyApp1?
);
}
}
my_app3.dart
class MyApp3 extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp3> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return Container();
}
}
use state management to do this. for example GetX. Type GetX in pub.dev and search.
Avoid setState. because it will increase the workload of your program.
For the answer to your question, see the link below.
Flutter Back button with return data
Just pass the count parameter to MyApp2 so when your callback function run then it again render MyApp2 and update the count on MyApp2 also
here is an example -
Code in MyApp1
MyApp2(count:count),
MyApp2 Code
class MyApp2 extends StatefulWidget {
const MyApp({Key? key,this.count}) : super(key: key);
final int count;
#override
State<MyApp2> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return Container(
child: Text($`enter code here count), how can I see the update count? from MyApp1?
);
}
}

How to use flutter negation operator in stateful widget?

In normal approach to use negation operator is like this
isValid = !isValid
but this approach is not working inside stateful widget constructor variable like
widget.isValid = !widget.isValid
How to make this second approach valid .
You are adding the negation to just widget, It needs to be added to widget.isValid . Hence wrap it within brackets to work.
Change !widget.isValid to (!widget.isValid)
Example:
class MyApp extends StatefulWidget {
MyApp({Key? key}) : super(key: key);
bool value = true;
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: SafeArea(
child: Scaffold(
body: Center(child: Text((!widget.value).toString())),
),
),
);
}
}
Output:

No Directionality widget found ; I want to use only Container and Text

I just run the basic flutter code.
I want to make stateful widget, only containing Text("hi")
so I write my code like below
import 'package:flutter/material.dart';
void main() {
runApp(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 Container(child: Text("hi");
}
}
but I got error
No Directionality widget found.
RichText widgets require a Directionality widget ancestor
I can fix my error to add textDirection attribute,
but I wonder when I use Text I didn't get that error even if I don't use that attribute.
I just want to use only Text, Container
i think its because you dont have MaterialApp
try it like this will work
void main() {
runApp(const MyApp1());
}
class MyApp1 extends StatelessWidget {
const MyApp1({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: 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 Container(child: Text("hi"));
}
}
Text needs a Directionality widget to provide information on whether the text is "left-to-right" or "right-to-left". Usually this is done (behind the scene) by MaterialApp widget. If you don't want to use that, you could provide one yourself, and specify the text direction.
Minimal code for a hello world:
import 'package:flutter/material.dart';
void main() {
runApp(
Directionality(
textDirection: TextDirection.ltr,
child: Text("Hello world."),
),
);
}

Event Listeners in flutter

Is there a way I can listen to a button click in flutter? I want to know if the button is clicked in another class that creates a object of that button.
What i want to do is let MyButtonRow know when MyButton is clicked, since it involves changing variables in MyButtonRow.
The functionality i am looking for is similar to .setEventListener in JavaScript
So here's the code
class MyButtonRow extends StatefulWidget {
const MyButtonRow({Key? key}) : super(key: key);
#override
_MyButtonRowState createState() => _MyButtonRowState();
}
class _MyButtonRowState extends State<MyButtonRow> {
#override
Widget build(BuildContext context) {
return Container(width: MediaQuery.of(context).size.width,
child: Row(children: <Widget>[MyButtonTile()],));
}
}
class MyButtonTile extends StatefulWidget {
const MyButtonTile({Key? key}) : super(key: key);
#override
_MyButtonTileState createState() => _MyButtonTileState();
}
class _MyButtonTileState extends State<MyButtonTile> {
#override
Widget build(BuildContext context) {
return TextButton(onPressed: (){
//notify MyButtonRow about the click
}, child: Text("hello"));
}
}
Firstly you declare onTap function on your child widget and then just pass the onTap function from where you define the MyButtonTile
class MyButtonRow extends StatefulWidget {
const MyButtonRow({Key? key}) : super(key: key);
#override
_MyButtonRowState createState() => _MyButtonRowState();
}
class _MyButtonRowState extends State<MyButtonRow> {
#override
Widget build(BuildContext context) {
return Container(width: MediaQuery.of(context).size.width,
child: Row(children: <Widget>[MyButtonTile(onTap: (){
print("Notify me");
})],));
}
}
class MyButtonTile extends StatelessWidget {
final Function onTap;
MyButtonTile({this.onTap});
#override
Widget build(BuildContext context) {
return TextButton(onPressed:onTap,//notify MyButtonRow about the click
child: Text("hello"));
}
}

Trigger animations on widget load flutter

So, I have a AnimatedPositioned widget in my widget tree, which contains a form. I want the AnimatedPositioned widget to slide up from bottom when user navigates to the screen. Now, there are many tutorials which show how to do this when user clicks a button using the setState method. But how do I trigger this automatically when this screen is loaded?
The "right" way to do that would be not to use an implicit animation widget like AnimatedPositioned and instead use an explicit animation. Where you start your AnimationController in the initState of a StatefulWidget.
But just technically you could set the "destination" values for your AnimatedPositioned widget in a Future so that the value changes on the next frame. You try remoing the Future to see that otherwise the widget renders at its end position.
This way is not recommended but possible:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double _dist = 0.0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: [
AnimatedPositioned(
child: Text('Hello Words'),
duration: Duration(seconds: 5),
left: _dist,
top: _dist,
),
]),
);
}
#override
initState() {
super.initState();
Future(() {
setState(() {
_dist = 250.0;
});
});
}
}