简体   繁体   中英

How to make full page with widgets in a TabBarView widget

I'm trying to create an app containing tabs beneath the AppBar .

appBar: AppBar(
  bottom: TabBar(
    labelColor: Color(0xFF1778f2),
    unselectedLabelColor: Colors.black87,
    indicatorColor: Color(0xFF1778f2),
    tabs: <Widget>[
      Tab(icon: Icon(Icons.home)),
    ],
  ),
),

Which works. But the problem is residing when creating its contents in a TabBarView . The documentation shows an example showing a simple Icon for each tab, and that's it. I'm trying to create many more widgets with Image , TextField , Column s, etc. But things aren't as simple as the documentation expresses it to be.

This is my HomeScreen , placed as at the top of TabBarView :

body: TabBarView(
  children: <Widget>[
    HomeScreen(),
  ,
),
class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: <Widget>[
          Row(
            children: <Widget>[
              CircleAvatar(),
              TextField(),
            ],
          );
        ],
      ),
    );
  }
}

And then, errors like

RRenderBox was not laid out: _RenderDecoration#f0d71 relayoutBoundary=up6 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE 'package:flutter/src/rendering/box.dart':

Failed assertion: line 1687 pos 12: 'hasSize'

which are many, all pointing to my HomeScreen . What's missing that the documentation doesn't show?

A screenshot with many of the errors.

在此处输入图片说明

I have a code demo as below. Your problem may be that you didn't set size for widget and set tabcontroller for tabbar and tabview . I hope that it can help you

class TabBarDemo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return TabBarDemoState();
  }
}

class TabBarDemoState extends State<TabBarDemo> with TickerProviderStateMixin {
  TabController _controller; ///<-- fixed here

  @override
  void initState() {
    super.initState();
    _controller = TabController(length: 1, vsync: this);
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        bottom: TabBar(
          controller: _controller, ///<-- fixed here
          labelColor: Color(0xFF1778f2),
          unselectedLabelColor: Colors.black87,
          indicatorColor: Color(0xFF1778f2),
          tabs: <Widget>[
            Tab(icon: Icon(Icons.home)),
          ],
        ),
        title: Text('Tabs Demo'),
      ),
      body: TabBarView(
        controller: _controller,
        children: [
          HomeScreen(),
        ],
      ),
    );
  }
}
class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Size screenSize = MediaQuery.of(context).size;
    return Container(
      height: screenSize.height, // <--fixed here
      width: screenSize.width, // <--fixed here
      child: ListView(
        children: <Widget>[
          Row(
            children: <Widget>[
              CircleAvatar(),
              Container( // <--fixed here
                width: screenSize.width / 2, // <--fixed here
                child: TextField(),
              ),// <--fixed here
            ],
          ),
        ],
      ),
    );
  }
}

It's simple. You can use any widget inside TabBarView . But to change the page according to Tab change, you have to use TabBarController or wrap with DefaultTabBarController .

Here is a bare minimal cleaner example with DefaultTabBarController :

import 'package:flutter/material.dart';

class SimpleTabBar extends StatefulWidget {
  @override
  _SimpleTabBarState createState() => _SimpleTabBarState();
}

class _SimpleTabBarState extends State<SimpleTabBar> {
  List<Widget> tabs;

  @override
  void initState() {
    tabs = [
      buildTab("Dart", Icons.favorite),
      buildTab("Flutter", Icons.thumb_up)
    ];
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      initialIndex: 0,
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          title: Text("Title"),
          bottom: buildTabBar(context),
        ),
        body: TabBarView(
          children: <Widget>[
            buildTabView(Colors.redAccent),
            buildTabView(Colors.greenAccent)
          ],
        ),
      ),
    );
  }

  Container buildTabView(Color color) {
    return Container(
      color: color,
      child: Column(
        children: List.generate(20, (index) => Text("$index")),
      ),
    );
  }

  Widget buildTab(String title, IconData icon) =>
      Column(children: <Widget>[Icon(icon), Text(title)]);

  TabBar buildTabBar(BuildContext context) => TabBar(tabs: tabs);
}

Screenshot:

在此处输入图片说明

Checkout how the rows and columns are managed inside TabBarView, The problem is with your defining TextField.

class NetworkDiagnosis extends StatefulWidget {
  @override
  _NetworkDiagnosisState createState() => _NetworkDiagnosisState();
}

class _NetworkDiagnosisState extends State<NetworkDiagnosis> {
  @override
  Widget build(BuildContext context) {
    return  DefaultTabController(
      length: 3,
      child:  Scaffold(
        appBar:  AppBar(
          title:  Text("Tabs"),
          bottom:  TabBar(
            tabs: <Widget>[
              Tab(text: 'One'),
              Tab(text: 'Two'),
              Tab(text: 'Three'),
            ],
          ),
        ),
        body:  TabBarView(
          children: <Widget>[
            Center(child:  HomeScreen()),
            Center(child:  Text('Two')),
            Center(child:  Text('Three')),
          ],
        ),
      ),
    );
  }
}


class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: <Widget>[
          Text('One'),
          Text('Two'),
          Row(
            children: <Widget>[
             Container(
               width: 300,
               height: 100,
               child:  TextField(
                 // controller: new TextEditingController(text: 'Enter data'),
                 keyboardType: TextInputType.text,
                 decoration: InputDecoration(
                     border: InputBorder.none,
                     hintText: "Enter Password",
                     hintStyle: TextStyle(fontSize: 16.0)),
               ),
             )

            ],
          )
        ],
      ),
    );
  }
}

The issue is the TextField() . It needed to be wrapped around Expanded() . Solved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM