talamaska / onboarding_overlay

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add getter isVisible and currentStep to OnboardingState

guenth39 opened this issue · comments

commented

For me, it would be very helpful to know if an overlay is currently displayed. Maybe a getter currentStep would also be interesting, then you don't have to use the onChange listener and save the index separate.
Or is there already such a possibility and I have not found it yet?

Best Regards

No there isn't such possibility. I'll see what I can do.

@guenth39 check latest changes in https://github.com/talamaska/onboarding_overlay/tree/feature/provide-builder
added those things you want to a special ChangeNotifier aka controller
there is a n example of how to access it.

commented

Works like expected ✅ Thanks a lot!

ok will release a prelease tomorrow with one more feature that I have in the stack - a pulsing animation around the hole of the focused widget. So that more people can eventually test from pub.dev

Published a v3.0.0-pre.2. Give it a shot again when you have time. This release includes all your requested features, plus some breaking changes and other features. Refer to the changelog for a precise list. Will work on the readme to reflect all the new stuff and next week will publish a stable version if no issue comes up.

commented

I just tested it and I noticed the following things:

  1. You write nextStep and close work only if manualControl == true, but for me they always work. But I think that is good and important, especially that close always works! manualControl == false disables from my point of view only the simple "next Step on Tap". Correct me if I am wrong.

  2. If I don't give a TextStyle to a text in the builder, no default Style is applied. I would expect that in this case the theme of my app is used and the text looks exactly like if I create a simple Text('MyText') widget outside of onboarding.

  3. Maybe a new feature rather than a bug: is there a way to jump to the next step when tapping on the focused widget? The event is then passed to the child or not based on the overlayBehavior but I want to go to the next step at that moment. I could imagine to set this directly as a bool, but more flexible would be an onTapCallback(TapArea tapArea, VoidCallback nextStep, VoidCallback close), then everyone could decide how to handle the tap. Of course this only makes sense in combination with manualControl == true. Do you understand what I mean? Because it would be practical if you want to declare e.g. a FAB that opens an Alert, that you actually open this Alert when the user clicks on the FAB and jumps to the next onBoardingStep. This would be a very useful addition from my point of view.

  4. If I set showPulseAnimation = true at one step it will be shown at all steps, even if showPulseAnimation is null or false at the next step.

You write nextStep and close work only if manualControl == true

Will fix that. There should not be duplicating/conflicting gestures.

If I don't give a TextStyle to a text in the builder, no default Style is applied

Yep, you have to apply the style that is provided in the builder. You are on your own here. I can't apply any styles to the widgets that are passed in the builder. Probably i should mention this in the docs. No styles are applied, because those widgets are outside of a scaffold they are in a overlay. So in order to fix your styles you need to wrap everything in stepBuilder with a Scaffold or Material widget.

 OnboardingStep(
              focusNode: focusNodes[0],
              titleText: 'Tap anywhere to continue ',
              titleTextColor: Colors.black,
              bodyText: 'Tap anywhere to continue Tap anywhere to continue',
              labelBoxPadding: const EdgeInsets.all(16.0),
              labelBoxDecoration: BoxDecoration(
                shape: BoxShape.rectangle,
                borderRadius: const BorderRadius.all(Radius.circular(8.0)),
                color: const Color(0xFF00E1FF),
                border: Border.all(
                  color: const Color(0xFF1E05FB),
                  width: 1.0,
                  style: BorderStyle.solid,
                ),
              ),
              arrowPosition: ArrowPosition.autoVertical,
              hasArrow: true,
              hasLabelBox: true,
              fullscreen: true,
              manualControl: true,
              stepBuilder: (
                BuildContext context,
                OnboardingStepRenderInfo renderInfo,
              ) {
                return Material(
                  child: SingleChildScrollView(
                    child: Column(
                      children: [
                        Text(
                          renderInfo.titleText,
                          // style: renderInfo.titleStyle,
                        ),
                        Row(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Image.asset(
                              'assets/demo.gif',
                              width: 50,
                            ),
                            const SizedBox(
                              width: 10,
                            ),
                            Flexible(
                              child: AutoSizeText(
                                renderInfo.bodyText,
                                style: renderInfo.bodyStyle,
                              ),
                            ),
                          ],
                        ),
                        Row(
                          children: [
                            TextButton(
                              onPressed: renderInfo.nextStep,
                              child: Text('Next'),
                            ),
                            TextButton(
                              onPressed: renderInfo.close,
                              child: Text('close'),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                );
              },
            ),

Maybe a new feature rather than a bug: is there a way to jump to the next step when tapping on the focused widget?

I understand, but i think this complicates too much the behavior. You could use HitTestBehavior.translucent. Then tap are going to be triggered on the widget and on the overlay. and you can go to nextStep and open your Alert.

If I set showPulseAnimation = true at one step it will be shown at all steps,

Will take a look, this is a bug. the flag should be only for one a specific step

@guenth39 Maybe i should handle the close callback separately from manualControl.
Will see what i can do.

The problem I have is that. The onboarding cannot know if there is a close button defined, and if set magically ignore the global gesture detector when clicked on it. Maybe with a special key? Hm interesting.

@guenth39 Here is what i have tested. I could add an additional property to the OnbardingStep - closeKey. it should be a GlobalKey. If it is set and it is attached to a widget(a button) In the gesture detector i can check if the tap coordinates are within this RenderBox. And if they are, ignore the onTap. This would be independent of the manualControl bool. So manualControl would just make it possible to make you own call to nextStep. and the closeKey would control if you have your own close button. So you can have one but not another. You could have just close, but still be possible to go to next step by clicking anywhere else on the overlay. What to test that out in a separate branch?

commented

Hey @talamaska I just tried it and it looks all good. But one thing I still do not understand.

Maybe a new feature rather than a bug: is there a way to jump to the next step when tapping on the focused widget?

I understand, but i think this complicates too much the behavior. You could use HitTestBehavior.translucent. Then tap are going to be triggered on the widget and on the overlay. and you can go to nextStep and open your Alert.

But if I do it this way, I would have to open the alert manually, the tap event would not arrive at the widget. Right? This may work in this simple example but in most cases you need specific information from the widget and so it doesn't work.
Can you explain again why it would be too complicated to add an additional OnTapCallback to the OnboardingStep? Then the original event would simply be passed to the underlying widget and I could manually call the next step. If I'm not mistaken this would only affect Stepper:486-490 or am I wrong? For clarification here an example:

OnboardingStep(
  focusNode: focusNodes[0],
  title: 'Tap to the highlighted widget to continue ',
  titleTextColor: Colors.black,
  bodyText:
      'If you tap to the highlighted area the widgets nativ on tap action will be triggered and the next step is called',
  labelBoxPadding: const EdgeInsets.all(16.0),
  fullscreen: true,
  manualControl: true,
  onTapCallback: (TapArea tapArea, VoidCallback next, VoidCallback close){
    if(tapArea == TapArea.hole){
      next();
    }
    // If the tapArea == TapArea.overlay i can do other things or nothing
  }
),

But if I do it this way, I would have to open the alert manually, the tap event would not arrive at the widget. Right?
I'm probably misunderstanding. Let me ask more question to understand better.
Can this Alert be opened without the onboarding? Is it openable from a button with onTap or onPress?
If yes, what do you mean by "open the alert manually"?
Why do you need to call next manually?

As said above. If you set overlayBehavior to HitTestBehavior.translucent, the gesture will be triggered on both your button and my overlay, thus opening your Alert and my next method.
Isn't that what you want to achieve?

P.S. I think i have found an issue with the translucent. Like it doesn't work at all.

If I add onTapCallback I need to add logic to ignore the default behavior and this won't be straightforward.
Also manualControl was renamed to manualNextControl, and in your demo it shouldn't be true, as I'd have to check if the onTapCallback is not null and do my stuff. And leave manualNextControl only for stepBuilder.

I need some time to think about it. i didn't expect this HitTestBehavior.translucent to not work :(

@guenth39 I made some experiments. I had to make quite a lot of changes to make this work. And even them it's like on one wrong move of breaking. Especially if you have showing and hiding elements - you suggested with Alert I tried with a drawer. same logic. I can open the drawer trough the overlay, but the closing is an issue. When next is called it tries to animate the overlay and the hole, but it can't find the hole cause the element is not in the tree and I get an exception.
From the beginning I wanted to avoid such stuff, that's why I didn't implement it initially. I'm not sure what to do. Will look a bit more, and I can't figure it out, gonna move on.

@guenth39 pushed, made some fixes. and implemented onTapCallback. check readme and changelog
still on that branch
https://github.com/talamaska/onboarding_overlay/tree/feature/3.0.0-pre.5

commented

I have just tested the latest version and really like the changes! From my perspective, it is without manualNextControl and without closeKey again much cleaner.
The onTapCallback also works for me, but unfortunately it is not called when overlayBehavior == OverlayBehavior.deferToChild and I tap TapArea.hole. Is this just not possible or is this a bug?

Yeah I think it should be always deferToOverlay if you want to use the onTapCallback, else the click on the overlay is ignored and the hitTest is not checked and onTapCallback is not used. Will see if I can set an assert and add some docs.

commented

But then the original goal that the tap reaches the widget in the hole and I additionally do something in the onTapCallback can not be achieved? I think the onTapCallback should always be called, regardless of whether the event is forwarded afterwards or not. Whether you use it or not is another thing. But if HitTestBehavior.translucent doesn't work, of course it doesn't work. Unfortunately for me this is the only UseCase of the onTapCallback I need :(

Theoretically it should be enough to replace Stepper:443 with HitTestBehavior.translucent or? But that was the thing that doesn't work or?

commented

Maybe this helps: flutter/flutter#18450

For more clarity of how translucent works read here.
flutter/flutter#92103
flutter/flutter#74733
flutter/flutter#28170
if the HitTestBehavior is deferToChild, then my GestureDetector is not called at all, when you click on the widget in the hole. So if my GestureDetector is called, then I can't call magically the onTapCallback.
That's how it is.

Maybe there is something I can do. Like it depends if I use GestureDetector or Listener.

commented

Okay, I got it! But it must be somehow possible that the underlying widget can receive the event... Unbelievable that this is so complicated! But I also think that using the Listener is a hot track. I'm playing around with it a bit right now as well.

Yes, testing, I think I made it, just verifying if everything is as expected. Thanks for your patience and QA for me :)

commented

I have to thank for your effort!
For me it works with the Listener. I just replaced the GestureDetector with a Listener and then it works if i use HitTestBehavior.translucent

I think that if onTapCallback is set, then the internal call to next step should be bypassed. Do you agree?

commented

Love it! I found no 🐛 and I am very happy with the result ✅
It was a pleasure working with you. Let's see how long it takes before I miss the next thing 😅

commented

Ups, rejoiced too soon... one minor suggestion: I think we could remove step.stepBuilder == null from the _nextStep() check? Or is that still necessary? I think onTapCallback is enough.

EDIT: Forget it, I don't think it makes sense to removing it

Right, cause if you have stepBuilder and you have the exposed callbacks it's up to you to call them, cause in other case nexsStep will be called and your buttons will not work :)