Reputation: 427
I'm trying to reproduce the same contextual menu of Pinterest, in Flutter. So I have an overlay, which displays my contextual menu with a background, and I'd like to keep also the current element in front of the overlay.
Here are 2 videos: the Pinterest menu vs My Flutter menu.
To make an overlay I'm using flutter_portal package.
Here is the code of the blue card widget, with the overlay stuff:
import 'package:flutter/material.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:vector_math/vector_math.dart' show radians;
class CardWidget extends StatefulWidget {
@override
_CardWidgetState createState() => _CardWidgetState();
}
class _CardWidgetState extends State<CardWidget> with SingleTickerProviderStateMixin {
late AnimationController controller;
late Animation<double> degreeAnimation;
late Animation<double> opacityAnimation;
bool isMenuOpen = false;
double menuPosX = 0;
double menuPosY = 0;
@override
void initState() {
controller = AnimationController(vsync: this, duration: Duration(milliseconds: 200))
..addListener(() {
setState(() {});
})
..addStatusListener((status) {
if (status == AnimationStatus.forward) {
isMenuOpen = true;
} else if (status == AnimationStatus.dismissed) {
isMenuOpen = false;
}
});
degreeAnimation =
Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(parent: controller, curve: Curves.easeOutBack));
opacityAnimation =
Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(parent: controller, curve: Curves.easeOutExpo));
super.initState();
}
@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 63.5 / 88.9,
child: PortalEntry(
visible: isMenuOpen,
portal: Container(
color: Colors.black.withOpacity(opacityAnimation.value / 2),
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
controller.reverse();
},
),
),
child: PortalEntry(
visible: isMenuOpen,
child: GestureDetector(
onTapDown: (details) {
if (controller.isCompleted) {
controller.reverse();
} else {
menuPosX = details.globalPosition.dx;
menuPosY = details.globalPosition.dy;
controller.forward();
}
},
// Blue card content
child: Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(
Radius.circular(8),
),
),
child: Center(
child: Text(
'Card Widget',
style: TextStyle(color: Colors.white),
),
),
),
),
// Current contextual Menu
portal: ContextualMenuWidget(),
),
),
);
}
}
Thank you for your help!
Upvotes: 0
Views: 481
Reputation: 427
Thanks to orotype, instead of making a black overlay, I finally wrapped my cards with an AnimatedOpacity, and passed a callback when the contextual menu is opened/closed to trig the animation.
I don't know if this is the best solution, but I like the result.
Upvotes: 0
Reputation: 459
Maybe instead of an trying to add an overlay, you can change the color of all the other cards to the same as the background. By that you would achieve the same effect.
You can check if isMenuOpen
is true and save the index of the card on which it was clicked, and in your grid builder function you can change the color of all the cards to the same as the background.
Upvotes: 1