Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I have a TabView with variable height content within a Scrollable View with Flutter?

Tags:

flutter

dart

I have a TabBar & TabBarView nested within a Block. This is because the content inside the TabBarView is dynamic and the height of the content is not known until runtime.

I cannot nest the Block inside the TabBarView because there is content preceding the TabBar that should scroll along with the TabBarView content.

Diagram:

Layout Diagram

Code:

new DefaultTabController(
  length: 3,
  child: new Block(
    children: [
      new Container(
        height: 200.0,
        decoration: new BoxDecoration(
          backgroundColor: Colors.blue[500],
        ),
      ),
      new TabBar(
        tabs: <Widget>[
          new Tab(text: '1'),
          new Tab(text: '2'),
          new Tab(text: '3'),
        ],
      ),
      new TabBarView(
        children: [
          new Text('one'),
          new Text('two'),
          new Text('three'),
        ],
      ),
    ],
  )
);

However, a TabBarView's Viewport is not constrained and requires an ancestor widget with a bounded height constraint. Unfortunately a Block does not give a bounded height because its scrollable nature.

I receive this error when running the layout:

══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY    ╞═════════════════════════════════════════════════════════
I/flutter (28715): The following assertion was thrown during   performLayout():
I/flutter (28715): RenderList object was given an infinite size during layout.
I/flutter (28715): This probably means that it is a render object that tries to be as big as possible, but it was put
I/flutter (28715): inside another render object that allows its children to pick their own size.
I/flutter (28715): The nearest ancestor providing an unbounded height constraint is: ...

Any ideas on how to best approach this?

like image 993
Dvdwasibi Avatar asked Jan 30 '17 19:01

Dvdwasibi


People also ask

How do I make my TabBar scrollable?

If you set the tab bar's width and the scroll view's contentSize appropriately, the tab bar will be scrollable. You will probably want to turn off bouncing and scroll indicators.

How to create Tab bar in Flutter?

You can create tabs using the TabBar widget. In this example, create a TabBar with three Tab widgets and place it within an AppBar . return MaterialApp( home: DefaultTabController( length: 3, child: Scaffold( appBar: AppBar( bottom: const TabBar( tabs: [ Tab(icon: Icon(Icons. directions_car)), Tab(icon: Icon(Icons.


1 Answers

I don't know what is the block (the link is not working anymore). But as I see from the question, you need to put TableView inside some scrollable component.

The easiest solution is to use tab controller + container instead of TabView Widget.

enter image description here

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

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;
  int _tabIndex = 0;

  @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(() {
        _tabIndex = _tabController.index;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        children: <Widget>[
          Container(
            height: 120,
            child: Center(
              child: Text('something on top'),
            ),
          ),

          TabBar(
            controller: _tabController,
            labelColor: Colors.redAccent,
            isScrollable: true,
            tabs: myTabs,
          ),
          Center(
            child: [
              Text('second tab'),
              Column(
                children: List.generate(20, (index) => Text('line: $index')).toList(),
              ),
              Text('third tab')
            ][_tabIndex],
          ),
          Container(child: Text('another component')),
        ],
      ),
    );
  }
}
like image 54
Kherel Avatar answered Oct 18 '22 16:10

Kherel