Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter Error: 'indexOf(child) > index': is not true. (StreamBuilder,PageView)

I'm trying to create a screen that is contained within a pageview, that also contains a page view for part of the screen.

To acheive this I have an unlimited page view for the whole page itself, then every page has a header view, with a bottom half that has a page view with 3 possible options. I have this pretty much working, however, the pages I am using I would like a StreamBuilder... This is where the issue is caused.

class DiaryPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _DiaryPage();
}

class _DiaryPage extends State<DiaryPage> with TickerProviderStateMixin {
  DiaryBloc _diaryBloc;
  TabController _tabController;
  PageController _pageController;

  @override
  void initState() {
    _diaryBloc = BlocProvider.of<DiaryBloc>(context);
    _diaryBloc.init();

    _tabController = TabController(length: 3, vsync: this);
    _pageController = PageController(initialPage: _diaryBloc.initialPage);

    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {

    return Flexible(
      child: PageView.builder(
        controller: _pageController,
        itemBuilder: (BuildContext context, int position) {
          return _buildPage(_diaryBloc.getDateFromPosition(position));
        },
        itemCount: _diaryBloc.amountOfPages,
      ),
    );
  }

  Widget _buildPage(DateTime date) {
    return Column(
      mainAxisSize: MainAxisSize.max,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[_getHeader(date), _getTabBody()],
    );
  }

  Widget _getHeader(DateTime date) {
    return Card(
      child: SizedBox(
        width: double.infinity,
        height: 125,
        child: Column(
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.fromLTRB(8, 16, 8, 0),
              child: Text(
                '${DateFormat('EEEE').format(date)} ${date.day} ${DateFormat('MMMM').format(date)}',
                style: Theme.of(context).textTheme.subtitle,
                textScaleFactor: 1,
                textAlign: TextAlign.center,
              ),
            ),
            Row(
              mainAxisSize: MainAxisSize.max,
              children: <Widget>[
                IconButton(
                  icon: const Icon(Icons.chevron_left),
                  onPressed: () => {
                        _pageController.previousPage(
                            duration: Duration(milliseconds: 250),
                            curve: Curves.ease)
                      },
                ),
                const Expanded(child: LinearProgressIndicator()),
                IconButton(
                  icon: const Icon(Icons.chevron_right),
                  onPressed: () => {
                        _pageController.nextPage(
                            duration: Duration(milliseconds: 250),
                            curve: Curves.ease)
                      },
                ),
              ],
            ),
            Container(
              height: 40.0,
              child: DefaultTabController(
                length: 3,
                child: Scaffold(
                  backgroundColor: Colors.white,
                  appBar: TabBar(
                    controller: _tabController,
                    unselectedLabelColor: Colors.grey[500],
                    labelColor: Theme.of(context).primaryColor,
                    tabs: const <Widget>[
                      Tab(icon: Icon(Icons.pie_chart)),
                      Tab(icon: Icon(Icons.fastfood)),
                      Tab(icon: Icon(Icons.directions_run)),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _getTabBody() {
    return Expanded(
      child: TabBarView(
        controller: _tabController,
        children: <Widget>[
          _getOverviewScreen(),
          _getFoodScreen(),
          _getExerciseScreen(),
        ],
      ),
    );
  }

  // TODO - this seems to be the issue, wtf and why
  Widget _getBody() {
    return Flexible(
      child: StreamBuilder<Widget>(
        stream: _diaryBloc.widgetStream,
        initialData: _diaryBloc.buildEmptyWidget(),
        builder: (BuildContext context, AsyncSnapshot<Widget> snapshot) {
          return snapshot.data;
        },
      ),
    );
  }

  Widget _getExerciseScreen() {
    return Text("Exercise Screen"); //_getBody();
  }

  Widget _getFoodScreen() {
    return Text("Food Screen"); //_getBody();
  }

  Widget _getOverviewScreen() {
    return _getBody();
  }
}

As you can see, there are three widgets being returned as part of the sub page view, 2 of them are Text Widgets which show correctly, but the StreamBuilder, which is populated correctly with another Text Widget seems to give me the red screen of death. Any ideas?

like image 914
Phill Wiggins Avatar asked Sep 19 '25 08:09

Phill Wiggins


1 Answers

Fixed the problem, it was related to the StreamBuilder being wrapped in a Flexible rather than a column. I then added column to have a mainAxisSize of max... Seemed to work.

like image 95
Phill Wiggins Avatar answered Sep 20 '25 23:09

Phill Wiggins