В арсенале 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, меняя визуальную обратную связь) или сложные флаги в состояниях, а использовать декларативный и точный инструмент. Эти невидимые виджеты - фундамент для создания проработанного, устойчивого к нежелательным действиям пользовательского интерфейса, где каждое взаимодействие находится под вашим полным контролем.
➡️ Flutter & Dart | Мобильный трудоголик