Solución:
Para llamar a una función de un padre, puede usar el patrón de devolución de llamada. En este ejemplo, una función (onColorSelected
) se pasa al niño. El niño llama a la función cuando se presiona un botón:
import 'package:flutter/material.dart';
class Parent extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return ParentState();
}
}
class ParentState extends State<Parent> {
Color selectedColor = Colors.grey;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
color: selectedColor,
height: 200.0,
),
ColorPicker(
onColorSelect: (Color color) {
setState(() {
selectedColor = color;
});
},
)
],
);
}
}
class ColorPicker extends StatelessWidget {
const ColorPicker({this.onColorSelect});
final ColorCallback onColorSelect;
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
RaisedButton(
child: Text('red'),
color: Colors.red,
onPressed: () {
onColorSelect(Colors.red);
},
),
RaisedButton(
child: Text('green'),
color: Colors.green,
onPressed: () {
onColorSelect(Colors.green);
},
),
RaisedButton(
child: Text('blue'),
color: Colors.blue,
onPressed: () {
onColorSelect(Colors.blue);
},
)
],
);
}
}
typedef ColorCallback = void Function(Color color);
Los widgets internos de Flutter, como los botones o los campos de formulario, utilizan exactamente el mismo patrón. Si solo desea llamar a una función sin ningún argumento, puede usar el VoidCallback
escriba en lugar de definir su propio tipo de devolución de llamada.
Si desea notificar a un padre superior, puede repetir este patrón en cada nivel de jerarquía:
class ColorPickerWrapper extends StatelessWidget {
const ColorPickerWrapper({this.onColorSelect});
final ColorCallback onColorSelect;
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(20.0),
child: ColorPicker(onColorSelect: onColorSelect),
)
}
}
No se recomienda llamar a un método de widget secundario desde un widget principal en Flutter. En cambio, Flutter le anima a pasar el estado de un niño como parámetros de constructor. En lugar de llamar a un método del niño, simplemente llama setState
en el widget padre para actualizar sus hijos.
Un enfoque alternativo son los controller
clases en Flutter (ScrollController
, AnimationController
, …). Estos también se pasan a los niños como parámetros de constructor y contienen métodos para controlar el estado del niño sin llamar setState
en el padre. Ejemplo:
scrollController.animateTo(200.0, duration: Duration(seconds: 1), curve: Curves.easeInOut);
Luego, se requiere que los niños escuchen estos cambios para actualizar su estado interno. Por supuesto, también puede implementar su propia clase de controlador. Si es necesario, le recomiendo que mire el código fuente de Flutter para comprender cómo funciona.
Los futuros y las corrientes son otra alternativa para transmitir el estado y también podrían usarse para llamar a una función de un niño.
Pero realmente no lo recomiendo. Si necesita llamar a un método de un widget secundario, es muy parecido a que la arquitectura de su aplicación tiene fallas. ¡Intente mover el estado al antepasado común!
Puedes hacer eso usando llave de widget
myWidget.dart
class MyWidget extends StatefulWidget {
const MyWidget ({Key key}) : super(key: key);
@override
State<StatefulWidget> createState()=> MyState();
}
class MyState extends State<MyWidget >{
Widget build(BuildContext context){ return ....}
void printSample (){
print("Sample text");
}
}
ahora cuando use MyWidget declarar GlobalKey como clave global
GlobalKey<MyState> _myKey = GlobalKey();
y pásalo cuando crees el widget
MyWidget(
key : _myKey,
)
con esta clave puede llamar a cualquier método público dentro del estado
_myKey.currentState.printSample();
si desea llamar a printSample () func, puede usar:
class Myapp extends StatefulWidget{
...
MyappState myAppState=new MyappState();
@override
MyappState createState() => myAppState;
void printSample(){
myAppState.printSample();
}
}
class MyAppState extends State<MyApp>{
void printSample (){
print("Sample text");
}
}
...............
Myapp _myapp = new Myapp();
myapp.printSample();
...