Как динамически отключить вертикальный свайп в просмотре страниц

#flutter

Вопрос:

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

Я использую riverpod для обновления состояния в дочернем виджете, когда он создается, чтобы знать, когда я должен перейти NeverScrollableScrollPhysics к physics параметру в родительском виджете. Но дело в том, что этот подход заставляет мой дочерний виджет перестраиваться рекурсивно, потому что это приводит к PageView перестройке для обновления параметров физики. Так что я действительно не знаю, что здесь делать.

У меня есть этот родительский виджет, который создает просмотр страницы:

 Widget build(BuildContext context) {
  final _navBar = useProvider(bottomNavigationBarProvider);
  return PageView(
    physics: navBar.isSwipeBlocked ? const NeverScrollableScrollPhysics() : null,
    controller: pageController,
    onPageChanged: onPageChanged,
    children: [
      Beamer(
        key: const Key('feed-tab'),
        routerDelegate: BeamerDelegate(locationBuilder: (state) => FeedLocation(state)),
      ), 
    ]
  )
}  
 

И дочерний виджет, который обновляет переменную состояния:

 Widget build(BuildContext context) {
  final _navBar = useProvider(bottomNavigationBarProvider.notifier);
  useEffect(() {
    Future.microtask(() => _navBar.blockSwipe());
  }, []);
  return Container(...);
}
 

Поэтому при FeedLocation загрузке он обновляется _navBar в попытке отключить поведение прокрутки. Но, как я уже упоминал, это приводит к тому, что родитель перестраивается и FeedLocation строится заново, а затем переходит в рекурсивное состояние..

Идея состояла в том , чтобы иметь возможность перейти FeedLocation , отключить прокрутку, а затем, когда вернетесь, снова включить ее, но я не вижу решения для этого.

Я думаю, что уже сделал то, что предложил этот парень https://github.com/flutter/flutter/issues/37510#issuecomment-738051469 использование Riverpod

И я думаю, что я в такой же ситуации, как и эти ребята из той же темы https://github.com/flutter/flutter/issues/37510#issuecomment-864416592

Кто-нибудь может увидеть решение или то, что я делаю неправильно?

Ответ №1:

Вы должны заменить null вторичную физику PageScrollPhysics() прокрутки и обязательно добавить setState(() {}); ее при обновлении isSwipeBlocked переменной.

Комментарии:

1. Привет @MindStudio. Замена null на PageScrollPhysics() не имеет значения, так physics как может быть аннулирована и существует значение по умолчанию. Кроме того, я не вижу, что использовать с setState и где именно, так как я использую riverpod для заблокированного состояния Isswip. Не могли бы вы, пожалуйста, уточнить setState(() {}); использование ?

2. вы звоните setState(() {}); всякий раз, когда хотите перестроить дерево виджетов виджета с отслеживанием состояния с новыми значениями. Вам необходимо перестроить виджет после изменения значения isSwipeBlocked, чтобы изменения вступили в силу. Вы можете вызвать setState(() {}); из любого места внутри функции сборки StatefulWidget.

3. Привет @MindStudio, спасибо. Дело в том, что я уже использую riverpod, и вызов _navBar.blockSwipe() в дочернем устройстве уже обновляет состояние как _navBar StateNotifier из riverpod, что вызывает перестройку родителя PageView , которая заставляет ребенка снова строить, а затем рекурсию, и это, мой друг, моя проблема 🙂 Я бы сказал blockSwipe() , что это своего рода setState речной стручок. Кстати, мои виджеты такие HookWidget .