写点什么

Flutter 构建常见的 App 页面框架

作者:岛上码农
  • 2022 年 3 月 08 日
  • 本文字数:2791 字

    阅读完需:约 9 分钟

Flutter 构建常见的App页面框架

大多数 App 中都会有底部导航栏,通过底部导航栏切换实现不同页面之间的切换。在 Flutter 中提供了BottomNavigationBar组件实现底部导航。本篇介绍通过BottomNavigationBarIndexedStack构建最为常见的 App 页面框架。



最终实现的结果如上图所示,顶部共用一个导航栏,底部有四个图标导航,点击对应的图标跳转到对应的页面。

图标准备

本次例程需要 4 个图标,2 种颜色,可以从 iconfont 中找到自己需要的图标下载不同的颜色使用。然后在 pubspec.yaml 中的 assets 指定素材所在目录。需要注意的是如果是 png 文件直接指定整个目录即可,但如果是 jpg 格式,则需要同时指定文件名及后缀。

BottomNavigationBar 简介

BottomNavigationBar的构造函数如下:


BottomNavigationBar({    Key? key,    required this.items,    this.onTap,    this.currentIndex = 0,    this.elevation,    this.type,    Color? fixedColor,    this.backgroundColor,    this.iconSize = 24.0,    Color? selectedItemColor,    this.unselectedItemColor,    this.selectedIconTheme,    this.unselectedIconTheme,    this.selectedFontSize = 14.0,    this.unselectedFontSize = 12.0,    this.selectedLabelStyle,    this.unselectedLabelStyle,    this.showSelectedLabels,    this.showUnselectedLabels,    this.mouseCursor,  })
复制代码


其中常用的属性为:


  • items:及对应的页面组件数组

  • currentIndex:默认显示第几个页面

  • type:组件类型,使用BottomNavigationBarType枚举,有fixedshifting两种。fixed 是图标固定位置,而shifting的图标点击后会有一个漂移效果,可以实际试一下,一般用fixed比较多。

  • onTap:点击后的事件,一般用这个更新状态数据,以便更新页面。


其他属性用于控制样式的,可以根据实际需要设置图标大小,主题色,字体等参数。

构建项目页面结构

首先,新建四个业务页面,分别是 dynamic.dartmessage.dartcategory.dartmine.dart,分别对应动态、消息、分类浏览和个人中心四个页面。目前这四个页面很简单,只是在页面中间依次显示“岛上码农”四个字。代码都是类似的,以dynamic为例:


import 'package:flutter/material.dart';
class DynamicPage extends StatelessWidget { const DynamicPage({Key key}) : super(key: key);
@override Widget build(BuildContext context) { return Scaffold( body: Center( child: Text('岛'), ), ); }}
复制代码


注意的是这里的Scaffold没有AppBar了,这是因为在首页已经有了,如果再有AppBar就会出现两个,当然也可以把首页的去掉,每个页面使用自己的AppBar,这样可以每个页面的都不一样。。


其次,新建首页,用于管理四个业务页面,命名为 app.dartapp.dart 使用了 BottomNavigationBar 管理四个业务页面的切换。


import 'package:flutter/material.dart';import 'dynamic.dart';import 'message.dart';import 'category.dart';import 'mine.dart';
class AppHomePage extends StatefulWidget { AppHomePage({Key key}) : super(key: key);
@override _AppHomePageState createState() => _AppHomePageState();}
class _AppHomePageState extends State<AppHomePage> { int _index = 0;
List<Widget> _homeWidgets = [ DynamicPage(), MessagePage(), CategoryPage(), MinePage(), ];
void _onBottomNagigationBarTapped(index) { setState(() { _index = index; }); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('岛上码农'), ), body: IndexedStack( index: _index, children: _homeWidgets, ), bottomNavigationBar: BottomNavigationBar( type: BottomNavigationBarType.fixed, currentIndex: _index, onTap: _onBottomNagigationBarTapped, items: [ _getBottomNavItem( '动态', 'images/dynamic.png', 'images/dynamic-hover.png', 0), _getBottomNavItem( ' 消息', 'images/message.png', 'images/message-hover.png', 1), _getBottomNavItem( '分类浏览', 'images/category.png', 'images/category-hover.png', 2), _getBottomNavItem( '个人中心', 'images/mine.png', 'images/mine-hover.png', 3), ], ), ); }
BottomNavigationBarItem _getBottomNavItem( String title, String normalIcon, String pressedIcon, int index) { return BottomNavigationBarItem( icon: _index == index ? Image.asset( pressedIcon, width: 32, height: 28, ) : Image.asset( normalIcon, width: 32, height: 28, ), label: title, ); }}
复制代码


这里关键的地方有两个,一是使用的IndexedStack,这是一个管理页面显示层级的容器。使用index属性确定当前容器里那个页面在最顶上,容器里的页面通过children 属性设置,要求是一个Widget数组。因此,逻辑就是当BottomNavigationBar中的图标被点击后,对应点击事件会回调onTap属性指定的方法,将当前的点击索引值传递回调函数,因此可以利用这个方式控制IndexedStack的页面层级切换。


最后,使用了状态变量_index存储IndexedStatck当前显示页面的索引值,然后当BottomNavigationBar的图标点击事件发生后,在回调函数中使用 setState 更新状态变量_index 来刷新当前界面。

简化入口

main.dart是入口文件,应当做最基础的配置和全局初始化配置,而不应该有业务代码,因此可以简化为从main方法加载首页即可。通过这种方式可以让 main.dart 文件即为简洁。这也是在开发的时候需要注意的地方,将不相关的代码剥离,相关的代码聚合,即所谓的“高内聚,低耦合”原则。


import 'package:flutter/material.dart';import 'app.dart';
void main() { runApp(MyApp());}
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'App 框架', theme: ThemeData( primarySwatch: Colors.blue, ), home: AppHomePage(), ); }}
复制代码

代码复用

写代码的时候要注意复用,在这里将构建 BottomNavigationBar 元素抽离出了一个构建方法_getBottomNavItem,从而提高代码的复用性和维护性,也可以避免 Flutter 的组件构建的 build 方法中出现过多的元素和嵌套,影响代码的可读性。


发布于: 刚刚阅读数: 2
用户头像

岛上码农

关注

用代码连接孤岛 2022.03.03 加入

从南漂到北,从北漂到南的业余码农

评论

发布
暂无评论
Flutter 构建常见的App页面框架_flutter_岛上码农_InfoQ写作平台