I'm trying to implement a feature where an edit icon appears only for the container the user is hovering over. Currently, when I hover over one container, edit icons appear for all four containers. Here's what I'm experiencing:
This is the desired result:
I have a row of four AddProyectName
widgets, each representing a project container. The edit icon visibility is controlled by a single _isEditIconVisible
state variable in the parent widget.
Here's a simplified version of the relevant code:
add_projects.dart
class AddProyectName extends ConsumerStatefulWidget {
final Color color;
final Icon? icon;
final int index;
final bool isEditable;
final bool isEditIconVisible;
final Function(PointerEnterEvent)? onEnterContainerHover;
final Function(PointerExitEvent)? onExitContainerHover;
const AddProyectName(this.color,
{required this.index,
this.icon,
this.isEditable = false,
super.key,
required this.isEditIconVisible,
this.onEnterContainerHover,
this.onExitContainerHover});
@override
ConsumerState<ConsumerStatefulWidget> createState() => _AddProyectNameState();
}
class _AddProyectNameState extends ConsumerState<AddProyectName> {
bool _isHovered = false;
@override
Widget build(BuildContext context) {
final selectedContainerIndex = ref.watch(selectedProyectContainerProvider);
final projectNames = ref.watch(projectStateNotifierProvider);
//... code
return MouseRegion(
onEnter: widget.onEnterContainerHover,
onExit: widget.onExitContainerHover,
cursor: SystemMouseCursors.click,
child: Container(
height: 66,
width: 27,
decoration: BoxDecoration(
border: Border.all(
color: Colors.transparent,
),
),
//... code
child: Container(
width: 24,
height: 24,
decoration: BoxDecoration(
color: widget.color,
shape: BoxShape.circle,
border: selectedContainerIndex != null &&
selectedContainerIndex == widget.index
? Border.all(color: Colors.white, width: 2.0)
: null,
),
child: widget.icon != null
? Center(child: widget.icon)
: null,
),
),
Visibility(
visible: widget.isEditIconVisible,
replacement: const SizedBox(
height: 40,
width: 25,
),
child: MouseRegion(
onEnter: (_) => setState(() => _isHovered = true),
onExit: (_) => setState(() => _isHovered = false),
cursor: SystemMouseCursors.click,
child: Tooltip(
message: "Edit Project",
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(4.0),
),
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _isHovered
? Colors.white30
: Colors.transparent,
),
height: 40,
width: 25,
child: GestureDetector(
onTap: () {
_showDialog(context, 'Edit Project',
'Please edit the project name');
},
child: const Icon(Icons.edit,
color: Colors.white, size: 20),
),
),
),
),
),
//... code
task_card.dart
class TaskCard extends ConsumerStatefulWidget {
const TaskCard({super.key});
@override
ConsumerState<ConsumerStatefulWidget> createState() => _TaskCardState();
}
class _TaskCardState extends ConsumerState<TaskCard> {
bool _isEditIconVisible = false;
//... code
return LayoutBuilder(builder: (context, constraints) {
final currentWidth = MediaQuery.of(context).size.width;
return Row(
//... code
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Flexible(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
setState(() => _isEditIconVisible = false);
},
child: AddProyectName(
const Color(0xffDE6868),
index: 0,
isEditable: true,
isEditIconVisible: _isEditIconVisible,
onEnterContainerHover: (p0) {
setState(() => _isEditIconVisible = true);
},
onExitContainerHover: (p0) {
setState(() => _isEditIconVisible = false);
},
),
),
),
// ... similar code for other AddProyectName widgets
],
),
The AddProyectName
widget uses this isEditIconVisible
prop to determine whether to show the edit icon:
Visibility(
visible: widget.isEditIconVisible,
replacement: const SizedBox(height: 40, width: 25),
child: // ... edit icon widget
)
The issue is that the _isEditIconVisible
state is shared among all AddProyectName
widgets. When one container is hovered, it sets _isEditIconVisible
to true, causing all containers to show their edit icons.
I've attempted to use individual MouseRegion
widgets for each container, but I'm still struggling to make the edit icon appear only for the hovered container.
How can I modify my code to ensure that the edit icon appears only for the specific container being hovered over?
We need to separate "_isEditIconVisible" for each container.
Like this:
import 'package:flutter/material.dart';
void main() async {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(useMaterial3: false),
home: const TestApp(),
);
}
}
class TestApp extends StatefulWidget {
const TestApp({super.key});
@override
State<TestApp> createState() => _TestAppState();
}
class _TestAppState extends State<TestApp> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Center(
child: Row(
children: const [
AddProyectName(
Color(0xffDE6868),
index: 0,
isEditable: true,
),
SizedBox(width: 20),
AddProyectName(
Colors.yellow,
index: 1,
isEditable: true,
),
SizedBox(width: 20),
AddProyectName(
Colors.blue,
index: 2,
isEditable: true,
),
SizedBox(width: 20),
AddProyectName(
Colors.green,
index: 3,
isEditable: true,
),
],
),
),
);
}
}
class AddProyectName extends StatefulWidget {
final Color color;
final int index;
final bool isEditable;
const AddProyectName(
this.color, {
required this.index,
this.isEditable = false,
super.key,
});
@override
State<AddProyectName> createState() => _AddProyectNameState();
}
class _AddProyectNameState extends State<AddProyectName> {
bool _isHovered = false;
bool _isEditIconVisible = false;
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
setState(() => _isEditIconVisible = false);
},
child: MouseRegion(
onEnter: (event) {
setState(() => _isEditIconVisible = true);
},
onExit: (event) {
setState(() => _isEditIconVisible = false);
},
child: SizedBox(
height: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Column(
children: [
Container(
width: 50,
height: 50,
color: widget.color,
),
Visibility(
visible: _isEditIconVisible,
replacement: const SizedBox(
height: 40,
width: 40,
),
child: MouseRegion(
onEnter: (_) => setState(() => _isHovered = true),
onExit: (_) => setState(() => _isHovered = false),
cursor: SystemMouseCursors.click,
child: Tooltip(
message: "Edit Message",
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(4.0),
),
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _isHovered
? Colors.white30
: Colors.transparent,
),
height: 40,
width: 40,
child: const Icon(Icons.edit,
color: Colors.white, size: 20),
),
),
)),
],
),
],
),
),
),
);
}
}