[Flutter-29]Tabbar 实现

Tabbar 实现

  • Scaffold 里有bottomNavigationBar属性,直接在这里设置即可.
  • 通过IndexedStack 来设置切换的tab下的页面
  • BottomNavigationBar 下的type, 如果tab数量 >= 4, 必须设置为Fixed, 不如出现底部一片白
  • 具体代码实现如下:

1. main.dart

import 'package:flutter/material.dart';
import 'package:flutter_tabbar/Social.dart';
import 'package:flutter_tabbar/home.dart';
import 'package:flutter_tabbar/mall.dart';
import 'package:flutter_tabbar/user.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '首页',
      // theme: ThemeData.dark(),
      home: Content(),
    );
  }
}

class Content extends StatefulWidget {
  @override
  _ContentState createState() => _ContentState();
}

class _ContentState extends State<Content> {
  var _selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Tabbar'),
        backgroundColor: Colors.teal[900],
        brightness: Brightness.dark,
      ),
      bottomNavigationBar: _createBottomNavigationBarWidget(),
      body: new IndexedStack(
        index: _selectedIndex,
        children: [
          HomePage(),
          MallPage(),
          SocialPage(),
          UserPage(),
        ],
      ),
    );
  }

  _createBottomNavigationBarWidget() {
    return BottomNavigationBar(
      type: BottomNavigationBarType.fixed, // 超过4个必须设置fixed,否则底部一片白
      currentIndex: _selectedIndex,
      onTap: (index) {
        if (_selectedIndex == index) return;
        setState(() {
          _selectedIndex = index;
        });
        print('index: $index');
      },
      items: [
        _createItem(Icon(Icons.home), '首页'),
        _createItem(Icon(Icons.local_mall), '商城'),
        _createItem(Icon(Icons.social_distance), '社交'),
        _createItem(Icon(Icons.person), '我的'),
      ],
    );
  }

  BottomNavigationBarItem _createItem(Widget iconData, String labelTitle) {
    return BottomNavigationBarItem(icon: iconData, label: labelTitle);
  }
}

2. home.dart

import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView.separated(
      itemBuilder: (BuildContext context, int index) {
        return ListTile(
          // tileColor: Colors.grey[200], // 如果设置背景色、请包裹一层Container设置decoration即可.
          title: Text('item$index'),
          subtitle: Text('description$index'),
          leading: Icon(Icons.phone, size: 30),
        );
      },
      separatorBuilder: (BuildContext context, int index) {
        return Divider(
          color: Colors.grey[350],
        );
      },
      itemCount: 20,
    );
  }
}

3. mall.dart

import 'package:flutter/material.dart';

class MallPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GridView.builder(
      padding: EdgeInsets.all(10),
      itemCount: 31,
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 3,
        mainAxisSpacing: 10,
        crossAxisSpacing: 10,
        childAspectRatio: 1.0,
      ),
      itemBuilder: (BuildContext context, int index) {
        return Container(
          color: Colors.grey[300],
          alignment: Alignment(0, 0),
          child: Text('item$index'),
        );
      },
    );
  }
}

4. social.dart

import 'package:flutter/material.dart';

class SocialPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView.separated(
      itemCount: 15,
      separatorBuilder: (BuildContext context, int index) {
        return Divider(
          color: Colors.grey[400],
          height: 1,
        );
      },
      itemBuilder: (BuildContext context, int index) {
        return Container(
          height: 400,
          alignment: Alignment(0, 0),
          color: Colors.grey[200],
          child: Text('item$index'),
        );
      },
    );
  }
}

5. user.dart

import 'package:flutter/material.dart';

class UserPage extends StatelessWidget {
  final List<String> leftTitles = ['用户订单', '用户收藏', '个人中心', '清除缓存', '退出登录'];
  final List<IconData?> leftIcons = [
    Icons.local_mall,
    Icons.save,
    Icons.center_focus_strong,
    Icons.cached,
    Icons.logout,
  ];

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: [
        // HeaderView
        // https://588ku.com/tuku/kejixiantiao.html
        // https://tva1.sinaimg.cn/large/006y8mN6gy1g72j6nk1d4j30u00k0n0j.jpg
        SliverAppBar(
          expandedHeight: 250,
          flexibleSpace: FlexibleSpaceBar(
            title: Text('Wike Spiken'),
            background: Image(
              image: NetworkImage('https://588ku.com/tuku/kejixiantiao.html'),
              fit: BoxFit.cover,
            ),
          ),
        ),
        // ListView
        SliverFixedExtentList(
          delegate: SliverChildBuilderDelegate(
            (BuildContext context, int index) {
              return _getSliverFixedExtentListWidget(context, index);
            },
            childCount: 5,
          ),
          itemExtent: 60,
        ),
      ],
    );
  }

/* // ListTile无法设置分割线、只能自定义.
  _getListTileWidget() {
    return Container(
      decoration: BoxDecoration(
        color: Colors.grey[200],
      ),
      child: ListTile(
        // tileColor: Colors.grey[200], // !!!这个设置有bug,每个tabbar页面都会出现这个颜色
        title: Text(leftTitles[index]),
        leading: Icon(leftIcons[index], size: 25),
        trailing: Icon(Icons.arrow_forward_ios, size: 15),
        minLeadingWidth: 10,
      ),
    );
  }
*/

  _getSliverFixedExtentListWidget(BuildContext context, int index) {
    return Container(
      decoration: BoxDecoration(
        color: Colors
            .grey[200], //index % 2 == 0 ? Colors.green[200] : Colors.green,
      ),
      child: Column(
        // mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Spacer(), // 尽可能大的间距
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              SizedBox(width: 20),
              Icon(leftIcons[index], size: 25),
              SizedBox(width: 10),
              Text(leftTitles[index]),
              Spacer(), // 尽可能大的间距
              Icon(Icons.arrow_forward_ios, size: 15),
              SizedBox(width: 15),
            ],
          ),
          Spacer(), // 尽可能大的间距
          // 自定义分割线
          Container(
            width: MediaQuery.of(context).size.width,
            height: 1,
            color: Colors.grey[300],
          ),
        ],
      ),
    );
  }
}
posted @ 2021-07-27 16:37  comefromchina  阅读(216)  评论(0)    收藏  举报