I have an app that looks like this
class MainScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => MainScreenState();
}
class MainScreenState extends State<MainScreen> {
#override
Widget build(BuildContext context) {
return new Container(
child: FlatButton(
onPressed:() {
// Want pop up to launch
},
),
)
}
}
class PopUp extends StatefulWidget {
PopUp({
this.postId
})
#override
State<StatefulWidget> createState() => PopUpState();
}
class PopUpState extends State<PopUp> {
// api logic
#override
Widget build(BuildContext context) {
return new Dialog()
}
}
Is it possible for me to overlay the PopUp widget on top of the MainScreen Widget without using showDialog ? Since i'm trying to make the PopUp stateful in that it processes and rerenders itself depending on the processed data ?
Related
I want to call method from another class which contains setState. I got some error in page 2like this
This happens when you call setState() on a State object for a widget that hasn't been inserted into the widget tree yet. It is not necessary to call setState() in the constructor, since the state is already assumed to be dirty when it is initially created.
I've read this answer, but I didnt get it on my case. Any Ideas? Thank you
class Page1 extends StatefulWidget {
#override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
#override
void initState(){
Page2().method();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
),
);
}
}
class Page2 extends StatefulWidget {
method() => createState().methodInPage2();
#override
_Page2State createState() => _Page2State();
}
class _Page2State extends State<Page2> {
Future<List<String>> methodInPage2() async{
//error here
setState(){
//setState here,
}
}
#override
Widget build(BuildContext context) => Container();
}
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"));
}
}
how to pass a variable as a parameter to a widget two, modify it there, and return the modified value to widget one.
I need to change the value of the variable when I click the "Change it" button, and that change is reflected in widget one.
class FirstWidget extends StatefulWidget {
#override
_FirstWidgetState createState() => _FirstWidgetState();
}
class FirstWidgetState extends State<FirstWidget> {
String c = 'start';
#override
Widget build(BuildContext context){
return Container(
child: SecondWidget(variable: c),
);
}
}
class SecondWidget extends StatefulWidget {
String variable;
SecondWidget({ this.variable });
#override
_SecondWidgetState createState() => _SecondWidgetState();
}
class SecondWidgetState extends State<SecondWidget> {
#override
Widget build(BuildContext context){
return Container(
child: RaisedButton(child:Text('Change it'), onPressed: () {widget.variable = 'end';}),
);
}
}
It is possible to implement it easily with a callback, meaning you pass a function to your second widget, and when the button is clicked you call the function, this way you can modify whatever you want in the first widget.
Like this:
class FirstWidget extends StatefulWidget {
#override
_FirstWidgetState createState() => _FirstWidgetState();
}
class FirstWidgetState extends State<FirstWidget> {
String c = 'start';
#override
Widget build(BuildContext context){
return Container(
child: SecondWidget(variable: c, onChange: (newVal) {
setState(() {c = newVal;});
}),
);
}
}
class SecondWidget extends StatefulWidget {
String variable;
final onChange;
SecondWidget({ this.variable, this.onChange });
#override
_SecondWidgetState createState() => _SecondWidgetState();
}
class SecondWidgetState extends State<SecondWidget> {
#override
Widget build(BuildContext context){
return Container(
child: RaisedButton(child:Text('Change it'), onPressed: () {widget.onChange('end');}),
);
}
}
I want to implement the GestureDetector method onTapin child class. Is there a way to do it in Flutter ?
ParentClass.dart
Class ParentClass extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GestureDetector {
onTap: methodA,
child: ChildClass(),
}
}
ChildClass.dart
Class ChildClass extends StatefulWidget {
methodA() // need to access methodA which is being passed to gesture detector
// How do I access methodA of parent class method here
// so whenever GestureDetector's onTap method is called, i want to handle that in ChildClass is there a way to do it ?
}
You can access the Child State methods using a unique key. Here is a minimal example:
Inside the ParentWidget, we define _childKey, a GlobalKey<_ChildWidgetState> that we then can use to access the State's method updateValue as follows:
_childKey.currentState.updateValue('Goodbye, Thierry!'),
Full source code
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
);
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: ParentWidget()),
);
}
}
class ParentWidget extends StatefulWidget {
#override
_ParentWidgetState createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
final _childKey = GlobalKey<_ChildWidgetState>();
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => _childKey.currentState.updateValue('Goodbye, Thierry!'),
child: ChildWidget(key: _childKey),
);
}
}
class ChildWidget extends StatefulWidget {
const ChildWidget({Key key}) : super(key: key);
#override
_ChildWidgetState createState() => _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
String value = 'Hello, Thierry!';
void updateValue(String newValue) {
setState(() => value = newValue);
}
#override
Widget build(BuildContext context) {
return Text(value);
}
}
In your ChildClass, return a GestureDetector. Set the child property to the rest of your widgets, and then set the onTap to call methodA. That should look something like this:
class ChildClass extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GestureDetector {
onTap: methodA,
child: SomeWidget(),
}
}
You are asking how to detect child class onTap and pass it to Parent right?
class YourChild extends StatelessWidget {
final Function parentCallback;
const YourChild({this.parentCallback});
#override
Widget build(BuildContext context) {
return GestureDetector(
// 1st option
onTap: () {
print("do something");
parentCallback();
},
)
}
}
Then for using It.
class YourParent extends StatelessWidget {
#override
Widget build(BuildContext context) {
return YourChild( parentCallback(){
//do your stuff}
)
}
}
Below is the minimal version of what i'm attempting to do with my app that maintains the issue. The slider still responds to being interacted with by showing it's animation, however it does not change the value or actually move. This only seems to occur because the Scaffold has been separated out to it's own widget.
I know that changing it to a stateless widget would fix it in this case, however the version in my app requires state changes.
I've tried adding UniqueKeys up and down the widget tree with no luck, though i'll admit I don't fully understand their use in this case.
Any advice, or a point in the right direction? Should I keep playing around with keys, or am I going about this in the wrong way?
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Scaffold Test',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage();
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double _value = 20.0;
#override
Widget build(BuildContext context) {
return MyScaffold(
child: Center(
child: Slider(
min: 0,
max: 100,
value: _value,
onChanged: (double value) {
setState(() {
_value = value;
});
},
),
),
);
}
}
class MyScaffold extends StatefulWidget {
final Widget child;
MyScaffold({this.child});
#override
State<StatefulWidget> createState() => new MyScaffoldState(child);
}
class MyScaffoldState extends State<MyScaffold> {
Widget child;
MyScaffoldState(this.child);
#override
Widget build(BuildContext context) {
return Scaffold(
body: child,
);
}
}
As commented by user #pskink, removing the state constructor fixes the issue.
class MyScaffold extends StatefulWidget {
final Widget child;
MyScaffold({this.child});
#override
State<StatefulWidget> createState() => MyScaffoldState();
}
class MyScaffoldState extends State<MyScaffold> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: widget.child,
);
}
}
In flutter, you should never have constructors for states.
if you need to initialize state properties, use initState.