flutter Tabbar

这篇博客介绍了两种在Flutter中实现底部导航栏切换页面的方法。第一种使用IndexedStack,不带过渡动画,通过BottomNavigationBar切换不同页面。第二种方法利用PageView,提供页面间平滑过渡的动画效果。同时,博主还实现了监听安卓返回键的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法一(不带过度动画,IndexedStack方式)

// An highlighted block

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
//引入3页
import './car_page.dart';
import './my_page.dart';
import './index_page.dart';

class HomePage extends StatefulWidget{
    @override
    _HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>{
     //这是监听安卓的返回键操作
    Future<bool> _onWillPop() {
        return showDialog(
            context: context,
            builder: (context) => new AlertDialog(
                title: new Text('退出App?'),
                content: new Text('Do you want to exit an App'),
                actions: <Widget>[
                    new FlatButton(
                        onPressed: () => Navigator.of(context).pop(false),
                        child: new Text('不'),
                    ),
                    new FlatButton(
                        onPressed: () async {
                            await pop();
                        },
                        child: new Text('是的'),
                    ),
                ],
            ),
        ) ?? false;
    }

    static Future<void> pop() async {
        await SystemChannels.platform.invokeMethod('SystemNavigator.pop');
    }


    final List<BottomNavigationBarItem> bottomTabs = [
        BottomNavigationBarItem(
            icon: Icon(CupertinoIcons.home),
            title: Text("首页")
        ),
        BottomNavigationBarItem(
            icon: Icon(CupertinoIcons.search),
            title: Text("备用")
        ),
        BottomNavigationBarItem(
            icon: Icon(CupertinoIcons.profile_circled),
            title: Text("我的")
        )
    ];

    final List<Widget> tabBodies = [
        IndexPage(),
        CarPage(),
        MyPage(),
    ];


    int currentIndex = 0;
    var currenPage;
    @override
    void initState(){
        currenPage = tabBodies[currentIndex];
        super.initState();
    }

    @override
    Widget build(BuildContext context){
        return WillPopScope(
            onWillPop: _onWillPop,
            child: Container(
                child: Scaffold(
                    bottomNavigationBar: BottomNavigationBar(
                        type: BottomNavigationBarType.fixed,
                        currentIndex: currentIndex,
                        items: bottomTabs,
                        onTap: (index){
                            setState(() {
                                currentIndex = index;
                                currenPage = tabBodies[currentIndex];
                            });
                        },
                    ),
                    body: IndexedStack(
                        index: currentIndex,
                        children: tabBodies,
                    ),
                ),
            )
        );
    }
}

方法二(带过度动画,PageView方式)


import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

//引入3个切换的页面
import './car_page.dart';
import './my_page.dart';
import './index_page.dart';

class HomePage extends StatefulWidget{
    @override
    _HomePageState createState() => _HomePageState();
}
//要混入SingleTickerProviderStateMixin
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin{
    //这是监听安卓的返回键操作
    Future<bool> _onWillPop() {
        return showDialog(
            context: context,
            builder: (context) => new AlertDialog(
                title: new Text('退出App?'),
                content: new Text('Do you want to exit an App'),
                actions: <Widget>[
                    new FlatButton(
                        onPressed: () => Navigator.of(context).pop(false),
                        child: new Text('不'),
                    ),
                    new FlatButton(
                        onPressed: () async {
                            await pop();
                        },
                        child: new Text('是的'),
                    ),
                ],
            ),
        ) ?? false;
    }

    static Future<void> pop() async {
        await SystemChannels.platform.invokeMethod('SystemNavigator.pop');
    }

    //建立下面三个按钮数组
    final List<BottomNavigationBarItem> bottomTabs = [
        BottomNavigationBarItem(
            icon: Icon(CupertinoIcons.home),
            title: Text("首页")
        ),
        BottomNavigationBarItem(
            icon: Icon(CupertinoIcons.search),
            title: Text("备用")
        ),
        BottomNavigationBarItem(
            icon: Icon(CupertinoIcons.profile_circled),
            title: Text("我的")
        )
    ];
    //把3个页面排成数组形式方便切换
    final List<Widget> tabBodies = [
        IndexPage(),
        CarPage(),
        MyPage(),
    ];


    int currentIndex = 0;
    //创建页面控制器
    var _pageController;
    @override
    void initState(){
        //页面控制器初始化
        _pageController = new PageController(initialPage : 0);
        super.initState();
    }

    @override
    Widget build(BuildContext context){
        //WillPopScope监听安卓返回键
        return WillPopScope(
            onWillPop: _onWillPop,
            child: Container(
                child: Scaffold(
                    bottomNavigationBar: BottomNavigationBar(
                        type: BottomNavigationBarType.fixed,
                        currentIndex: currentIndex,
                        items: bottomTabs,
                        onTap: (index){
                            setState(() {
                                currentIndex = index;
                            });
                            //点击下面tabbar的时候执行动画跳转方法
                            _pageController.animateToPage(index, duration: new Duration(milliseconds: 500),curve:new ElasticOutCurve(4));
                        },
                    ),
                    body: PageView(
                        controller: _pageController,
                        children: tabBodies,
                        onPageChanged: (index){
                           currentIndex = index;
                        },
                    ),
                ),
            )
        ); 
    }
}


### Flutter TabBar 使用教程 #### 什么是 TabBar? `TabBar` 是 Flutter 中用于创建标签栏的一个重要组件。它通常与 `AppBar` 和 `TabBarView` 配合使用,提供一种直观的方式来切换不同的视图或页面[^1]。 #### TabBar 的基本结构 以下是 `TabBar` 组件的基本组成部分及其常见属性: - **tabs**: 定义显示的选项卡列表。 - **controller**: 可选参数,指定一个 `TabController` 来控制当前活动的选项卡。 - **isScrollable**: 如果设置为 true,则允许水平滚动以适应更多选项卡。 - **indicatorColor** 和 **labelColor**: 设置指示器和文字的颜色。 下面是一个简单的例子展示如何配置 `TabBar`: ```dart import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: DefaultTabController( length: 3, child: Scaffold( appBar: AppBar( bottom: TabBar( tabs: [ Tab(icon: Icon(Icons.home)), Tab(icon: Icon(Icons.search)), Tab(icon: Icon(Icons.person)), ], ), title: Text('Tabs Demo'), ), body: TabBarView( children: [ Center(child: Text("Home")), Center(child: Text("Search")), Center(child: Text("Profile")), ], ), ), ), ); } } ``` 此代码片段展示了如何通过 `DefaultTabController` 创建三个选项卡,并分别关联到对应的子视图[^4]。 #### 自定义 TabBar 除了默认样式外,还可以进一步定制 `TabBar` 外观。例如调整字体大小、颜色以及背景色等。以下是如何修改这些特性的示例: ```dart TabBar( labelStyle: TextStyle(fontSize: 18), // 文字风格 unselectedLabelColor: Colors.grey, // 未选中的标签颜色 indicatorSize: TabBarIndicatorSize.label, // 指示器尺寸模式 indicatorPadding: EdgeInsets.all(5), // 指示器填充 tabs: [...], ); ``` 上述代码中提到的各种属性可以用来增强用户体验并满足设计需求[^2]。 #### 解决常见的问题 当实际开发过程中遇到一些典型挑战时,可尝试如下解决方案: - **无法保持状态不变:** 当快速切换多个 tab 导致重建 widget 树从而丢失数据时,可以通过包裹一层 `AutomaticKeepAliveClientMixin` 或者利用第三方插件来保存状态。 - **动态更新 Tabs 数量或者内容:** 应该重新构建整个 `TabBar` 并通知其控制器刷新界面[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值