Flutter系列(四)底部导航+顶部导航+图文列表完整代码

一、背景

          目前市场上绝大部分App的布局结构基本统一:底部导航+顶部导航,底部导航页里嵌套顶部导航栏,顶部导航页里嵌套图文列表展示信息,可以使用于各种行业。这种风格简洁清晰,便于用户阅读。本文将实现这种布局结构,力求代码简洁化容易理解。

二、演示效果

Flutter系列(四)底部导航+顶部导航+图文列表完整代码_第1张图片

三、组件设计

Flutter系列(四)底部导航+顶部导航+图文列表完整代码_第2张图片

设计说明:

1.底部导航:TabBar 组件

官方文档:使用 tabs - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter

2.顶部导航:BottomNavigationBar 组件

3.图文列表:ListView 组件

更多实用教程:实用教程 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter

四、完整代码

代码工程结构:

Flutter系列(四)底部导航+顶部导航+图文列表完整代码_第3张图片

 

1)启动页:main.dart

import 'package:flutter/material.dart';
import 'package:flutter_play/bottomNavigationBar.dart';

/*启动页*/
void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(), //主题
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State createState() => _MyHomePageState();
}

class _MyHomePageState extends State {

  int _bottomNavigationIndex = 0;  //底部导航的索引

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: pages[_bottomNavigationIndex], //页面切换
        bottomNavigationBar: _bottomNavigationBar()  //底部导航
    );
  }

  //底部导航-样式
  BottomNavigationBar _bottomNavigationBar(){
    return BottomNavigationBar(
      items: items(), //底部导航-图标和文字的定义,封装到函数里
      currentIndex: _bottomNavigationIndex,
      onTap: (flag) {
        setState(() {
          _bottomNavigationIndex = flag;  //使用底部导航索引
        });
      }, //onTap 点击切换页面
      fixedColor: Colors.blue,  //样式:图标选中时的颜色:蓝色
      type: BottomNavigationBarType.fixed, //样式:选中图标后的样式是固定的
    );
  }

}

2)底部导航页:bottomNavigationBar.dart

import 'package:flutter/material.dart';
import 'package:flutter_play/index.dart';
import 'package:flutter_play/find.dart';
import 'package:flutter_play/shop.dart';
import 'package:flutter_play/home.dart';

//底部导航页-切换页面
final pages = [
  IndexPage(), //首页
  FindPage(), //发现页
  ShopPage(), //商城页
  HomePage()  //个人主页
];

//底部导航-图标和文字定义
List items(){
  return [
    const BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: '首页',
    ),
    const BottomNavigationBarItem(
      icon: Icon(Icons.find_in_page),
      label: '发现',
    ),
    const BottomNavigationBarItem(
      icon: Icon(Icons.shop),
      label: '商城',
    ),
    const BottomNavigationBarItem(
      icon: Icon(Icons.local_activity),
      label: '我的',
    ),
  ];
}

3)顶部导航栏:index.dart (首页)  嵌套顶部导航布局

import 'package:flutter/material.dart';
import 'package:flutter_play/recommend.dart';

/*首页
* 嵌入:顶部导航栏 TabBar
* 导航栏嵌入:图文列表 ListView
* */
class IndexPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            bottom: const TabBar(
              tabs: [
                Tab(text: '推荐'),
                Tab(text: '资讯'),
                Tab(text: '科技'),
              ],
            ),
          ),
          body: TabBarView(
            children: [
              RecommendPage(),  // 推荐页(内部嵌套ListView)
              const Icon(Icons.directions_transit),
              const Icon(Icons.directions_bike),
            ],
          ),
        ),
      ),
    );
  }
}

4)图文列表页:  recommend.dart  (推荐页)

import 'package:flutter/material.dart';

/*推荐页*/
class RecommendPage extends StatelessWidget {

  final List items = List.generate(50, (i) => '标题 $i');

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ListView.builder(
          itemCount: items.length,
          // prototypeItem 计算预加载需要的空间,内容和下面的ListTile相同
          prototypeItem: ListTile(
            title: Text(items.first),
            subtitle: Text(items.first),
            trailing: Image.asset('images/mobile.jpg',
              fit: BoxFit.fill,
              width: 128,
              height: 64),
          ),
          itemBuilder: (context, index) {
            // ListTile 实际展示的列表内容
            return ListTile(
              title: Text(items[index]),  //大标题
              subtitle: Text(items[index]),  //小标题
              trailing: Image.asset('images/mobile.jpg',
                  fit: BoxFit.fill,
                  width: 64,
                  height: 64),
            );
          },
        ),
      ),
    );
  }

}

图片显示的组件:Image

这里采用加载本地图片的方式

注意:需要添加配置 和 创建文件夹放图片

配置:pubspec.yaml  添加内容如下图

Flutter系列(四)底部导航+顶部导航+图文列表完整代码_第4张图片

 在项目根目录新建文件夹images放图片,和lib目录是同级的,在上面代码工程架构图里有展示

5)其他页(发现页、商城页、个人主页)还未实现,先占上布局

发现页:find.dart

import 'package:flutter/material.dart';

/*发现页*/
class FindPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
          body: Text('发现'),
      ),
    );
  }

}

商城页:shop.dart

import 'package:flutter/material.dart';

/*商城页*/
class ShopPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
          body: Text('商城'),
      ),
    );
  }

}

个人主页:home.dart

import 'package:flutter/material.dart';

/*个人主页*/
class HomePage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
          body: Text('个人主页'),
      ),
    );
  }

}

END...

以上是完整代码,代码上加了注释易于大家理解。避免篇幅过长,组件的详细解析会在后续章节展开描述,便于大家灵活使用组件。

你可能感兴趣的:(flutter,flutter,android)