将底部 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。由于您正在使用 AppBarbottom 属性 需要 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 并将其添加到 TabBarTabBarView.

controller: 参数中

我还注意到示例中有一个 ListView 包含两个选项卡小部件。这行不通,换成 TabBarView.