Home > OS >  how to call child widget function from parent widget
how to call child widget function from parent widget

Time:09-24

All data is contains in Parent widget and showing in child widget

I want to call function in child widget when parent state change

child widget function which is stateFull widget

  void changeSelectedJodi(i) {
    _jodiScrollController.animateTo(50.0 * i,
        duration: Duration(seconds: 2), curve: Curves.fastOutSlowIn);
  }

Parent widget

   child: JodiDataWidget(
      this._jodies, <= data is here
      this.selectedJodi, <= call function changeSelectedJodi in child widget when change
   ),

how to achieve this method

CodePudding user response:

You still don't want to access your child from your parent. Flutter control flow goes only one way and there are good reasons for that, which your should respect.

The question is, then, how can my child know that my parent has changed? For this, you have to update the child from the parent (as always) then use didUdpdateWidget in the child to catch a widget change and react to it.

Here is a small example:

import 'dart:math';

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(home: ParentWidget()));
}

class ParentWidget extends StatefulWidget {
  @override
  State<ParentWidget> createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  /// The item of the list to display
  ///
  /// This will be changed randomly by clicking the button
  int selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Column(
        mainAxisSize: MainAxisSize.max,
        children: [
          Expanded(
            child: Center(
              child: ChildWidget(
                selectedIndex: selectedIndex,
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(15.0),
            child: ElevatedButton(
              onPressed: () => setState(() => selectedIndex = Random().nextInt(100)),
              child: Center(
                child: Text('Press my to move the list'),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class ChildWidget extends StatefulWidget {
  /// The item of the list to display
  ///
  /// Changed randomly by the parent
  final int selectedIndex;

  const ChildWidget({
    Key? key,
    required this.selectedIndex,
  }) : super(key: key);

  @override
  State<ChildWidget> createState() => _ChildWidgetState();
}

class _ChildWidgetState extends State<ChildWidget> {
  /// The colors of the items in the list
  final _itemsColors = List.generate(
    100,
        (index) => getRandomColor(),
  );

  static Color getRandomColor() =>
      Color((Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0);

  final _controller = PageController();
  
  void functionOfChildWidget() {
    _controller.animateToPage(
      widget.selectedIndex,
      duration: Duration(milliseconds: 200),
      curve: Curves.easeIn,
    );
  }

  /// Here is the important part: When data is set from the parent,
  /// move this widget
  @override
  void didUpdateWidget(covariant ChildWidget oldWidget) {
    // If you want to react only to changes you could check
    // oldWidget.selectedIndex != widget.selectedIndex
    functionOfChildWidget();
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 200,
      child: PageView.builder(
        controller: _controller,
        padEnds: false,
        itemBuilder: (context, index) {
          return Container(
            margin: EdgeInsets.all(50),
            color: _itemsColors[index],
            width: 100,
          );
        },
        itemCount: _itemsColors.length,
      ),
    );
  }
}
  • Related