likes
comments
collection
share

小程序自定义顶部导航栏

作者站长头像
站长
· 阅读数 19

上篇博客自定义了一个底部导航栏,效果还可以,但是我在开发过程中又遇到了一个棘手的问题。就是在底部导航栏的第一个页面需要将页面沉浸到状态栏去,这就麻烦了,因为中间的容器页面无论第几个都是在外面的主界面里,而主界面需要动态的去隐藏标题栏,设计师这是在为难我胖虎?

当然也不是没有办法,这里就需要用到自定义的导航栏了,下面详细介绍。

先看效果

这个是首页的沉浸状态栏效果

小程序自定义顶部导航栏

这个是非首页的标题栏效果

小程序自定义顶部导航栏

看看代码

  • WXML
<!--pages/tabbar/index.wxml-->
<cover-view wx:if="{{!isStatusBar}}" style="height:{{topHeight}}rpx;background:white;">
    <cover-view class="center-both" style="margin-top:{{statusHeight}}rpx;height: {{naviHeight}}rpx">
        <cover-view>
            {{title}}
        </cover-view>
    </cover-view>
</cover-view>

<view class="page-container" style="height:{{containerHeight}}rpx">
    <!-- 使用wx:if 不会渲染,每次点击会重走组件生命周期 -->
    <!-- 使用display:none隐藏,仍然会渲染组件,只走一遍生命周期 -->
    <!-- 使用hidden隐藏,和display:none一样,但是受限于块级元素,无法使用 -->

    <!-- 用户 -->
    <block wx:if="{{roleType=='user'}}">
        <home id="id0" indexpage="{{true}}" style="display: {{currentPageIndex==0?'block':'none'}};" />
        <user id="id1" show='{{currentPageIndex==1}}' style="display: {{currentPageIndex==1?'block':'none'}};" />
    </block>

    <!-- 管理员 -->
    <block wx:elif="{{roleType=='manager'}}">
        <manager id="id0" style="display: {{currentPageIndex==0?'block':'none'}};" />
        <log id="id1" style="display: {{currentPageIndex==1?'block':'none'}};" />
    </block>
</view>

<!-- 底部切换菜单 -->
<view class="row-center tab-container" style="height:{{104 + bottomHeight}}rpx;padding-bottom:{{bottomHeight}}rpx">
    <view wx:for="{{tabBar}}" wx:key="index" class="flex1 center-both col"
        style="color:{{index==currentPageIndex?'#0B7BFBFF':'#616161FF'}}" data-index="{{index}}" bindtap="onSelectTap">
        <view class="{{item.iconClass}} icon"></view>
        <view class="text">{{item.text}}</view>
    </view>
</view>

在昨天的基础上加了自定义的顶部导航栏,适配了一下高度,使用 cover-view 放在了最顶层。

  • WXSS

这里没什么变化,导航栏样式直接写在 style 里了,需要的话可以写在 wxss 里。

  • JSON
{
  "navigationStyle": "custom",
   ...
}

配置文件里面加入上面这句话,自定义导航栏,需要微信客户端7.0支持,如果要适配的话可以去全局的 windows 里面设置。

  • Page.js
// pages/index/index.js
var app = getApp()

Page({

    data: {
        //状态栏高度
        statusHeight: app.globalData.statusHeight,
        //导航栏高度
        naviHeight: app.globalData.naviHeight,
        //顶部高度 = 状态栏高度 + 导航栏高度
        topHeight: app.globalData.topHeight,
        
        //底部高度
        bottomHeight: app.globalData.bottomHeight,
        //中间内容容器高度 = 屏幕高度 - 底部安全高度 - 底部导航栏高度
        containerHeight: app.globalData.screenHeight - app.globalData.bottomHeight - 104,

        isStatusBar: true,
        title: '',
        currentPageIndex: 0,
        roleType: "",
        tabBar: [],

        userTabBar: [{
                "iconClass": "iconfont home",
                "text": "首页",
                "uptoStatus": true
            },
            {
                "iconClass": "iconfont user",
                "text": "个人中心",
                "uptoStatus": false
            },
        ],

        managerTabBar: [{
                "iconClass": "iconfont manager",
                "text": "管理", 
            	"uptoStatus": false
            },
            {
                "iconClass": "iconfont log",
                "text": "日志",     
                "uptoStatus": false
            },
        ]
    },

    onLoad: function (options) {
        let tabBar = this.data.tabBar
        if (options.roleType == 'user') {
            tabBar = this.data.userTabBar
        } else if (options.roleType == 'manager') {
            tabBar = this.data.managerTabBar
        }
		
        // 在此加载数据
        this.setData({
            tabBar: tabBar,
            roleType: options.roleType,
        })
    },
    
    // 下拉加载
    onPullDownRefresh() {
        this.selectComponent("#id" + this.data.currentPageIndex).onPullDownRefresh()
	},

    onSelectTap(event) {
        let index = event.currentTarget.dataset.index;   
        let isStatusBar = this.data.tabBar[index].uptoStatus;
        
        //中间页面高度 = 屏幕高度 - 底部安全高度 - 底部导航高度 - 顶部高度
        let containerHeight = app.globalData.screenHeight - bottomHeight - 104
        if (!isStatusBar) {
            containerHeight = containerHeight - this.data.topHeight
        }
        
        //选中页面更新
        this.setData({
            currentPageIndex: index,
            title: this.data.tabBar[index].text,
            currentPageIndex: index,
            isStatusBar: isStatusBar,
            containerHeight: containerHeight
        })
    },
})

Page中的改动就多了点,一个一个讲吧。

先引入了顶部导航栏适配需要用到的三个变量,状态栏高度、标题栏高度以及两者之和,标题栏使用 margin 在状态栏空出对应高度,再使用居中对齐使标题居中,适配效果不错。

同时引入是否沉浸状态栏和标题两个变量,isStatusBar控制是否显示顶部导航栏,标题就不用说了。

在各个标签信息里面增加了 uptoStatus 字段,确定是否要沉浸状态栏。

最后就是切换页面中,要判断选中页面是否要沉浸状态栏,如果要沉浸状态栏,还得修改中间容器的高度,同时标题也应该对应修改。

适配数据

这里也把高度适配数据贴一份吧,具体解释看前面博客。

globalData: {
    //系统信息
    systemInfo: {},
    //1px像素值 对应 rpx
    pixelRatio1: 2,
    //胶囊信息
    menuInfo: {},
    //屏幕高度
    screenHeight: 2000,
    //顶部高度 = 状态栏高度 + 导航栏高度
    topHeight: 0,
    //状态栏高度
    statusHeight: 0,
    //导航栏高度
    naviHeight: 0,
    //底部安全高度
    bottomHeight: 0,
},
      
onLaunch: function () {
    var that = this;

    //获取设备信息
    let systemInfo = wx.getSystemInfoSync()
    that.globalData.systemInfo = systemInfo

    //1rpx 像素值
    let pixelRatio1 = 750 / systemInfo.windowWidth;
    that.globalData.pixelRatio1 = pixelRatio1

    //胶囊信息
    let menu = wx.getMenuButtonBoundingClientRect()
    that.globalData.menuInfo = menu

    //状态栏高度
    let statusHeight = systemInfo.statusBarHeight
    that.globalData.statusHeight = statusHeight * pixelRatio1

    //导航栏高度
    let naviHeight = (menu.top - statusHeight) * 2 + menu.height
    that.globalData.naviHeight = naviHeight * pixelRatio1

    //顶部高度 = 状态栏高度 + 导航栏高度
    that.globalData.topHeight = (statusHeight + naviHeight) * pixelRatio1

    //屏幕高度
    let screenHeight = systemInfo.screenHeight
    that.globalData.screenHeight = screenHeight * pixelRatio1

    //底部高度 = 屏幕高度 - 安全区域bottom
    let bottom = systemInfo.safeArea.bottom
    that.globalData.bottomHeight = (screenHeight - bottom) * pixelRatio1
}


结语

顶部导航栏自定义起来还是挺简单的,就是这里也有一些不如意的问题,比如在苹果手机上使用,可以一直上拉,让标题栏都划上去,但是在安卓使没问题的,机型问题就不管了,有机会调。

end

完美撒花

转载自:https://juejin.cn/post/7222862599851556921
评论
请登录