Search code examples
flutterdartflutter-provider

Unable to change the state of a custom widget with ProviderPackage


I have a icon that is on top of a map, Basically it is a location pin icon. I want to show or hide when a button is clicked. Initially I have set the visibility to hide but then when I click the button it wont show

Here is the code for the widget

import 'package:flutter/material.dart';

class MapPickerController {
  Function? mapMoving;
  Function? mapFinishedMoving;
}

class MapPicker extends StatefulWidget {
  final Widget child;
  final Widget iconWidget;
  final bool showDot;
  final MapPickerController mapPickerController;
  final bool showMapPicker;

  MapPicker(
      {required this.mapPickerController,
      required this.iconWidget,
      this.showDot = true,
      required this.child,
      required this.showMapPicker});

  @override
  _MapPickerState createState() => _MapPickerState();
}

class _MapPickerState extends State<MapPicker>
    with SingleTickerProviderStateMixin {
  late AnimationController animationController;

  @override
  void initState() {
    super.initState();
    animationController =
        AnimationController(vsync: this, duration: Duration(milliseconds: 300));
    widget.mapPickerController.mapMoving = mapMoving;
    widget.mapPickerController.mapFinishedMoving = mapFinishedMoving;
  }

  void mapMoving() {
    (widget.showMapPicker);
    if (!animationController.isCompleted || !animationController.isAnimating) {
      animationController.forward();
      print("Map Moving");
    }
  }

  void mapFinishedMoving() {
    animationController.reverse();
    print("Map Finished Moving");
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        widget.child,
        Container(),
        if (widget.showMapPicker)
          AnimatedBuilder(
              animation: animationController,
              builder: (context, snapshot) {
                return Align(
                  alignment: Alignment.center,
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Transform.translate(
                        offset: Offset(0, -10 * animationController.value),
                        child: widget.iconWidget,
                      ),
                      if (widget.showDot)
                        Container(
                          width: 5,
                          height: 5,
                          decoration: BoxDecoration(
                              color: Colors.black,
                              borderRadius: BorderRadius.circular(5)),
                        )
                    ],
                  ),
                );
              }),
      ],
    );
  }
}

This is the code fort provider

 bool showMap = false;

  void showMapPicker(bool showMapP) {
    showMap = showMapP;

    notifyListeners();
  }

This is the button with GestureDetector to hide and show the widget

 GestureDetector(
    onTap: () {
        Provider.of < AppData > (context, listen: false)
            .showMapPicker(true);
    },
    child: SvgPicture.asset(
        "assets/edit_loc.svg",
        height: 60,
    ),
),

Finally it is the widget itself that i want to show and hide,

child: MapPicker(
    iconWidget: SvgPicture.asset(
        //color: Colors.deepPurple,
        "assets/pin.svg",
        height: 40,
    ),
    //add map picker controller
    mapPickerController: mapPickerController,

    showMapPicker:
    Provider.of < AppData > (context, listen: false).showMap,


    child: (GoogleMap(
        mapKey: _mapKe)),

),

But nothing happens. The boolean showMapPicker is set to false initially, i believe it has changed to True after clicking on GestureDetector but the state doesn't change. Do i need to add anything else ? setState(){} or sth? Shouldn't provider package take care of that ?


Solution

  • child: Consumer < AppData > (
        builder: (context, value, child) => MapPicker(
            iconWidget: SvgPicture.asset(
                //color: Colors.deepPurple,
                "assets/pin.svg",
                height: 40,
            ),
            //add map picker controller
            mapPickerController: mapPickerController,
    
            showMapPicker: value.showMap,
    
            child: (GoogleMap(
                mapKey: _mapKey)),
        ),
    ),