微信小程序@自定义导航栏

3,144 阅读4分钟

概述

自定义导航栏是微信小程序开发中常有的需求,本篇文章主要给大家介绍下在微信小程序中自定义导航栏的思路,后面会贴出demo地址,有兴趣的小伙伴可以自行下载查看。在这里不再累述如何创建和使用自定义组件,不了解的小伙伴可以去查阅官方文档。

分析

1. 模板结构

在定义模板之前首先你需要了解导航栏的组成,通过下图我们可以看出导航栏由状态栏、标题栏和胶囊按钮组成。

所以自定义导航栏最基础的模板结构如下:

<view class="app-header">
  <view class="navigation-bar">
    <!-- 状态栏 -->
    <view class="status-bar" />
    <!-- 标题栏 -->
    <view class="title-bar"></view>
  </view>
</view>

2. 计算导航栏高度

自定义导航栏最关键的地方就是需要去计算导航栏的高度,由于胶囊按钮在iOS和安卓设备上的表现是不一致的,所以我们需要依赖于胶囊按钮来动态获取导航栏的高度以保持和原生导航栏高度的一致。由导航栏的组成我们可以得出:

导航栏的高度 = 状态栏高度 + 标题栏高度

状态栏的高度我们可以通过如下代码获取:

const { statusBarHeight } = wx.getSystemInfoSync();

拿到状态栏的高度之后,接下来我们就需要去计算标题栏的高度了,官方为我们提供了如下方法来获取胶囊信息:

const { width, height, left, top, right } = wx.getMenuButtonBoundingClientRect();

观察下图,我们可以知道,标题栏的高度 = 胶囊高度 + (胶囊距离顶部的距离 - 状态栏高度) * 2。

注意:胶囊Right值是胶囊右边界相对于屏幕左侧的距离,所以胶囊距离屏幕右侧的距离应该是:屏幕宽度 - 胶囊的Right值。

核心代码如下:

// 获取状态栏高度/屏幕宽度
const { statusBarHeight, screenWidth } = wx.getSystemInfoSync();
// 获取胶囊信息
const { width, height, left, top, right } = wx.getMenuButtonBoundingClientRect();
// 计算标题栏高度
const titleBarHeight = height + (top - statusBarHeight) * 2;
// 计算导航栏高度
const appHeaderHeight = statusBarHeight + titleBarHeight;

3. 标题栏宽度

标题栏的宽度默认为屏幕的宽度,这样我们在设置标题文本相对于屏幕水平居中时会非常方便。但是得考虑到另外一种情况,如果我们希望封装的组件更加灵活,比如可以自定义标题栏的视图,那我们就必须要注意把控自定义标题视图的安全区域了。为了让导航栏看起来比较协调,左右间距应该保持一致,所以在设置自定义标题栏距离屏幕左侧的距离应该和胶囊距离屏幕右侧的距离一致。

观察上图可以得知,自定义标题视图的宽度及左侧间距的计算公式如下:

// 左侧间距 = 屏幕宽度 - 胶囊Right值
// 自定义标题视图的宽度 = 胶囊Left值 - 左侧间距
const navigationBarLeftGap = screenWidth - right;
const safeWidth = left - navigationBarLeftGap;

这里我提供了一个属性来标记标题栏是否采用自定义模式,如下所示:

properties: {
    // 标题栏风格:default / custom
    titleViewStyle: {
      type: String,
      value: 'default'
    } 
  }

然后在模板文件中判断:

<!-- 标题栏 -->
<view class="title-bar" style="height: {{titleBarHeight}}px;">
  <view wx:if="{{titleViewStyle === 'custom'}}" class="custom-view" style="width:{{safeWidth}}px; margin-left:{{navigationBarLeftGap}}px;">
    <slot />
  </view>
  <view wx:else class="title-view">{{title}}</view>
</view>

4. 仿胶囊按钮

有时我们可能需要实现一个类似于微信胶囊风格的功能按钮,比如返回上一页和返回主页的按钮,如下图所示: 这里主要列出系统胶囊在black和white风格下的样式信息,如下图所示: 可以使用定位的方式布局胶囊,但是要注意,为了协调一定要保持胶囊距离屏幕边界间距的一致性。具体的布局方式这里不再详解。

5. 渐变导航

为了提升用户体验,页面中也会出现一些渐变导航的效果,如下图所示: 渐变导航的实现并不复杂,主要是监听页面滚动,计算并更新导航栏的 opacity 值即可,组件中我封装了 setOpacity 方法,便于在页面中监听到滚动时触发:

setOpacity(scrollTop) {
    const maxTop = 200;
    let opacity = 0;
    if (scrollTop < maxTop) {
      opacity = scrollTop / maxTop;
    } else {
      opacity = 1;
    }
    this.setData({
      opacity
    })
  }

源码地址

https://github.com/LiHongyao/miniprogram__App_Header