Как отобразить только один значок редактирования для выбранного контейнера во Flutter?

Я пытаюсь реализовать функцию, при которой значок редактирования отображается только для контейнера, над которым наводит курсор. В настоящее время, когда я навожу курсор на один контейнер, значки редактирования появляются для всех четырех контейнеров. Вот что я испытываю:

Это желаемый результат:

Текущая реализация

У меня есть ряд из четырех виджетов AddProyectName, каждый из которых представляет контейнер проекта. Видимость значка редактирования контролируется одной переменной состояния _isEditIconVisible в родительском виджете.

Вот упрощенная версия соответствующего кода:

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

                        ],
                      ),
                    



Виджет AddProyectName использует этот реквизит isEditIconVisible, чтобы определить, отображать ли значок редактирования:

Visibility(
  visible: widget.isEditIconVisible,
  replacement: const SizedBox(height: 40, width: 25),
  child: // ... edit icon widget
)

Проблема:

Проблема в том, что состояние _isEditIconVisible является общим для всех AddProyectName виджетов. Когда на один контейнер наведен курсор, для _isEditIconVisible устанавливается значение true, в результате чего во всех контейнерах отображаются значки редактирования.

Что я пробовал

Я пытался использовать отдельные виджеты MouseRegion для каждого контейнера, но все еще пытаюсь сделать так, чтобы значок редактирования отображался только для наведенного контейнера.

Вопрос

Как я могу изменить свой код, чтобы значок редактирования отображался только для конкретного контейнера, над которым наведен курсор?

Вы пробовали использовать Tooltip?

SrPanda 26.06.2024 16:12
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Нам нужно отделить «_isEditIconVisible» для каждого контейнера.

Так:

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),
                          ),
                        ),
                      )),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Другие вопросы по теме