Skip to content

Switching between navigation bars that have different number of tab bars throws an exception in animation libray.  #97441

@SuperPenguin

Description

@SuperPenguin

Whenever TabBarView controller is changed with one that has length more than previous length. It throws error.
Current stable atm doesn't throw error but still have this bug #93237.
The bug is already fixed on master by #94339, but fix causing error on case below.

Steps to Reproduce

  1. Run code below
  2. Go to last tab on Nav 0
  3. Navigate to Nav 1
  4. Navigate to Nav 0

Expected results: No error

Actual results: TabBarViewState throwing error

Code sample
import 'package:flutter/material.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  runApp(const App());
}

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      themeMode: ThemeMode.system,
      initialRoute: '/',
      routes: {
        '/': (context) => const HomePage(),
      },
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
  late final List<TabController> _tabControllers = [
    TabController(length: 20, vsync: this),
    TabController(length: 10, vsync: this),
    TabController(length: 2, vsync: this),
    TabController(length: 3, vsync: this),
  ];

  int _navIndex = 0;

  void _setNavIndex(int value) {
    setState(() {
      _navIndex = value;
    });
  }

  @override
  void dispose() {
    for (final c in _tabControllers) {
      c.dispose();
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final tc = _tabControllers[_navIndex];

    return Scaffold(
      appBar: AppBar(
        title: const Text('App'),
        bottom: TabBar(
          controller: tc,
          isScrollable: tc.length > 3,
          tabs: List<Tab>.generate(
            tc.length,
            (index) => Tab(
              text: 'Tab $_navIndex-$index',
            ),
          ),
        ),
      ),
      body: TabBarView(
        controller: tc,
        children: List<Widget>.generate(
          tc.length,
          (index) => Center(
            child: Text('Content $_navIndex-$index'),
          ),
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        currentIndex: _navIndex,
        onTap: _setNavIndex,
        items: const [
          BottomNavigationBarItem(
            icon: Icon(Icons.home_rounded),
            label: 'Nav 0',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.ac_unit_rounded),
            label: 'Nav 1',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.access_alarms_rounded),
            label: 'Nav 2',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.settings_rounded),
            label: 'Nav 3',
          ),
        ],
      ),
    );
  }
}
Logs
════════ Exception caught by animation library ═════════════════════════════════
The following assertion was thrown while notifying listeners for AnimationController:
Build scheduled during frame.

While the widget tree was being built, laid out, and painted, a new frame was scheduled to rebuild the widget tree.

This might be because setState() was called from a layout or paint callback. If a change is needed to the widget tree, it should be applied as the tree is being built. Scheduling a change for the subsequent frame instead results in an interface that lags behind by one frame. If this was done to make your build dependent on a size measured at layout time, consider using a LayoutBuilder, CustomSingleChildLayout, or CustomMultiChildLayout. If, on the other hand, the one frame delay is the desired effect, for example because this is an animation, consider scheduling the frame in a post-frame callback using SchedulerBinding.addPostFrameCallback or using an AnimationController to trigger the animation.

When the exception was thrown, this was the stack
#0      WidgetsBinding._handleBuildScheduled.<anonymous closure>
package:flutter/…/widgets/binding.dart:747
#1      WidgetsBinding._handleBuildScheduled
package:flutter/…/widgets/binding.dart:770
#2      BuildOwner.scheduleBuildFor
package:flutter/…/widgets/framework.dart:2539
#3      Element.markNeedsBuild
package:flutter/…/widgets/framework.dart:4477
#4      State.setState
package:flutter/…/widgets/framework.dart:1193
#5      _AnimatedState._handleChange
package:flutter/…/widgets/transitions.dart:128
#6      AnimationLocalListenersMixin.notifyListeners
package:flutter/…/animation/listener_helpers.dart:155
#7      AnimationController.value=
package:flutter/…/animation/animation_controller.dart:365
#8      TabController._changeIndex
package:flutter/…/material/tab_controller.dart:201
#9      TabController.index=
package:flutter/…/material/tab_controller.dart:219
#10     _TabBarViewState._handleScrollNotification
package:flutter/…/material/tabs.dart:1476
#11     Element.visitAncestorElements
package:flutter/…/widgets/framework.dart:4288
#12     Notification.dispatch
package:flutter/…/widgets/notification_listener.dart:83
#13     ScrollActivity.dispatchScrollEndNotification
package:flutter/…/widgets/scroll_activity.dart:104
#14     ScrollPosition.didEndScroll
package:flutter/…/widgets/scroll_position.dart:907
#15     ScrollPosition.beginActivity
package:flutter/…/widgets/scroll_position.dart:876
#16     ScrollPositionWithSingleContext.beginActivity
package:flutter/…/widgets/scroll_position_with_single_context.dart:114
#17     ScrollPositionWithSingleContext.goIdle
package:flutter/…/widgets/scroll_position_with_single_context.dart:129
#18     ScrollPositionWithSingleContext.goBallistic
package:flutter/…/widgets/scroll_position_with_single_context.dart:148
#19     BallisticScrollActivity.applyNewDimensions
package:flutter/…/widgets/scroll_activity.dart:549
#20     ScrollPosition.applyNewDimensions
package:flutter/…/widgets/scroll_position.dart:623
#21     ScrollPositionWithSingleContext.applyNewDimensions
package:flutter/…/widgets/scroll_position_with_single_context.dart:104
#22     ScrollPosition.applyContentDimensions
package:flutter/…/widgets/scroll_position.dart:553
#23     _PagePosition.applyContentDimensions
package:flutter/…/widgets/page_view.dart:473
#24     RenderViewport.performLayout
package:flutter/…/rendering/viewport.dart:1493
#25     RenderObject._layoutWithoutResize
package:flutter/…/rendering/object.dart:1733
#26     PipelineOwner.flushLayout
package:flutter/…/rendering/object.dart:887
#27     RendererBinding.drawFrame
package:flutter/…/rendering/binding.dart:497
#28     WidgetsBinding.drawFrame
package:flutter/…/widgets/binding.dart:883
#29     RendererBinding._handlePersistentFrameCallback
package:flutter/…/rendering/binding.dart:363
#30     SchedulerBinding._invokeFrameCallback
package:flutter/…/scheduler/binding.dart:1144
#31     SchedulerBinding.handleDrawFrame
package:flutter/…/scheduler/binding.dart:1081
#32     SchedulerBinding._handleDrawFrame
package:flutter/…/scheduler/binding.dart:995
#37     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
#38     _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)
The AnimationController notifying listeners was: AnimationController#d42a2(▶ 19.000; paused)
════════════════════════════════════════════════════════════════════════════════
PS C:\flutter> flutter doctor -v
[√] Flutter (Channel master, 2.10.0-1.0.pre.320, on Microsoft Windows [Version 10.0.22000.434], locale en-001)
    • Flutter version 2.10.0-1.0.pre.320 at C:\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision fc71ec55ee (3 hours ago), 2022-01-28 16:35:17 +0200
    • Engine revision c5ee2e4c35
    • Dart version 2.17.0 (build 2.17.0-66.0.dev)
    • DevTools version 2.10.0-dev.1

[√] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
    • Android SDK at C:\Users\andre\AppData\Local\Android\sdk
    • Platform android-31, build-tools 31.0.0
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.11.9)
    • Visual Studio at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community
    • Visual Studio Community 2019 version 16.11.32106.194
    • Windows 10 SDK version 10.0.19041.0

[√] Android Studio (version 2020.3)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7249189)

[√] VS Code (version 1.63.2)
    • VS Code at C:\Users\andre\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.32.0

[√] Connected device (4 available)
    • sdk gphone64 x86 64 (mobile) • emulator-5554 • android-x64    • Android 12 (API 31) (emulator)
    • Windows (desktop)            • windows       • windows-x64    • Microsoft Windows [Version 10.0.22000.434]
    • Chrome (web)                 • chrome        • web-javascript • Google Chrome 97.0.4692.71
    • Edge (web)                   • edge          • web-javascript • Microsoft Edge 97.0.1072.76

[√] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

Metadata

Metadata

Assignees

Labels

a: error messageError messages from the Flutter frameworkc: crashStack traces logged to the consolef: material designflutter/packages/flutter/material repository.found in release: 2.10Found to occur in 2.10frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer version

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions