В арсенале Flutter-разработчика есть десятки виджетов для построения визуала, но ключевое качество современного интерфейса - не только красота, но и его предсказуемое поведение. Как элегантно запретить двойное нажатие на кнопку, сделать слайдер только для чтения или временно приостановить все жесты в сложной форме? Для этих задач существуют специальные виджеты-контроллеры, которые оставаясь невидимыми, кардинально меняют логику взаимодействия. Сегодня разберем двух таких стражей порядка:
AbsorbPointer и
IgnorePointer.
Суть проблемы - управление потоком событий:
Каждое нажатие, свайп или скролл в приложении - это событие (event), которое проходит определенный путь (hit test) по дереву виджетов, чтобы найти целевой элемент. Иногда необходимо этот поток прервать или перенаправить. Именно здесь на сцену выходят невидимые виджеты-обертки. Их главная задача - влиять на процесс обработки жестов, не изменяя при этом внешний вид дочерних виджетов.
AbsorbPointer - полная блокировка:
Это стена. Когда
absorbing: true, все касания останавливаются на этом виджете. События не проходят к дочерним виджетам и не ищут другие цели.
Пример: кнопка отправки формы. Нужно заблокировать ее во время загрузки, но оставить видимой с анимацией:
AbsorbPointer(
absorbing: isLoading,
child: ElevatedButton(...),
)
IgnorePointer - сквозное игнорирование:
Это невидимка. При
ignoring: true виджет пропускает события сквозь себя. Hit-тестирование продолжается, события могут попасть в виджеты ниже.
Пример: полупрозрачный баннер поверх карты. Баннер виден, но карта остается интерактивной:
Stack(
children: [
InteractiveMap(),
IgnorePointer(
child: PromoBanner(),
),
],
)
Главное отличие:
- AbsorbPointer: события не проходят вообще.
- IgnorePointer: события проходят сквозь к виджетам позади.
Критические сценарии:
- Модальное окно с затемнением фона - нужен AbsorbPointer для блокировки фона.
- Анимированный индикатор поверх контента - нужен IgnorePointer, чтобы контент оставался кликабельным.
- Временное отключение поля формы - IgnorePointer, если нужно сохранить структуру hit-теста.
Вывод:
Выбор между
AbsorbPointer и
IgnorePointer - это не вопрос вкуса, а вопрос архитектуры взаимодействия. Он сводится к простому решению: нужно ли изолировать проблемную зону от всей системы событий (AbsorbPointer), или же требуется точечно выключить один виджет, не трогая общий поток (IgnorePointer).
Понимание этой разницы - признак зрелости разработчика. Оно позволяет не костылять отключение через
onPressed: null (что портит UX, меняя визуальную обратную связь) или сложные флаги в состояниях, а использовать декларативный и точный инструмент. Эти невидимые виджеты - фундамент для создания проработанного, устойчивого к нежелательным действиям пользовательского интерфейса, где каждое взаимодействие находится под вашим полным контролем.