:主页设计之顶部导航栏

Posted 因吹斯听的Sun同学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了:主页设计之顶部导航栏相关的知识,希望对你有一定的参考价值。

主页设计之顶部导航栏

前言
本篇在讲什么

本篇文章主要来制作一个导航栏,具体效果就按照下图来处理吧
本篇适合什么

适合初学Vue的小白
想了解建站的同学

本篇需要什么

html语法有简单认知
CSS语法有简单认知
Vue有简单认知
依赖VS Code编辑器

本篇的特色

具有全流程的图文教学
重实践,轻理论,快速上手
提供全流程的源码内容


★提高阅读体验★

👉 ♠ 一级标题 👈

👉 ♥ 二级标题 👈

👉 ♣ 三级标题 👈

👉 ♦ 四级标题 👈


目录


♠ 样式



♠ 新建组件

在第一章Vue-router的基础上,我们首先在components内新建一个名为NavBar的vue脚本,我们将在这个脚本内编写和顶部导航栏相关的内容


很简单的一个脚本,我们在App.vue内引用新脚本页面,然后直接显示在页面的最顶端


♠ 设计显示

首先我们要明确我们自己的需求,然后再去逐步的实现我们的需求

  • 有一个带颜色的长条框框置顶
  • 左上角有一个Logo标志
  • 右上角存放各个跳转按钮
  • 跳转按钮左侧带一个小图标样式

♥ 导航栏背景

我们先做一个上居中的长条框框,设置好背景颜色,和框线粗细

<template>
    <div>
        <div class="header">
            <!-- todo -->
        </div>
    </div>
</template>

<script>
    export default 
        name: "NavBar"
    
</script>

<style>
    .header
        display: flex;
        align-items: center;
        justify-content: space-between;
        height: 70px;
        background-color:#F0F0F0;
        color: #F0F0F0;
        border: 1px solid #2c2c2c;
    
</style>

如上述代码所示,我们做了一个名为header的的div组件,在style内给其设置了css的样式,高度、填充颜色、变现粗细等,最终得到了上图所示的效果

注意:默认下组件是没有贴顶部的,这里把App.vue下的margin-top属性删除或设置为0就好了


♥ 设置Logo的显示

我们在导航栏的左侧做一个Logo和title的显示

<template>
    <div>
        <div class="header">
            <div class="box">
                <h1>
                    <img src="../assets/logo.png">
                    <span>Sun</span>
                </h1>
            </div>
        </div>
    </div>
</template>

<script>
    export default 
        name: "NavBar"
    
</script>

<style>
    .header
        display: flex;
        align-items: center;
        justify-content: space-between;
        height: 70px;
        background-color:#F0F0F0;
        color: #F0F0F0;
        border: 1px solid #2c2c2c;
    
    .box
        display: flex;
        align-items: center;
    
    h1
        display: flex;
        align-items: center;
        font: normal 30px Cookie;
        padding: 0px 20px;
        color:#2c2c2c;
        font-family:"Microsoft YaHei";
    
</style>

如上述代码所示,我们新建了一个box的div模块,里面包含了一个h1组件,并且h1组件内包含了一张图片和一个title,在下方style设计好css的显示样式,即得到了上述图片演示的样子


♥ 制作右侧导航按钮

需求比较简单,我们不需要搜索框和其他组件,简单的图片+文字的导航按钮即可,整理下需求和资源

  • 需求

    • 个人介绍
    • 工作经历
    • 作品介绍
    • 能力介绍
  • 资源(小logo)

<template>
    <div>
        <div class="header">
            <div class="box">
                <h1>
                    <img src="../assets/logo.png" class="img_title">
                    <span>Sun</span>
                </h1>
            </div>
            <div class="box">
                <nav class="nav_link">
                    <img src="../assets/home.png" class="img_btn">
                    <router-link class="link_btn" active-class="active" to="/home">首页</router-link>
                </nav>
                <nav class="nav_link">
                    <img src="../assets/data.png" class="img_btn">
                    <router-link class="link_btn" active-class="active" to="/data">个人介绍</router-link>
                </nav>
                <nav class="nav_link">
                    <img src="../assets/work.png" class="img_btn">
                    <router-link class="link_btn" active-class="active" to="/work">作品介绍</router-link>
                </nav>
                <nav class="nav_link">
                    <img src="../assets/power.png" class="img_btn">
                    <router-link class="link_btn" active-class="active" to="/power">能力介绍</router-link>
                </nav>
            </div>
        </div>
    </div>
</template>

<script>
    export default 
        name: "NavBar"
    
</script>

<style>
    .header
        display: flex;
        align-items: center;
        justify-content: space-between;
        height: 70px;
        background-color:#ffffff;
        color: #ffffff;
        border: 1px solid #2c2c2c;
    
    .box
        display: flex;
        align-items: center;
    
    h1
        display: flex;
        align-items: center;
        font: normal 30px Cookie;
        padding: 0px 20px;
        color:#2c2c2c;
        font-family:"Microsoft YaHei";
    
    .img_title
        width: 40px;
        height: 40px;
    

    .nav_link
        display: flex;
        align-items: center;
        padding: 0 30px;
    
    .link_btn
        text-decoration:none;
        color: #7F7F7F;
        font-size: 25px;
        font-weight: normal;
    
    .img_btn
        width: 30px;
        height: 30px;
    
</style>

我们新增了一个div模块用来存放四个nav组件,该组件包含了一个图片和一个router-link组件,在css调整一下样式,就得到上图所示效果了


♠ 推送

  • Github
https://github.com/KingSun5

♠ 结语

略丑,就先这样吧,后边有空在搞搞效果吧,若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。

👉 本文属于原创文章,转载请评论留言,并在转载文章头部著名作者出处👈

一文搞定Flutter所有类型导航栏设计

概要:目前App中较为常见有三种导航栏设计,分别是底部导航栏、顶部导航栏和侧边导航栏。本文主要介绍利用Flutter实现上面三种导航栏功能。


目录:
1.  前言
2. 底部导航栏
3. 顶部导航栏
4. 侧边导航栏
5. 导航栏搜索功能
6. 总结


1


前言



Flutter中的导航栏会涉及到以下几个核心点,我整理了以下表格进行说明:


可以看到上述导航栏都是 Scaffold 的一个属性,这就类似于一个架子,架子提供了很多模块。如果我们需要某些模块,只需要按照模块的格式插入数据,就可以实现相应功能。这个控件的一些参数属性含义如下:
  
    
    
  
const Scaffold({ Key key, this.appBar, // 应用栏,显示在顶部,包括其中的搜索框 this.body, // 页面的主题显示内容 this.floatingActionButton, // 设置显示在上层区域的按钮,默认位置位于右下角 this.floatingActionButtonLocation, // 设置floatingActionButton的位置 this.floatingActionButtonAnimator, // floatingActionButton动画 this.persistentFooterButtons, // 在底部导航栏之上的一组操作按钮 this.drawer, // 左侧导航栏 this.endDrawer, // 右侧导航栏 this.bottomNavigationBar, // 底部导航栏 this.bottomSheet, // 底部可隐藏导航栏 this.backgroundColor, // 内容区域颜色 this.resizeToAvoidBottomPadding, // 是否重新布局来避免底部被覆盖了,比如当键盘显示的时候,重新布局避免被键盘盖住内容。默认值为 true。 this.resizeToAvoidBottomInset, //键盘弹出时是否重新绘制,以避免输入框被遮挡 this.primary = true, // 是否计算手机顶部状态栏的高度 this.drawerDragStartBehavior = DragStartBehavior.start, // 拖动的处理 this.extendBody = false, // 是否延伸body至底部 this.extendBodyBehindAppBar = false, // 是否延伸body至顶部 this.drawerScrimColor, // 抽屉遮罩层背景色 this.drawerEdgeDragWidth, // 滑动拉出抽屉的生效距离 this.drawerEnableOpenDragGesture = true, // 确定是否可以通过拖动手势打开Scaffold.drawer, 默认情况下,拖动手势处于启用状态 this.endDrawerEnableOpenDragGesture = true, // 确定是否可以使用拖动手势打开Scaffold.endDrawer,默认情况下,拖动手势处于启用状态。 })
 
基本属性介绍完后,我们下面就开始实现三种经典的导航栏。



2


底部导航栏




根据控件 Scaffold 的说明,底部导航栏的开发会涉及 bottomNavigationBar 这个属性,在表格中有说明到该属性对应的是一个 BottomNavigationBar 组件,该组件的属性也比较多,具体说明如下所示:

  
    
    
  
BottomNavigationBar({ Key key, @required this.items, // 数组,对应于BottomNavigationBarItem这个组件为菜单栏的每一项,其中包含四个属性icon、title、activeIcon和backgroundColor this.onTap, // 点击触发逻辑,一般用来触发页面的跳转更新 this.currentIndex = 0, // 当前所在的 items 数组中的位置 this.elevation = 8.0, // 设置阴影效果值 BottomNavigationBarType type, // fixed(固定位置)和shifting(浮动效果) Color fixedColor, // 代表选中时候的颜色,不能和selectedItemColor一起使用 this.backgroundColor, // 背景颜色 this.iconSize = 24.0, // icon 大小 Color selectedItemColor, // 代表选中的颜色,不能和selectedItemColor一起使用 this.unselectedItemColor, // 未选中时颜色 this.selectedIconTheme = const IconThemeData(), // 当前选中的BottomNavigationBarItem.icon中图标的大小,不透明度和颜色 this.unselectedIconTheme = const IconThemeData(), // 当前未选中的BottomNavigationBarItem.icon中图标的大小,不透明度和颜色 this.selectedFontSize = 14.0, // 选中的字体大小 this.unselectedFontSize = 12.0, // 未选中字体大小 this.selectedLabelStyle, // 选中字体样式 this.unselectedLabelStyle, // 未选中字体样式 this.showSelectedLabels = true, // 是否开启选中的样式 bool showUnselectedLabels, // 是否开启未选中的样式 })

介绍完一些基础属性以后,我们来尝试实现底部导航栏功能。

我们实现两个页面,通过使用导航栏的方式来支持页面跳转。底部导航栏需要一个状态属性 indexValue 来控制导航栏显示位置,我们看下具体在 Scaffold 中的代码逻辑。
  
    
    
  
return Scaffold( appBar: AppBar(     title: Text('MORTAL'), // 页面名字 ), body: Stack( children: <Widget>[ _getPagesWidget(0), _getPagesWidget(1), _getPagesWidget(2) ], ), bottomNavigationBar: BottomNavigationBar( items: [ BottomNavigationBarItem( icon: Icon(Icons.people),         title: Text('首页'), activeIcon: Icon(Icons.people_outline), ), BottomNavigationBarItem( icon: Icon(Icons.favorite),         title: Text('发现'), activeIcon: Icon(Icons.favorite_border), ), BottomNavigationBarItem( icon: Icon(Icons.person), title: Text('我'), activeIcon: Icon(Icons.person_outline), ), ], iconSize: 24, currentIndex: _indexNum, /// 选中后,底部BottomNavigationBar内容的颜色(选中时,默认为主题色) /// (仅当type: BottomNavigationBarType.fixed,时生效) fixedColor: Colors.lightBlueAccent, type: BottomNavigationBarType.fixed, onTap: (int index) { ///这里根据点击的index来显示,非index的page均隐藏 if(_indexNum != index){ setState(() { _indexNum = index; }); } }, ), );

上面代码中,第 5 - 10 行是获取具体的页面信息,并且在 _getPagesWidget 里会判断当前 index 的值,判断当前索引 _indexNum 与 index 是否相同,相同则显示页面,不相同则页面隐藏,具体 _getPagesWidget 代码实现逻辑如下:

  
    
    
  
/// 获取页面组件 Widget _getPagesWidget(int index) { List<Widget> widgetList = [ router.getPageByRouter('homepage'), Icon(Icons.directions_transit), router.getPageByRouter('userpage') ]; return Offstage( offstage: _indexNum != index, child: TickerMode( enabled: _indexNum == index, child: widgetList[index], ), ); }

Scaffold 中代码的第 12 行开始实现底部导航栏逻辑,其中使用到了 BottomNavigationBar 控件,配置控件中的 items 属性,该属性注意是导航栏具体每一项数据,iconSize、currentIndex、fixedColor、type 和 onTap,onTap 主要是来切换页面,触发 setState ,然后重新 build 页面结构。

以上就完成了导航栏的设计,运行完以后,就可以正常进行页面切换操作。


3


顶部导航栏




顶部导航栏,需要控件 Scaffold 属性 appBar ,在 appBar 中设置 bottom 就可以实现顶部导航栏功能。接下来看下 bottom 的设置方法,代码如下:

  
    
    
  
return Scaffold( appBar: AppBar(     title: Text('MORTAL'), // 页面名字 bottom: TabBar( controller: _controller, tabs: <Widget>[ Tab( icon: Icon(Icons.view_list),           text: '首页', ), Tab( icon: Icon(Icons.favorite),           text: '发现', ), Tab( icon: Icon(Icons.person), text: '我', ), ], ), ), body: TabBarView( controller: _controller, children: [ router.getPageByRouter('homepage'), Icon(Icons.directions_transit), router.getPageByRouter('userpage') ], ), );

在上面代码中的第 4 到第 21 行是在设置 bottom 的 TabBar 组件。在 TabBar 中,包含了一个控制导航栏的 controller 和具体导航栏的配置信息的 Tabs。在代码第 22 行到第 29 行也是在配置各个 tab 对应的页面内容组件,这里也是通过 controller 来控制显示,具体 controller 控制部分代码如下:

  
    
    
  
/// 跳转页面 void redirect(String link) { if (link == null) { return; } int indexNum = router.open(context, link); if (indexNum > -1 && _controller.index != indexNum) { _controller.animateTo(indexNum); } }
顶部导航栏的跳转逻辑部分和底部导航栏相似,这里是使用状态变量 _controller 的 animateTo 方法来处理 tab 的切换。


4


侧边导航栏




侧边导航栏主要使用的是 Scaffold 的 drawer 属性。该属性需要一个 Drawer 对象,因此我们可以在 Widgets 目录中创建一个 menu 目录,并新增 draw.dart 文件,具体代码如下:

  
    
    
  
import 'package:flutter/material.dart'; import 'package:MORTAL/router.dart'; /// 左侧菜单 class MenuDraw extends StatelessWidget { /// 外部跳转 final Function redirect; /// 默认构造函数 const MenuDraw(this.redirect); @override Widget build(BuildContext context) { return Drawer( child: MediaQuery.removePadding( context: context, child: ListView( children: <Widget>[ ListTile( leading: Icon(Icons.view_list),                 title: Text('首页'), onTap: () { Navigator.pop(context); redirect('tyfapp://homepage'); }, ), ListTile( leading: Icon(Icons.favorite),                 title: Text('发现'), onTap: () { Navigator.pop(context);                   Router().open(context, 'http://www.baidu.com'); }, ), ListTile( leading: Icon(Icons.person), title: Text('我'), onTap: () { Navigator.pop(context);                   redirect('tyfapp://mypage'); }, ), ], ), ), ); } }
前 4 行是导入相应的库,创建 MenuDraw 类,类包含 redirect 方法,该方法就是 entrance 中声明的 tab 导航栏切换的方法,如果非 entrance 的切换则需要使用到 router 跳转,类似上面代码中的第 33 行 。

代码的第 19 行到第 44 行则为相应的左侧导航栏的配置,onTap 为导航栏的跳转逻辑,在点击相应的 Tap 以后,需要使用 Navigator.pop(context) 来关闭左侧导航栏。

实现完成该 MenuDraw 类后,我们需要在控件 Scaffold 中增加 drawer 属性,代码如下。
  
    
    
  
return Scaffold( appBar: AppBar( title: Text('MORTAL App'), // 页面名字 ), drawer: MenuDraw(redirect), ... );
上面代码的第 5 行就是新增 drawer 左侧导航栏.


5



搜索功能



为了让功能更完善,我们需要增加一个右侧搜索功能,这里就涉及 AppBar 的 actions 属性,我们可以在 AppBar 中增加如下代码:

  
    
    
  
AppBar(   title: Text('MORTAL'), // 页面名字 actions: <Widget>[ IconButton( icon: Icon(Icons.search), onPressed: () { showSearch( context: context, delegate: SearchPageCustomDelegate() ); }, ), ], )
在 actions 中可以添加一组功能按钮,由于这里我们只需要搜索功能按钮,因此在 actions 属性中添加一个 IconButton 即可。IconButton 中需要展示一个搜索 icon ,并且点击以后前往搜索页面。

接下来我们就需要实现SearchPageDelegate 的页面逻辑,新增 search_page 页面,并在 search_page 下新建 custom_delegate.dart 文件,接下来实现该文件代码。

这个类需要继承Flutter自带的 SearchDelegate ,然后必须包含四个方法的实现逻辑,代码如下:
  
    
    
  
import 'package:flutter/material.dart'; /// 搜索框 class SearchPageDelegate extends SearchDelegate { @override List<Widget> buildActions(BuildContext context) { } @override Widget buildLeading(BuildContext context) { } @override Widget buildResults(BuildContext context) { } @override Widget buildSuggestions(BuildContext context) { } }

buildActions 为右侧的图标按钮,一般我们可以显示一个清除搜索框内容的功能,我们可以使用如下代码来实现:

  
    
    
  
return [ IconButton( tooltip: 'Clear', icon: const Icon(Icons.clear), onPressed: () { query = ''; showSuggestions(context); }, ) ];

buildLeading 为左侧的按钮一般来触发返回操作,代码实现如下:

  
    
    
  
@override Widget buildLeading(BuildContext context) { return IconButton( tooltip: 'Back', icon: AnimatedIcon( icon: AnimatedIcons.menu_arrow, progress: transitionAnimation, ), onPressed: () { close(context, null); }, ); }
关闭当前页面使用 close(context, null) 即可实现。

buildResults 为搜索结果显示列表,buildSuggestions 为搜索提示列表,在这里我们返回一个空 ListView() 就行。

在上面基础上,我们需要修改默认的搜索框的提示,并且需要匹配当前主题的颜色字体等,需要做以下两部分逻辑。

  
    
    
  
/// 修改提示框内容 String get searchFieldLabel => '用户、帖子'; @override ThemeData appBarTheme(BuildContext context) { final ThemeData theme = Theme.of(context); return theme.copyWith( inputDecorationTheme: InputDecorationTheme(), primaryColor: theme.primaryColor, primaryIconTheme: theme.primaryIconTheme, primaryColorBrightness: theme.primaryColorBrightness, primaryTextTheme: theme.primaryTextTheme ); }


End


总结



本文主要介绍了控件 Scaffold 的一些基础用法,着重介绍了其中三个比较常用的属性 bottomNavigationBar、appBar 和 drawer,同时使用这些属性完成了顶部导航栏、底部导航栏、侧边导航栏和搜索功能的实现。



以上是关于:主页设计之顶部导航栏的主要内容,如果未能解决你的问题,请参考以下文章

怎么用vue.js实现一个二级导航栏

vue.js项目实战运用篇之抖音视频APP-第四节:顶部导航栏组件功能

使用 Css 的导航栏样式

Bootstrap 4 固定顶部导航和固定侧边栏

h5之vue自定义底部导航栏

React实现顶部固定滑动式导航栏(导航条下拉一定像素时显示原导航栏样式)