Skip to content

Instantly share code, notes, and snippets.

@ferrarafer
Created August 8, 2024 01:51
Show Gist options
  • Save ferrarafer/cbc986771845fa494fe8b82c6f0381a7 to your computer and use it in GitHub Desktop.
Save ferrarafer/cbc986771845fa494fe8b82c6f0381a7 to your computer and use it in GitHub Desktop.
Conflict between MouseRegion and PopupMenuButton widgets
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _isMouseHover = false;
bool _anyTaskRunning = false;
bool _isSignOutBusy = false;
void _setMouseHovering(bool value) {
setState(() {
_isMouseHover = value;
});
}
void _runTask1() async {
print('running task 1');
setState(() {
_anyTaskRunning = true;
});
await Future.delayed(const Duration(seconds: 3));
setState(() {
_anyTaskRunning = false;
});
}
void _runTask2() async {
print('running task 2');
setState(() {
_anyTaskRunning = true;
});
await Future.delayed(const Duration(seconds: 3));
setState(() {
_anyTaskRunning = false;
});
}
void _onItemSelected(String item) async {
print('onItemSelected -> item:$item');
setState(() {
_isSignOutBusy = item == 'SignOut' ? true : false;
});
await Future.delayed(const Duration(seconds: 3));
setState(() {
_isSignOutBusy = item == 'SignOut' ? false : true;
});
}
@override
Widget build(BuildContext context) {
return Center(
child: MouseRegion(
onEnter: (_) => _setMouseHovering(true),
onExit: (_) => _setMouseHovering(false),
child: Container(
alignment: Alignment.center,
color: Colors.blueGrey[200],
height: 80,
width: double.infinity,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (_isMouseHover || _anyTaskRunning)
SizedBox(
width: 200,
child: FilledButton(
onPressed: _runTask1,
child: _anyTaskRunning
? const Row(
mainAxisSize: MainAxisSize.min,
children: [
Text('Running Task'),
SizedBox(
width: 25,
height: 25,
child: CircularProgressIndicator(),
)
],
)
: const Text('Task 1'),
),
),
const SizedBox(width: 40),
MenuProfile(
version: '0.0.1',
onSelected: _onItemSelected,
signOutBusy: _isSignOutBusy,
),
const SizedBox(width: 40),
if (_isMouseHover || _anyTaskRunning)
SizedBox(
width: 200,
child: FilledButton(
onPressed: _runTask2,
child: _anyTaskRunning
? const Row(
mainAxisSize: MainAxisSize.min,
children: [
Text('Running Task'),
SizedBox(
width: 25,
height: 25,
child: CircularProgressIndicator(),
)
],
)
: const Text('Task 2'),
),
),
],
),
),
),
);
}
}
class MenuProfile extends StatelessWidget {
final String version;
final bool signOutBusy;
final Function(String) onSelected;
const MenuProfile({
super.key,
required this.version,
required this.onSelected,
required this.signOutBusy,
});
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return PopupMenuButton(
itemBuilder: (context) => [
const PopupMenuItem<String>(
value: 'SignOut',
child: Text('Sign out'),
),
],
onSelected: onSelected,
icon: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 30,
height: 30,
padding: const EdgeInsets.all(3),
decoration: BoxDecoration(
color: colorScheme.inversePrimary,
shape: BoxShape.circle,
),
child: signOutBusy ? const CircularProgressIndicator() : null,
),
const SizedBox(height: 20),
Text(
version,
style: const TextStyle(fontSize: 7, color: Colors.grey),
),
],
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment