动画库捕获了选项卡控制器异常

时间:2019-05-19 10:55:12

标签: flutter flutter-animation

转到厨房屏幕。 点击[[蛋糕标签]]。 刷蛋糕项目。 当您进入蛋糕的最后一项时,点击[[菜谱选项卡]]。弹出此错误。

  

I / flutter(23156):BY动画库引起的异常提示   ╞═════════════════════════════════════════════════ ════════我/扑   (23156):在通知侦听器时引发了以下断言   对于AnimationController:I / flutter(23156):   'package:flutter / src / material / tab_controller.dart':断言失败:   第180行pos 12:“长度> 1”:I / flutter(23156):不正确。   I / flutter(23156):任一断言都指示   框架本身,否则我们应该提供大量的I / flutter   (23156):此错误消息中的更多信息可帮助您确定   并解决根本原因。 I / flutter(23156):无论哪种情况,   请通过在GitHub上提交错误报告此声明:I / flutter   (23156):
  https://github.com/flutter/flutter/issues/new?template=BUG.md   I / flutter(23156):I / flutter(23156):当引发异常时,   这是堆栈:I / flutter(23156):#2 TabController.offset =   (包:flutter / src / material / tab_controller.dart:180:12)I / flutter   (23156):#3 _TabBarViewState._handleScrollNotification   (包装:flutter / src / material / tabs.dart:1249:19)I / flutter(23156):#4   NotificationListener._dispatch   (package:flutter / src / widgets / notification_listener.dart:127:27)   I / flutter(23156):#5 Notification.visitAncestor   (package:flutter / src / widgets / notification_listener.dart:45:20)   I / flutter(23156):#6
  _ScrollNotification&LayoutChangedNotification&ViewportNotificationMixin.visitAncestor   (包:flutter / src / widgets / scroll_notification.dart:31:18)I / flutter   (23156):#7 Element.visitAncestorElements   (包:flutter / src / widgets / framework.dart:3355:39)I / flutter   (23156):#8 Notification.dispatch   (package:flutter / src / widgets / notification_listener.dart:61:13)   I / flutter(23156):#9
  ScrollActivity.dispatchScrollUpdateNotification   (package:flutter / src / widgets / scroll_activity.dart:96:92)I / flutter   (23156):#10 ScrollPosition.didUpdateScrollPositionBy   (包裹:flutter / src / widgets / scroll_position.dart:658:14)I / flutter   (23156):#11 ScrollPosition.setPixels   (包:flutter / src / widgets / scroll_position.dart:219:9)I / flutter   (23156):#12 ScrollPositionWithSingleContext.setPixels   (软件包:flutter / src / widgets / scroll_position_with_single_context.dart:84:18)   I / flutter(23156):#13 DrivenScrollActivity._tick   (包:flutter / src / widgets / scroll_activity.dart:629:18)I / flutter   (23156):#14
  _AnimationController&Animation&AnimationEagerListenerMixin&AnimationLocalListenersMixin.notifyListeners   (包:flutter / src / animation / listener_helpers.dart:126:19)I / flutter   (23156):#15 AnimationController._tick   (包:flutter / src / animation / animation_controller.dart:750:5)   I / flutter(23156):#16股票。_tick   (package:flutter / src / scheduler / ticker.dart:228:5)I / flutter(23156):

     

17 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback

     

(包:flutter / src / scheduler / binding.dart:1012:15)I / flutter   (23156):#18
  _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleBeginFrame。 (包:flutter / src / scheduler / binding.dart:928:11)I / flutter   (23156):#19
  __InternalLinkedHashMap&_HashVMBase&MapMixin&_LinkedHashMapMixin.forEach   (dart:collection-patch / compact_hash.dart:367:8)I / flutter(23156):#20   _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleBeginFrame   (package:flutter / src / scheduler / binding.dart:926:17)I / flutter(23156):

     

21 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleBeginFrame

     

(package:flutter / src / scheduler / binding.dart:856:5)I / flutter(23156):

     

25 _invoke1(dart:ui / hooks.dart:233:10)I / flutter(23156):#26 _beginFrame(dart:ui / hooks.dart:172:3)I / flutter(23156):(已消除来自类_AssertionError和包dart:async的5帧)I / flutter

     

(23156):I / flutter(23156):AnimationController通知   听众是:I / flutter(23156):AnimationController#88632(▶   222.418; for DrivenScrollActivity)

现在返回[[Dishes Tab]]。

  1. cakesController 一种。长度=
    _index
    b。 _previousIndex = dishesController C。 _index = {{0}}
  2. _previousIndex 一种。长度= dishesController。 b。 cakesController = {{0}} C。 cakesControllers = {{0}}

cakesController尝试完成从索引_index到索引{{0}}的动画,实际上这是_previousIndex的属性。这会导致错误。

可能的解决方案:  需要确认单击[[Dishes Tab]]后,import 'package:flutter/material.dart'; /***************************** Data Class *************************************************/ /******************************************************************************************/ /* * Data will display in the TabBarView build method of KitchenBody Class. */ class DynamicTabContent { IconData icon; String tooTip; DynamicTabContent.name(this.icon, this.tooTip); } void main() => runApp(MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Kitchen', theme: ThemeData( // This is the theme of your application. // // Try running your application with "flutter run". You'll see the // application has a blue toolbar. Then, without quitting the app, try // changing the primarySwatch below to Colors.green and then invoke // "hot reload" (press "r" in the console where you ran "flutter run", // or simply save your changes to "hot reload" in a Flutter IDE). // Notice that the counter didn't reset back to zero; the application // is not restarted. primarySwatch: Colors.blue, ), home: Kitchen(), ); } } class Kitchen extends StatefulWidget { @override KitchenState createState() => new KitchenState(); } /***************************** KitchenState Class *************************************************/ /******************************************************************************************/ /* * KitchenState is the whole working screen. */ class KitchenState extends State<Kitchen> with TickerProviderStateMixin { /* * These data lists will store data for dishes and cakes tabBarView Widgets. */ List<DynamicTabContent> dishes = new List(); List<DynamicTabContent> cakes = new List(); /* * parentTabsController is helping to move around dishes and cakes. */ TabController parentTabsController; /* * dishesController is helping to scroll around all the dishes. */ TabController dishesController; /* * dishesController is helping to scroll around all the cakes. */ TabController cakesController; dishesAndCakesTabsHandler() { /* * [[Check]] If parentTabsController index = 0 then it means we are in [[Dishes Tab]]. */ if (parentTabsController.index == 0) { /* * Please read this {{{ if (parentTabsController.index == 1) }}}} condition first * then comes back to this condition to understand the problem. * {{{Problem}}} * Go to [[Cakes Tab]]. Swipe cake items. Tap [[Dishes Tab]] when you are at * the last item of cakes. Animation length > 1 error occurs. * {{{Reason}}} When you come back to [[Dishes Tab]]. * cakesController * Length = {{2}}. * _index = {{1}} * _previousIndex = {{0}} * dishesController * Length = {{1}}. * _index = {{0}} * _previousIndex = {{0}} * dishesController tried to complete animation from index{{1}} to index{{0}} * which are actually the properties of cakesController. This cause error given below. * * ══╡ EXCEPTION CAUGHT BY ANIMATION LIBRARY ╞════════════════════════════════════════ * The following assertion was thrown while notifying listeners for AnimationController: * 'package:flutter/src/material/tab_controller.dart': Failed assertion: line 180 pos 12: * 'length > 1': is not true. * * {{{Now TabBarView data neither change nor swipe.}}} * * {{Possible Solution}} * Need to confirms that when [[Dishes Tab]] clicked, cakesControllers comes back * to default properties. For example * cakesController * Length = {{2}}. * _index = {{0}}. * _previousIndex = {{0}}. * * {{My Solution}} is implemented below */ setState(() { /* * animateTo index 0. */ this .cakesController .animateTo(0, duration: kTabScrollDuration, curve: Curves.ease); /* * You can see in console the cakesController current and previous indexes; */ print( 'cakesController.index: ' + this.cakesController.index.toString()); print('cakesController.previousIndex: ' + this.cakesController.previousIndex.toString()); /* * I completely erase cakesController data then reinitialize it.; */ this.cakesController = null; this.cakesController = new TabController(length: cakes.length, vsync: this); }); print('cakesController.index: ' + this.cakesController.index.toString()); print('cakesController.previousIndex: ' + this.cakesController.previousIndex.toString()); /* * Initialize dishes again; */ setState(() { /* * First clear dishes list to stop adding duplicate data. * Then initialize dishesController. */ dishes.clear(); dishes.add(new DynamicTabContent.name(Icons.map, "Taco")); this.dishesController = new TabController(length: dishes.length, vsync: this); }); } /* * [[Check]] If parentTabsController index = 1 then it means we are in [[Cakes Tab]]. */ if (parentTabsController.index == 1) { /* * First clear cakes list to stop adding duplicate data. * Then initialize cakesController. */ setState(() { cakes.clear(); cakes .add(new DynamicTabContent.name(Icons.cake, "Black Forest Gateau")); cakes.add(new DynamicTabContent.name(Icons.cake, "Basbousa")); this.cakesController = new TabController(length: cakes.length, vsync: this); }); } } @override void initState() { super.initState(); print("initState = KitchenTabs"); /* * Initializing parentTabsController and this initialization [[will never change]]. */ parentTabsController = new TabController(initialIndex: 0, length: 2, vsync: this); /* * Initializing dishes and dishesController and this initialization will change * when user came after the visit from [[Cakes to Dishes Tabs]]. */ dishes.add(new DynamicTabContent.name(Icons.map, "Taco")); dishesController = new TabController(length: dishes.length, vsync: this); /* * Initialization of cakes and cakesController will happen when user tap on [[Cakes Tab]]. */ } @override void dispose() { print("dispose = KitchenTabs"); dishesController.removeListener(dishesAndCakesTabsHandler); dishesController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: NestedScrollView( headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return <Widget>[ SliverAppBar( leading: IconButton( icon: Icon( Icons.arrow_back, color: Colors.white, ), onPressed: null, ), title: Text('Kitchen'), floating: true, pinned: true, bottom: TabBar( controller: parentTabsController, onTap: (int index) { print('*************************************************'); print("Parent Tab: " + index.toString()); print('*************************************************'); dishesAndCakesTabsHandler(); }, tabs: [ Tab(icon: Icon(Icons.fastfood), text: "Dishes"), Tab(icon: Icon(Icons.cake), text: "Cakes"), ], ), ), SliverPersistentHeader( pinned: true, delegate: TabBarDelegate( parentTabsController: parentTabsController, dishesController: dishesController, cakesController: cakesController, ), ), ]; }, body: TabBarViewWidget( parentTabsController: parentTabsController, dishesController: dishesController, cakesController: cakesController, dishes: dishes, cakes: cakes, ), ), ); } } class TabBarViewWidget extends StatefulWidget { TabBarViewWidget({ this.parentTabsController, this.dishesController, this.cakesController, this.dishes, this.cakes, }); final TabController parentTabsController; final TabController dishesController; final TabController cakesController; final List<DynamicTabContent> dishes; final List<DynamicTabContent> cakes; State<StatefulWidget> createState() { return TabBarViewWidgetState(); } } /***************************** TabBarViewWidgetState Class *********************************/ /******************************************************************************************/ /* * TabBarViewWidgetState is returning the TabBarView Widget. * TabBarViewWidgetState has tabControllers which are initialized from the Kitchen tabControllers. */ class TabBarViewWidgetState extends State<TabBarViewWidget> { @override void initState() { print("initState = KitchenBodyState"); super.initState(); } @override Widget build(BuildContext context) { return widget.parentTabsController.index == 0 ? TabBarView( controller: widget.dishesController, children: widget.dishes.isEmpty ? <Widget>[] : widget.dishes.map( (dynamicContent) { return ListView( children: <Widget>[ Container( padding: EdgeInsets.only(top: 50), width: 200, height: 400, child: Column( children: <Widget>[ Center( child: Icon( dynamicContent.icon, size: 80, ), ), SizedBox( height: 20, ), Center( child: Text( dynamicContent.tooTip, ), ), ], ), ), ], ); }, ).toList(), ) : widget.parentTabsController.index == 1 ? TabBarView( controller: widget.cakesController, children: widget.cakes.isEmpty ? <Widget>[] : widget.cakes.map( (dynamicContent) { return ListView( children: <Widget>[ Container( padding: EdgeInsets.only(top: 50), width: 200, height: 400, child: Column( children: <Widget>[ Center( child: Icon( dynamicContent.icon, size: 80, ), ), SizedBox( height: 20, ), Center( child: Text( dynamicContent.tooTip, ), ), ], ), ), ], ); }, ).toList(), ) : null; } } /***************************** TabBarDelegate Class *********************************/ /******************************************************************************************/ /* * TabBarDelegate is returning the TabBar Widget. * TabBarDelegate has tabBars which are initialized from the Kitchen tabBars. */ class TabBarDelegate extends SliverPersistentHeaderDelegate { TabBarDelegate({ this.parentTabsController, this.dishesController, this.cakesController, }); final TabController parentTabsController; final TabController dishesController; final TabController cakesController; @override double get minExtent => kToolbarHeight; @override double get maxExtent => kToolbarHeight; getDishName() { return List<Widget>.generate( dishesController.length, (int index) { print("Dish Tabs"); return new Tab(text: index.toString()); }, ); } getCakeName() { return List<Widget>.generate( cakesController.length, (int index) { print("Deal Tabs"); return new Tab(text: index.toString()); }, ); } @override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { return Container( color: Theme.of(context).cardColor, height: kToolbarHeight, child: TabBar( controller: parentTabsController.index == 0 ? dishesController : parentTabsController.index == 1 ? cakesController : null, isScrollable: true, labelColor: Theme.of(context).accentColor, indicatorSize: TabBarIndicatorSize.label, indicatorColor: Theme.of(context).accentColor, tabs: parentTabsController.index == 0 ? getDishName() : parentTabsController.index == 1 ? getCakeName() : null, ), ); } @override bool shouldRebuild(covariant TabBarDelegate oldDelegate) { return parentTabsController.index == 0 ? oldDelegate.dishesController != dishesController : parentTabsController.index == 1 ? oldDelegate.cakesController != cakesController : null; } } 返回默认属性。例如   1. {{1}}      一种。长度= {{2}}      b。 {{1}} = {{0}}      C。 {{1}} = {{0}}

/ **********只需复制/粘贴即可将代码运行到Flutter项目中********* / / ***************************************************** ********************** /

{{2}}

0 个答案:

没有答案