Изменение количества элементов Flutter PageView заставляет PageController jumpToPage переходить на неправильную страницу

У меня есть один PageView, который обрабатывает три списка данных разной длины. В первом списке есть один элемент, в списке 2 - 2 элемента, а в списке 3 - 3 элемента. Вот что происходит.

  1. PageView создается со списком 1 itemCount = 1 и страницей 0.
  2. PageView создается со списком 2 itemCount = 2 и страницей 0.
  3. PageView создается со списком 3 itemCount = 3 и страницей 2.
  4. Вызывается PageController.jumpToPage (2).
  5. Страница 2 отображается, а затем автоматически прокручивается до страницы 1. (кажется, что страницы 2 нет, и выполняется обратная прокрутка к последней странице, когда itemCount было 2)

Я попытался вызвать jumpToPage (2) после того, как PageView будет построен с использованием WidgetsBinding.instance.addPostFrameCallback (...) в методе сборки, думая, что PageController где-то читал старое значение itemCount = 2. Это не сработало.

Как заставить jumpToPage (2) работать на основе нового PageView itemCount = 3?

Вот мой код. Я постарался сделать это как можно проще.

import 'package:flutter/material.dart';

class HomePage2 extends StatefulWidget {
  @override
  _HomePage2State createState() => _HomePage2State();
}

class _HomePage2State extends State<HomePage2> {
  List<Map<String, dynamic>> following = [
    {'title': 'Page 1 of 1 following', 'color': Colors.purple.value},
  ];
  List<Map<String, dynamic>> suggested = [
    {'title': 'Page 1 of 2 suggested', 'color': Colors.purple.value},
    {'title': 'Page 2 of 2 suggested', 'color': Colors.red.value},
  ];
  List<Map<String, dynamic>> trending = [
    {'title': 'Page 1 of 3 trending', 'color': Colors.purple.value},
    {'title': 'Page 2 of 3 trending', 'color': Colors.red.value},
    {'title': 'Page 3 of 3 trending', 'color': Colors.orange.value},
  ];

  String currentFeed = 'suggested';

  int followingCurrentPosition = 0;
  int suggestedCurrentPosition = 0;
  int trendingCurrentPosition = 0;

  PageController _pageController;

  @override
  void initState() {
    super.initState();
    _pageController = PageController();
  }

  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    print('build');
    WidgetsBinding.instance.addPostFrameCallback(
        (_) => _pageController.jumpToPage(getCurrentFeedPosition()));
    return Scaffold(
      body: PageView.builder(
        itemCount: getCurrentFeed().length,
        scrollDirection: Axis.vertical,
        controller: _pageController = PageController(viewportFraction: 1),
        itemBuilder: (context, index) {
          print('PageView itemBuilder');
          return Container(
            color: Color(getCurrentFeed()[index]['color']),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Center(
                  child: Text(getCurrentFeed()[index]['title']),
                ),
                Center(
                  child: RaisedButton(
                    onPressed: () => changeCurrentFeed(),
                    child: Text('Change Feed'),
                  ),
                ),
              ],
            ),
          );
        },
      ),
    );
  }

  void changeCurrentFeed() {
    setState(
      () {
        if (currentFeed == 'following') {
          followingCurrentPosition = _pageController.page.floor();
          currentFeed = 'suggested';
        } else if (currentFeed == 'suggested') {
          suggestedCurrentPosition = _pageController.page.floor();
          currentFeed = 'trending';
        } else {
          trendingCurrentPosition = _pageController.page.floor();
          currentFeed = 'following';
        }
      },
    );
  }

  List<Map<String, dynamic>> getCurrentFeed() {
    if (currentFeed == 'following') {
      return following;
    } else if (currentFeed == 'suggested') {
      return suggested;
    } else {
      return trending;
    }
  }

  int getCurrentFeedPosition() {
    if (currentFeed == 'following') {
      return followingCurrentPosition;
    } else if (currentFeed == 'suggested') {
      return suggestedCurrentPosition;
    } else {
      return trendingCurrentPosition;
    }
  }
}

person Warren    schedule 14.09.2020    source источник


Ответы (1)


Такое поведение, по-видимому, вызвано тем, что PageView itemBuilder вызывается более одного раза за сборку. У других была эта проблема, но я не смог найти решения. В итоге я использовал отдельный PageView для каждого списка вместо того, чтобы пытаться использовать один PageView с несколькими списками. Это исправило это для меня.

person Warren    schedule 15.09.2020