SimformSolutionsPvtLtd / flutter_showcaseview

Flutter plugin that allows you to showcase your features on flutter application. πŸ‘ŒπŸ”πŸŽ‰
https://pub.dev/packages/showcaseview
MIT License
1.48k stars 433 forks source link

Bug when changing app theme #437

Closed mehrdad1990 closed 2 months ago

mehrdad1990 commented 4 months ago

Hi and thanks for the beautiful plugin. I have this issue after upgrading to Flutter 3.22 that when I change my app theme to dark or light mode my widgets that have Showcase.withWidget as their parent will throw errors.

Errors: 'package:flutter/src/rendering/object.dart': Failed assertion: line 3347 pos 14: 'renderer.parent != null': is not true.

0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:51:61)

  #1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:40:5)
  #2      RenderObject.getTransformTo (package:flutter/src/rendering/object.dart:3347:14)
  #3      RenderBox.localToGlobal (package:flutter/src/rendering/box.dart:2886:39)
  #4      AnchoredOverlay.build.<anonymous closure>.<anonymous closure> (package:showcaseview/src/layout_overlays.dart:72:19)

layout_overlays.dart line 72 shows error as well as get_position.dart line 53 I went through your code and debugged it but didn't find any solutions. I don't have this issue with the previous Flutter SDK. I don't have this issue even in Flutter 3.22 when changing theme if I remove your plugin's widgets as parents. changing theme causes everything to rebuild but I don't know how it relates with your widgets that throw errors!!! What could be the problem and how to fix it?

mehrdad1990 commented 3 months ago

layout_overlays.dart:72:19 this is the real cause. I guess it is because of rootRenderObject

rashi-simform commented 2 months ago

Hello @mehrdad1990, I have tried reproducing your issue in the example app provided in this package's code with flutter 3.22 and 3.16 and have failed to face such as issue. Can you please share a minimal reproducible code or try your approach in the example app to see if you still face the issue?

mehrdad1990 commented 2 months ago

I guess I have a similar problem as this issue when I revert to showcaseview: 2.0.3 I don't have this issue that's why I guess it is because of rootRenderObject.

rashi-simform commented 2 months ago

@mehrdad1990, the issue you have mentioned is talking about findRenderObject and it is present in 2.0.3 as well so it's not the cause of your problem. Also rootRenderObject is new but it is nullable and so it wouldn't cause any issue. Try your approach in the example app and verify if you still face the issue. Closing the issue, feel free to reopen if you face issue in the example app.

mehrdad1990 commented 2 months ago

@rashi-simform Take a look at the codes below this is from showcaseview 3.0.0:

@override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        return OverlayBuilder(
          showOverlay: showOverlay,
          overlayBuilder: (overlayContext) {
            // To calculate the "anchor" point we grab the render box of
            // our parent Container and then we find the center of that box.
            final box = context.findRenderObject() as RenderBox;

            final topLeft = box.size.topLeft(
              box.localToGlobal(
                const Offset(0.0, 0.0),
                ancestor: rootRenderObject,
              ),
            );
            final bottomRight = box.size.bottomRight(
              box.localToGlobal(
                const Offset(0.0, 0.0),
                ancestor: rootRenderObject,
              ),
            );
            Rect anchorBounds;
            anchorBounds = (topLeft.dx.isNaN ||
                    topLeft.dy.isNaN ||
                    bottomRight.dx.isNaN ||
                    bottomRight.dy.isNaN)
                ? const Rect.fromLTRB(0.0, 0.0, 0.0, 0.0)
                : Rect.fromLTRB(
                    topLeft.dx,
                    topLeft.dy,
                    bottomRight.dx,
                    bottomRight.dy,
                  );
            final anchorCenter = box.size.center(topLeft);
            return overlayBuilder!(overlayContext, anchorBounds, anchorCenter);
          },
          child: child,
        );
      },
    );
  }

and this is the code from showcaseview 2.0.3 which I don't have problem with:

    @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        return OverlayBuilder(
          showOverlay: showOverlay,
          overlayBuilder: (overlayContext) {
            // To calculate the "anchor" point we grab the render box of
            // our parent Container and then we find the center of that box.
            final box = context.findRenderObject() as RenderBox;
            final topLeft =
                box.size.topLeft(box.localToGlobal(const Offset(0.0, 0.0)));
            final bottomRight =
                box.size.bottomRight(box.localToGlobal(const Offset(0.0, 0.0)));
            Rect anchorBounds;
            anchorBounds = (topLeft.dx.isNaN ||
                    topLeft.dy.isNaN ||
                    bottomRight.dx.isNaN ||
                    bottomRight.dy.isNaN)
                ? const Rect.fromLTRB(0.0, 0.0, 0.0, 0.0)
                : Rect.fromLTRB(
                    topLeft.dx,
                    topLeft.dy,
                    bottomRight.dx,
                    bottomRight.dy,
                  );
            final anchorCenter = box.size.center(topLeft);
            return overlayBuilder!(overlayContext, anchorBounds, anchorCenter);
          },
          child: child,
        );
      },
    );
  }

the only logical issue that seems to cause the problem is with ancestor: rootRenderObject,. I know it is nullable but it is getting value in :

final rootWidget = context.findAncestorStateOfType<State<WidgetsApp>>();
      rootRenderObject = rootWidget?.context.findRenderObject() as RenderBox?;
      rootWidgetSize = rootWidget == null
          ? MediaQuery.of(context).size
          : rootRenderObject?.size;

so in my case this rootRenderObject changes when I'm changing app theme because I have to rebuild MaterialApp as you know it should happen for changing theme. Therefore, this rootRenderObject causes issue because of this rebuild on the MaterialApp parent. That's why I said this rootRenderObject is causing the problem here because it doesn't exist in 2.0.3 and it it working for me. I think there should be a way in 3.0.0 to sort it out. Any ideas?