gonuit / flutter-custom-refresh-indicator

Widget that makes it easy to implement a custom pull to refresh gesture.
MIT License
494 stars 63 forks source link

When I just tap on the screen, the refresh indicator appears unexpectedly #62

Open MrTadeu opened 2 months ago

MrTadeu commented 2 months ago

Hello,

I've been working with the CheckMarkIndicator example from your repository (there are really awesome exemples 🤩, btw), and I have encountered an issue.

For context, I set the edgeOffset like this:

edgeOffset: AppBar().preferredSize.height + MediaQuery.of(context).padding.top + 24;

To position the indicator where I want it. However, whenever I simply tap on the screen, the refresh indicator appears briefly.

Here are the logs from debugging: I/flutter ( 6309): Controller value: 0.0 I/flutter ( 6309): Controller state: IndicatorState.dragging

I initially tried to adjust the trigger conditions and triggerMode, but those changes did not resolve the issue. As a workaround, I updated the notificationPredicate to:

notificationPredicate: (notification) {
return (notification is ScrollUpdateNotification ||
          notification is ScrollStartNotification ||
          notification is ScrollEndNotification) &&
         notification.metrics.pixels.abs() > 0.0;
},

This change provides the correct boolean value during debugging (alternating between true and false as expected), but the indicator stops showing up and it doesn't works anymore - perhaps it's only constructed once and not rebuilt properly. I even tried to transforming it into something likebool statement = (notification is ...) and then wrapped in a setState.

Here’s a visual of the problem: Tap-problem

Is there a known fix or any recommendations for properly handling the refresh indicator without it appearing unexpectedly on tap?

Thank you a lot in advance!

MrTadeu commented 2 months ago

Hello,

I’ve been working further on the refresh indicator issue and have managed to come up with a solution. Although I was able to make it so that the refresh indicator only appears when you drag it down, the implementation doesn’t seem very clean. I’m also unsure if this was the intended approach or if there might be a more straightforward method.

Here's what I’ve come up with:

// More code ...
durations: const RefreshIndicatorDurations(
        completeDuration: Duration(seconds: 3),
      ),
useMaterialContainer: false, // This is required cuz the Material widget pops up unexpectedly, which causes the problem to persist.
indicatorBuilder: (
        BuildContext context,
        IndicatorController controller,
      ) {
//  Other things ....
if ((controller.value > 0 && controller.isDragging) || controller.isComplete || controller.isFinalizing || controller.isLoading || controller.isArmed) {
        return AnimatedContainer(
            decoration: BoxDecoration( // Manually added since I don't have the shadows from MaterialContainer
              color: style.background,
              shape: BoxShape.circle,
              boxShadow: [
                BoxShadow(
                  color: style.background.withOpacity(0.5),
                  blurRadius: 8,
                  spreadRadius: 2,
                ),
              ],
            ),
            //widget logic...
        ),
  }
 return const SizedBox();
}

The Debugging output for the condition (IF: ${controller.value > 0 && controller.isDragging} || ${controller.isComplete} || ${controller.isFinalizing} || ${controller.isLoading} || ${controller.isArmed} || ${controller.isSettling})

Shows the following results: image

Thus, this means the state is true in every situation where it should be.

gonuit commented 2 months ago

Hi @MrTadeu 👋 I will check this in upcoming days 🕵️‍♂️

gonuit commented 2 months ago

Can you share the full widget tree code? It is expected that the pointer will appear as soon as you start the p2r gesture from the edge of the scrollable widget. However, if the pointer is visible even though you haven't dragged it, it could mean that you have set the wrong offset or that you have wrapped more or less widgets than you want.