Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass method as parameter to a widget

Tags:

flutter

dart

I have a custom button widget:

class Button extends StatelessWidget {   final String text;    Button(this.text);    @override   Widget build(BuildContext context) {     return Container(       height: 50,       child: SizedBox(         width: double.infinity,         child: RaisedButton(           onPressed: () => {}, // Use the function from parent Widget           child: Padding(               padding: EdgeInsets.symmetric(vertical: 13),               child: Text(                 text,                 style: TextStyle(fontWeight: FontWeight.bold),               )),           color: COLOR_BLUE,           textColor: Colors.white,           shape:               RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)),         ),       ),     );   } } 

Then in parent Widget I want to pass a onPressed method to this button widget:

... myMethod () => {    // do some stuff } ... Padding(     padding: EdgeInsets.only(bottom: 10),     child: Button("Log in", myMethod), ), ... 

How can I tell a button widget to use the myMethod for onPress?

like image 310
Runtime Terror Avatar asked Feb 02 '19 12:02

Runtime Terror


People also ask

How do you pass parameters to widgets in Flutter?

Steps to Pass Data to Stateful Widget in Flutter To pass data to stateful widget, first of all, create two pages. Now from the first page open the second page and pass the data. Inside the second page, access the variable using the widget. For example widget.

How do you call a function inside a widget in Flutter?

Calling a method of child widget from a parent widget is discouraged in Flutter. Instead, Flutter encourages you to pass down the state of a child as constructor parameters. Hence instead of calling a method of the child, you just call setState in the parent widget to update its children.

Why do we pass functions to widgets?

Functions are first-class objects in Dart and can be passed as parameters to other functions. We pass a function to a widget essentially saying, invoke this function when something happens. Callbacks using interfaces like Android have too much boilerplate code for a simple callback.


2 Answers

Use the VoidCallback type, like this. Check the line comments on the code as well for more information:

class Button extends StatelessWidget {   final String text;   final VoidCallback callback; // Notice the variable type    Button(this.text, this.callback);    @override   Widget build(BuildContext context) {     return Container(       height: 50,       child: SizedBox(         width: double.infinity,         child: RaisedButton(           onPressed: callback, // Simply put the function name here, DON'T use ()           child: Padding(               padding: EdgeInsets.symmetric(vertical: 13),               child: Text(                 text,                 style: TextStyle(fontWeight: FontWeight.bold),               )),           color: COLOR_BLUE,           textColor: Colors.white,           shape:               RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)),         ),       ),     );   } } 
like image 99
George Avatar answered Oct 03 '22 20:10

George


There are a few predefined types that already exist.

VoidCallback

If you want to create a parameter something like this:

onPressed: () { }, 

Then you can define it in your class like so:

class MyWidget extends StatelessWidget {    MyWidget({Key key, this.onPressed}) : super(key: key);    final VoidCallback onPressed;    // ... } 

Notes

The typedef is defined in the source code like this:

typedef VoidCallback = void Function(); 

The asynchronous version is AsyncCallback.

typedef AsyncCallback = Future<void> Function(); 

ValueSetter

If you want to create a parameter something like this:

onPressed: (value) { }, 

Then you can define it in your class like so:

class MyWidget extends StatelessWidget {    MyWidget({Key key, this.onPressed}) : super(key: key);    final ValueSetter<String> onPressed;    // ... } 

Notes

The typedef is defined in the source code like this:

typedef ValueSetter<T> = void Function(T value); 

If you want to specify that the function only gets called when there is a change then use ValueChanged instead.

typedef ValueChanged<T> = void Function(T value); 

The asynchronous version is AsyncValueSetter.

typedef AsyncValueSetter<T> = Future<void> Function(T value); 

ValueGetter

If you want to create a parameter something like this:

onPressed: () => value, 

Then you can define it in your class like so:

class MyWidget extends StatelessWidget {    MyWidget({Key key, this.onPressed}) : super(key: key);    final ValueGetter<String> onPressed;    // ... } 

Notes

The typedef is defined in the source code like this:

typedef ValueGetter<T> = T Function(); 

The asynchronous version is AsyncValueGetter.

typedef AsyncValueGetter<T> = Future<T> Function(); 

Define your own type

As you can see from all of the examples above, everything is just a typedef for a Function. So it is easy enough to make your own.

Say you want to do something like this:

onEvent: (context, child) => value, 

Then you would make the typedef like this:

typedef MyEventCallback = int Function(BuildContext context, Widget widget); 

And use it like this:

class MyWidget extends StatelessWidget {    MyWidget({Key key, this.onEvent}) : super(key: key);    final MyEventCallback onEvent;    // ... } 

See the documentation for more.

like image 37
Suragch Avatar answered Oct 03 '22 20:10

Suragch