将底部 TabBar 添加到 AppBar (Flutter) 时,TabBar 没有 TabController
No TabController for TabBar when adding bottom TabBar to AppBar (Flutter)
所以我想做的是,除了我的应用栏,我有徽标和搜索选项,我想添加底部 TabBar,用户可以在其中选择电影或电视节目,当他在其中之一时文本应该被点亮(不同的颜色)。但是当我尝试添加 TabBar 时出现错误:
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building MediaQuery(MediaQueryData(size: Size(411.4, 683.4),
devicePixelRatio: 2.6, textScaleFactor: 1.0, platformBrightness: Brightness.light, padding:
EdgeInsets.zero, viewPadding: EdgeInsets.zero, viewInsets: EdgeInsets.zero, alwaysUse24HourFormat:
false, accessibleNavigation: false, highContrast: false, disableAnimations: false, invertColors:
false, boldText: false, navigationMode: traditional)):
No TabController for TabBar.
When creating a TabBar, you must either provide an explicit TabController using the "controller"
property, or you must ensure that there is a DefaultTabController above the TabBar.
In this case, there was neither an explicit controller nor a default controller.
The relevant error-causing widget was:
AppBar file:///C:/Users/Meliha/Desktop/Rubicon/chillax/lib/presenter/home_page_movies.dart:22:15
When the exception was thrown, this was the stack:
#0 _TabBarState._updateTabController.<anonymous closure> (package:flutter/src/material/tabs.dart:965:9)
#1 _TabBarState._updateTabController (package:flutter/src/material/tabs.dart:974:6)
#2 _TabBarState.didChangeDependencies (package:flutter/src/material/tabs.dart:1006:5)
#3 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4653:11)
#4 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4469:5)
#5 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
#6 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6094:32)
... Normal element mounting (99 frames)
#105 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
#106 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6094:32)
... Normal element mounting (238 frames)
#344 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
#345 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6094:32)
... Normal element mounting (300 frames)
#645 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
#646 Element.updateChild (package:flutter/src/widgets/framework.dart:3306:18)
#647 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1182:16)
#648 RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:1153:5)
#649 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:1095:18)
#650 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2647:19)
#651 RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:1094:13)
#652 WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:934:7)
#653 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:915:7)
(elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
════════════════════════════════════════════════════════════════════════════════════════════════════
这是电影主页的代码:
import 'package:eva_icons_flutter/eva_icons_flutter.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:movie_app/view/now_playing_movie.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:movie_app/view/now_playing_tv.dart';
import 'package:movie_app/view/test.dart';
import 'package:movie_app/view/top_movies.dart';
import 'package:movie_app/view/top_tvs.dart';
import '../style/style.dart';
class HomePageMovie extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePageMovie> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFF151C26),
appBar: AppBar(
backgroundColor: Color(0xFF151C26),
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SvgPicture.asset(
logo,
height: 195,
),
],
),
actions: <Widget>[
IconButton(
onPressed: () {},
icon: Icon(
EvaIcons.searchOutline,
color: Colors.white,
))
],
bottom: TabBar(
indicatorColor: Color(0xFFf4C10F),
indicatorSize: TabBarIndicatorSize.tab,
indicatorWeight: 3.0,
unselectedLabelColor: Colors.white,
labelColor: Colors.white,
isScrollable: true,
tabs: [
Tab(
icon: Icon(Icons.movie),
text: "Movies",
),
Tab(
icon: Icon(Icons.tv),
text: "TV Shows",
)
]),
titleSpacing: 0.0,
),
body: ListView(
children: <Widget>[
NowPlayingMovies(),
BestMovie(),
],
),
);
}
}
任何形式的 help/tip/guide 都很棒。提前致谢
您的问题的解决方案就在错误文本中
When creating a TabBar, you must either provide an explicit TabController using the "controller"
property, or you must ensure that there is a DefaultTabController above the TabBar.
因此,最简单的解决方案是用 DefaultTabController
包装您的 TabBar
。由于您正在使用 AppBar
的 bottom
属性 需要 PreferredSizeWidget
,因此您还需要将其全部包装在实现它的东西中(因为它是抽象的 class) - 这里最简单的解决方案是只使用 PreferredSize
。完整示例可能如下所示:
AppBar(
bottom: PreferredSize(
// Set whatever size you want - this is a good default one
preferredSize: Size.fromHeight(kToolbarHeight),
child: DefaultTabController(
length: 2,
child: TabBar(
tabs: [
Tab(
text: 'Movies',
),
Tab(
text: 'TV Shows',
),
],
),
),
),
),
错误日志有时非常冗长,但这是关键信息:
When creating a TabBar, you must either provide an explicit TabController using the "controller"
property, or you must ensure that there is a DefaultTabController above the TabBar.
In this case, there was neither an explicit controller nor a default controller.
您只需将 Scaffold
小部件包裹在 DefaultTabController
中,并为其指定与您拥有的选项卡数量相对应的长度。对于更复杂的行为,您可以初始化 ScrollController
并将其添加到 TabBar
和 TabBarView
.
的 controller:
参数中
我还注意到示例中有一个 ListView
包含两个选项卡小部件。这行不通,换成 TabBarView
.
所以我想做的是,除了我的应用栏,我有徽标和搜索选项,我想添加底部 TabBar,用户可以在其中选择电影或电视节目,当他在其中之一时文本应该被点亮(不同的颜色)。但是当我尝试添加 TabBar 时出现错误:
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building MediaQuery(MediaQueryData(size: Size(411.4, 683.4),
devicePixelRatio: 2.6, textScaleFactor: 1.0, platformBrightness: Brightness.light, padding:
EdgeInsets.zero, viewPadding: EdgeInsets.zero, viewInsets: EdgeInsets.zero, alwaysUse24HourFormat:
false, accessibleNavigation: false, highContrast: false, disableAnimations: false, invertColors:
false, boldText: false, navigationMode: traditional)):
No TabController for TabBar.
When creating a TabBar, you must either provide an explicit TabController using the "controller"
property, or you must ensure that there is a DefaultTabController above the TabBar.
In this case, there was neither an explicit controller nor a default controller.
The relevant error-causing widget was:
AppBar file:///C:/Users/Meliha/Desktop/Rubicon/chillax/lib/presenter/home_page_movies.dart:22:15
When the exception was thrown, this was the stack:
#0 _TabBarState._updateTabController.<anonymous closure> (package:flutter/src/material/tabs.dart:965:9)
#1 _TabBarState._updateTabController (package:flutter/src/material/tabs.dart:974:6)
#2 _TabBarState.didChangeDependencies (package:flutter/src/material/tabs.dart:1006:5)
#3 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4653:11)
#4 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4469:5)
#5 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
#6 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6094:32)
... Normal element mounting (99 frames)
#105 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
#106 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6094:32)
... Normal element mounting (238 frames)
#344 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
#345 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6094:32)
... Normal element mounting (300 frames)
#645 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
#646 Element.updateChild (package:flutter/src/widgets/framework.dart:3306:18)
#647 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1182:16)
#648 RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:1153:5)
#649 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:1095:18)
#650 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2647:19)
#651 RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:1094:13)
#652 WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:934:7)
#653 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:915:7)
(elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
════════════════════════════════════════════════════════════════════════════════════════════════════
这是电影主页的代码:
import 'package:eva_icons_flutter/eva_icons_flutter.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:movie_app/view/now_playing_movie.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:movie_app/view/now_playing_tv.dart';
import 'package:movie_app/view/test.dart';
import 'package:movie_app/view/top_movies.dart';
import 'package:movie_app/view/top_tvs.dart';
import '../style/style.dart';
class HomePageMovie extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePageMovie> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFF151C26),
appBar: AppBar(
backgroundColor: Color(0xFF151C26),
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SvgPicture.asset(
logo,
height: 195,
),
],
),
actions: <Widget>[
IconButton(
onPressed: () {},
icon: Icon(
EvaIcons.searchOutline,
color: Colors.white,
))
],
bottom: TabBar(
indicatorColor: Color(0xFFf4C10F),
indicatorSize: TabBarIndicatorSize.tab,
indicatorWeight: 3.0,
unselectedLabelColor: Colors.white,
labelColor: Colors.white,
isScrollable: true,
tabs: [
Tab(
icon: Icon(Icons.movie),
text: "Movies",
),
Tab(
icon: Icon(Icons.tv),
text: "TV Shows",
)
]),
titleSpacing: 0.0,
),
body: ListView(
children: <Widget>[
NowPlayingMovies(),
BestMovie(),
],
),
);
}
}
任何形式的 help/tip/guide 都很棒。提前致谢
您的问题的解决方案就在错误文本中
When creating a TabBar, you must either provide an explicit TabController using the "controller" property, or you must ensure that there is a DefaultTabController above the TabBar.
因此,最简单的解决方案是用 DefaultTabController
包装您的 TabBar
。由于您正在使用 AppBar
的 bottom
属性 需要 PreferredSizeWidget
,因此您还需要将其全部包装在实现它的东西中(因为它是抽象的 class) - 这里最简单的解决方案是只使用 PreferredSize
。完整示例可能如下所示:
AppBar(
bottom: PreferredSize(
// Set whatever size you want - this is a good default one
preferredSize: Size.fromHeight(kToolbarHeight),
child: DefaultTabController(
length: 2,
child: TabBar(
tabs: [
Tab(
text: 'Movies',
),
Tab(
text: 'TV Shows',
),
],
),
),
),
),
错误日志有时非常冗长,但这是关键信息:
When creating a TabBar, you must either provide an explicit TabController using the "controller" property, or you must ensure that there is a DefaultTabController above the TabBar. In this case, there was neither an explicit controller nor a default controller.
您只需将 Scaffold
小部件包裹在 DefaultTabController
中,并为其指定与您拥有的选项卡数量相对应的长度。对于更复杂的行为,您可以初始化 ScrollController
并将其添加到 TabBar
和 TabBarView
.
controller:
参数中
我还注意到示例中有一个 ListView
包含两个选项卡小部件。这行不通,换成 TabBarView
.