TabView在ListView中具有可变高度

Dan*_*pie 5 flutter

我有一个具有多种类型的项目的ListView,其中之一是TabBar和TabBarView的小部件。
问题是每个选项卡页面的高度都不同,我希望ListView根据其高度动态包装选项卡小部件
像这样
但是TabBarView不接受无限的高度,并且ListView不能为其子级提供高度。
无论如何,这可以做到吗?还是我必须将TabBar与可以包裹其内容(例如列)的东西一起使用,并牺牲在选项卡之间滑动的能力?

Khe*_*rel 25

您不需要使用 TabView 来显示 Tabs 内容。这种方法的缺点是你正在失去动画和滑动,所以如果你真的需要它,你需要自己做。

在此处输入图片说明

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  final List<Widget> myTabs = [
    Tab(text: 'one'),
    Tab(text: 'two'),
    Tab(text: 'three'),
  ];

  TabController _tabController;

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

  @override
  void initState() {
    _tabController = TabController(length: 3, vsync: this);
    _tabController.addListener(_handleTabSelection);
    super.initState();
  }

  _handleTabSelection() {
    if (_tabController.indexIsChanging) {
      setState(() {});
    }
  }

  _listItem() {
    return Container(
      decoration: BoxDecoration(
        border: Border.all(
          width: 1,
          color: Colors.blueAccent,
        ),
      ),
      height: 120,
      child: Center(
        child: Text('List Item', style: TextStyle(fontSize: 20.0)),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        children: <Widget>[
          _listItem(),
          TabBar(
            controller: _tabController,
            labelColor: Colors.redAccent,
            tabs: myTabs,
          ),
          Center(
            child: [
              Text('first tab'),
              Column(
                children: [
                  Text('second tab'),
                  ...List.generate(10, (index) => Text('line: $index'))
                ],
              ),
              Column(
                children: [
                  Text('third tab'),
                  ...List.generate(20, (index) => Text('line: $index'))
                ],
              ),
            ][_tabController.index],
          ),
          _listItem(),
          _listItem(),
        ],
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)


Ala*_*ana 15

不要用TabBarView,用IndexedStackwithVisibility代替。

import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  TabController tabController;
  int selectedIndex = 0;

  @override
  void initState() {
    super.initState();

    tabController = TabController(
      initialIndex: selectedIndex,
      length: 2,
      vsync: this,
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: ListView(
          children: [
            Container(
              height: 128,
              color: Colors.blue,
            ),
            Container(
              height: 256,
              color: Colors.green,
            ),
            TabBar(
              tabs: <Tab>[
                Tab(text: 'Tab Left'),
                Tab(text: 'Tab Right'),
              ],
              controller: tabController,
              onTap: (int index) {
                setState(() {
                  selectedIndex = index;
                  tabController.animateTo(index);
                });
              },
            ),
            Divider(height: 0),
            IndexedStack(
              children: <Widget>[
                Visibility(
                  child: Container(
                    height: 200,
                    color: Colors.yellow,
                    child: Center(
                      child: Text('Content left'),
                    ),
                  ),
                  maintainState: true,
                  visible: selectedIndex == 0,
                ),
                Visibility(
                  child: Container(
                    height: 1000,
                    color: Colors.red,
                    child: Center(
                      child: Text('Content right'),
                    ),
                  ),
                  maintainState: true,
                  visible: selectedIndex == 1,
                ),
              ],
              index: selectedIndex,
            ),
          ],
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

IndexedStack将根据indexwhileVisibility保持显示或隐藏视图显示来自子项列表中的单个子项。当视图隐藏时,没有多余的空白显示(堆栈高度等于其子项的最大高度)。

这是飞镖https://dartpad.dev/535f06aa01257b049c7f2f9c719c9881

  • 不要忘记 ```tabController.dispose();``` (4认同)