Home > Software engineering >  How to call a method of a child stateful widget? FLUTTER
How to call a method of a child stateful widget? FLUTTER

Time:07-14

How do I call method of child widget?

class Parent extends StatefulWidget {
  const Parent({Key? key}) : super(key: key);

  @override
  State<Parent> createState() => _ParentState();
}

class _ParentState extends State<Parent> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        FloatingActionButton(onPressed: (){
          //call child function named funcToCallFromParent
        }),
        Child(),
      ],
    );
  }
}
class Child extends StatefulWidget {
  const Child({Key? key}) : super(key: key);

  @override
  State<Child> createState() => _ChildState();
}

class _ChildState extends State<Child> {

  void funcToCallFromParent(){
    print('child func called from parent');
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

CodePudding user response:

You can use a GlobalKey for that.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  const MyHomePage({
    Key? key,
    required this.title,
  }) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _key = GlobalKey<_ChildState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(child: Child(key: _key)),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // The current state can be null,
          // i.e. there is no widget in the tree because it has been unmounted.
          _key.currentState?.funcToCallFromParent();
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

class Child extends StatefulWidget {
  const Child({Key? key}) : super(key: key);

  @override
  State<Child> createState() => _ChildState();
}

class _ChildState extends State<Child> {
  void funcToCallFromParent() {
    print('child func called from parent');
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

See https://api.flutter.dev/flutter/widgets/GlobalKey-class.html

CodePudding user response:

You can use ChangeNotifier to notify the child (or children if you have more than one child that need to be notified) when the parent's button is pressed:

class FloatingActionButtonNotifier extends ChangeNotifier {
  void onFloatingActionButtonPressed() => notifyListeners();
}

class Parent extends StatefulWidget {
  const Parent({super.key});

  @override
  State<Parent> createState() => _ParentState();
}

class _ParentState extends State<Parent> {
  final FloatingActionButtonNotifier fabNotifier = FloatingActionButtonNotifier();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        FloatingActionButton(onPressed: fabNotifier.onFloatingActionButtonPressed),
        Child(fabNotifier: fabNotifier),
      ],
    );
  }
}

class Child extends StatefulWidget {
  const Child({
    super.key,
    required this.fabNotifier,
  });

  final FloatingActionButtonNotifier fabNotifier;

  @override
  State<Child> createState() => _ChildState();
}

class _ChildState extends State<Child> {
  void funcToCallFromParent() {
    print('child func called from parent');
  }

  @override
  void initState() {
    super.initState();
    widget.fabNotifier.addListener(funcToCallFromParent);
  }

  @override
  void dispose() {
    super.dispose();
    widget.fabNotifier.removeListener(funcToCallFromParent);
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

CodePudding user response:

You can use GlobalKey for Child, and get the state of Child(StatefulWidget). Then call the child's function in the parent widget.

GlobalKey<MyHomePageState> homePageStateKey = GlobalKey<MyHomePageState>();

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {

    homePageStateKey.currentState?._incrementCounterAfterOneSecond();

    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(key: homePageStateKey, title: 'Flutter Demo Home Page'),
    );
  }
}
  • Related