5

Normally, the below behavior is quick in nature. However, inside a GridView (or any ScrollView I assume (tried ListView, too)) the performance seems to be very poor. When I tap on the screen the opacity of the Container increases, but after a delay. Any idea what I am missing?

import "package:flutter/material.dart";
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
    Widget build(BuildContext context) {
      return MaterialApp(
        home: Scaffold(
          body: MyWidget()
        )
      );
    }
}
class MyWidgetState extends State<MyWidget> {
  double opacity = 0.2;
  @override
    Widget build(BuildContext context) {
      return GridView.builder(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3
        ),
        itemBuilder: (context, index) {
          return GestureDetector(
            onTap: () {
              setState(() {
                opacity = 0.2;                
              });
            },
            onTapDown: (details) {
              setState(() {
                opacity = 1.0;                
              });
            },
            child: Container(
              color: Colors.red.withAlpha((255 * opacity).toInt())
            )
          );
        },
      );
    }
}
class MyWidget extends StatefulWidget {
  @override
    State<StatefulWidget> createState() {
      return MyWidgetState();
    }
}
footurist
  • 1,509
  • 2
  • 16
  • 23

1 Answers1

20

Maybe Listener would be faster in your case

Listener(
      onPointerDown: (PointerDownEvent event) {
        setState(() {
          opacity = 1.0;
        });
      },
      onPointerUp: (PointerUpEvent event) {
        setState(() {
          opacity = 0.2;
        });
      },
      child: Container(
          color: Colors.red.withAlpha((255 * opacity).toInt())
      ),
    )
Andrii Turkovskyi
  • 27,554
  • 16
  • 95
  • 105
  • Tried it out, works like a charm. Thanks for the quick response! – footurist Oct 30 '18 at 11:38
  • 2
    You're welcome. If this is solution - would you mark answer? ))) – Andrii Turkovskyi Oct 30 '18 at 12:02
  • Actually, I still had the GridView replaced with a column in my testing. So now I tried your approach and while it shortens the delay, the performance is still a little worse than using a column. Any idea why that is? Will mark your answer, though. It does increase performance. – footurist Oct 30 '18 at 12:03
  • 1
    Did you try `GridView.count` instead of `GridView.builder`? Does it change delay? – Andrii Turkovskyi Oct 30 '18 at 12:30
  • It doesn't change much. But what I am referring to is really a response to a ridiculously short tap. Scenario: When I'm tapping once as fast as I can and have the opacity increase on pointerDown and decrease on pointerUp, then I see no change. However, if I have the opacity change after the first tap and stay like that, I see the change, which means the taps are being recognized. Does this maybe mean that the tap is too short for the calculated opacity change to be visible at all? – footurist Oct 30 '18 at 12:56
  • 1
    If you check logs - you see that all taps work. But wen you tap really quick - `onPointerUp` returns opacity to previous level, so you can't catch moment of changing - it becomes so quick. `GestureDecector` works too, `Listener` just little quicker. I think that building of `Column` takes less time than `GridView.builder` – Andrii Turkovskyi Oct 30 '18 at 13:24
  • Right, I think a solution would be to let pointerUp always trigger an actual animation. Thanks for the help. – footurist Oct 30 '18 at 13:59
  • That's amazing - works 10000000x times faster. I wonder why it works so much faster. On the other hand, it incepts scrolling event on the item as if it was tap as well... – Nils Tierecke May 10 '21 at 22:07