Flutter 11: 图解底部状态栏小尝试
小菜今天来整理一下在学习测试 Flutter 时需用到的底部导航栏 BottomNavigationBar,使用方式很简单,小菜感觉效果比原生的 Android 要好一些。
何为 BottomNavigationBar ?
BottomNavigationBar 为底部导航栏控件,可以包含文字标签和图标等基本信息,通常在三到五个之间;据了解,iOS 的规范底部导航栏最多可设置五个,所以大部分应用均在五个以内;现在很多应用都是以底部导航栏 + 中部主内容 Content 方式来展示。
官网建议,BottomNavigationBar 底部导航栏通常与 Scaffold 一起使用,其中它作为Scaffold.bottomNavigationBar 参数提供。
如何应用 BottomNavigationBar ?
- 与 body 同级的位置添加 BottomNavigationBar,BottomNavigationBarItem 中可以添加文字标签或图标 (Icons/Image) 等,若图片不存在时会显示空白;这样就可以添加底部状态栏内容,文字和图标的样式也可以随意调整;如下:
bottomNavigationBar: new BottomNavigationBar( type: BottomNavigationBarType.fixed, items: [ BottomNavigationBarItem( icon: new Icon(Icons.category), title: new Text('签到')), BottomNavigationBarItem( icon: new Icon(Icons.account_circle), title: new Text('我')), ], ),
- 只有底部状态栏是不够的,还需要对应的中间展示内容块,可以跟 Android 的思路一样,添加几个 Page() 页作为 Fragment,小菜因为测试内容相对简单,尝试使用了 PageView,即对应 Android 中的 ViewPager,小菜会在今后的测试中详细说明,今天主要是使用基本方法展示主模块内容;如下:
body: new PageView.builder( itemBuilder: (BuildContext context, int index) { var str = (index == 0) ? "这里是【HomePage】->【签到】页面" : "这里是【HomePage】->【我】页面"; return new Center( child: new Container( width: 340.0, child: new Card( color: Colors.blue, elevation: 16.0, child: new FlatButton( child: new Text(str, style: new TextStyle(color: Colors.white)), )), )); }, itemCount: 2, ),
- 此时主模块 PageView 可以滑动切换内容,但是对应的底部状态栏不会变化;因为目前没有绑定对应的点击事件等;此时需要添加 PageController 和 状态栏的 onTap 点击事件;如下:
int _currentIndex = 0; var _pageController = new PageController(initialPage: 0); void _pageChange(int index) { if (_currentIndex != index) { _currentIndex = index; } } // 添加 PageView 的 PageController body: new PageView.builder( onPageChanged: _pageChange, controller: _pageController, itemBuilder: (BuildContext context, int index) { ... } ), // 添加 BottomNavigationBar 的 onTap bottomNavigationBar: new BottomNavigationBar( type: BottomNavigationBarType.fixed, items: [ ... ], //设置当前的索引 currentIndex: _currentIndex, //tabBottom的点击监听 onTap: (int index) { _pageController.animateToPage(index, duration: new Duration(seconds: 2), curve: new ElasticOutCurve(0.8)); _pageChange(index); _currentIndex = index; }, ),
- 此时,点击底部状态栏对应的 PageView 会切换内容,但是底部状态栏并没有改变样式,因为目前用的时固定的图标和文字,此时需要处理图标和文字切换时的样式,如下:
var _bottomText = ['签到', '我']; var _bottomIcons = [ [ new Icon(Icons.category, color: Colors.grey), new Icon(Icons.category, color: Colors.blue), ], [ new Icon(Icons.account_circle, color: Colors.grey), new Icon(Icons.account_circle, color: Colors.blue), ] ]; Icon changeIconStyle(int curIndex) { if (curIndex == _currentIndex) { return _bottomIcons[curIndex][1]; } return _bottomIcons[curIndex][0]; } Text changeTextStyle(int curIndex) { if (curIndex == _currentIndex) { return new Text(_bottomText[curIndex], style: new TextStyle(color: Colors.blue)); } else { return new Text(_bottomText[curIndex], style: new TextStyle(color: Colors.grey)); } } bottomNavigationBar: new BottomNavigationBar( type: BottomNavigationBarType.fixed, items: [ new BottomNavigationBarItem( icon: changeIconStyle(0), title: changeTextStyle(0)), new BottomNavigationBarItem( icon: changeIconStyle(1), title: changeTextStyle(1)), ], ... ),
- 然而小菜添加了更改状态时的样式,点击底部状态栏时依旧不会变色;小菜查了很久突然发现,小菜的 HomePage() 继承的是 StatelessWidget 无状态样式,此时更换为 StatefulWidget 有状态样式,并实现对应方法;如下:
class HomePage extends StatefulWidget { String result; HomePage(this.result); @override State<StatefulWidget> createState() { // TODO: implement createState return new HomePageState(); } } class HomePageState extends State<HomePage> { int _currentIndex = 0; ... }
至此,底部状态栏 BottomNavigationBar 配合滑动 PageView 的基本功能已经完成。
实用小贴士
- 通过点击 BottomNavigationBar 对 PageView 切换过程中,可以设置动画过程,也可以直接跳转到对应页面,需要设置 animateToPage 或 jumpToPage;如下:
onTap: (int index) { // 切换时没有动画效果 // _pageController.jumpToPage(index); // 切换时添加动画效果 _pageController.animateToPage(index, duration: new Duration(seconds: 2), curve: new ElasticOutCurve(0.8)); _pageChange(index); _currentIndex = index; },
- BottomNavigationBar 有两种样式分别为 shifting 和 fixed;直接效果图,shifting 样式时会突出显示选中的 item,其他的 item 文字隐藏;fixed 样式均分,没有突出效果;如下:
type: BottomNavigationBarType.shifting,
type: BottomNavigationBarType.fixed,
小菜刚接触 Flutter 时间不长,还有很多不清楚和不理解的地方,如果又不对的地方还希望多多指出。以下是小菜公众号,欢迎闲来吐槽~
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
关闭读写SD卡权限后的应用适配问题
今天在做SD卡的代码优化的工作。之前公司的应用是在MainActivity中申请读写SD卡权限,如果用户选择了拒绝,那么直接弹窗提示用户必须赋予SD卡读写权限,否则将直接退出应用。虽然微信等app都是这样的逻辑,但是还是觉得很不友好。在如今这个Android手机的大环境中,SD读写权限没有那么十分严重。 因此,我们将对这里的逻辑进行改造。 1. Android中的内部存储与外部存储 Android SD卡主要有两种存储方式 Internal 、 External Storage Internal内部存储,应用私有目录 这个目录的特点是: 内部存储不需要申请任何权限 这个目录始终可用,这个文件夹用于 App 中的 WebView 缓存页面信息,SharedPreferences 和 SQLiteDatabase 持久化应用相关数据等。 当用户卸载 App 时,系统自动删除 data/data 目录下对应包名的文件夹及其内容。 对于没有root的手机是没办法看到data/data目录的,但是我们可以通过Androidstudio提供的Device File Explorer来查看。 Ext...
- 下一篇
理解Activity的启动模式
Activity的启动模式有哪几种,分别用于什么场景? standard:标准模式 系统的默认模式。一种典型的多实例实现。每次启动一个Activity都会重新创建一个新的实例。被启动的Activity会被放入启动者的栈中,如果启动者是非Activity类型的Context(如ApplicationContext),并没有所谓的任务栈,就会报错,此时需为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,创建一个新栈。没有特殊需求默认是这种模式。 singleTop:栈顶复用模式 如果一个Activity的实例已经在栈顶存在,启动这个Activity时,不会创建新的Activity,而会回调onNewIntent(),如果不是在栈顶存在,则会新建一个实例。 适合接收通知启动的内容显示页面。当收到多条新闻推送时,用于展示新闻的Activity设置成此模式,根据传来的intent数据显示不同的新闻信息,不会启动多个Activity。 singleTask:栈内复用模式 一个单实例模式。只要Activity的实例在一个栈中存在,再次启动Activity都不会重新创建...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长