Reputation: 1609
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();
}
}
Upvotes: 6
Views: 5006
Reputation: 13890
I have created a reusable widget named PressFade
you can use it immediately, it clones the iOS button behavior:
import 'package:flutter/material.dart';
class PressFade extends StatefulWidget {
final Widget child;
final VoidCallback onPressed;
const PressFade({
super.key,
required this.onPressed,
required this.child,
});
@override
State<PressFade> createState() => _PressFadeState();
}
class _PressFadeState extends State<PressFade> {
double opacity = 1.0;
Duration duration = Duration.zero;
void _onTapDown() {
setState(() {
duration = Duration.zero;
opacity = 0.5;
});
}
void _onTapUp() {
setState(() {
duration = const Duration(milliseconds: 150);
opacity = 1.0;
});
}
@override
Widget build(BuildContext context) {
return Listener(
onPointerDown: (_) => _onTapDown(),
onPointerUp: (_) => _onTapUp(),
onPointerCancel: (_) => _onTapUp(),
child: GestureDetector(
onTap: widget.onPressed,
child: AnimatedOpacity(
duration: duration,
opacity: opacity,
child: widget.child,
),
),
);
}
}
Upvotes: 0
Reputation: 29458
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())
),
)
Upvotes: 21