zoukankan      html  css  js  c++  java
  • 微信小程序 自定义头部导航栏和导航栏背景图片 navigationStyle

    ​ 这两天因为要做一个带背景的小程序头,哭了,小程序导航栏有背景也就算了,还得让导航栏上的背景顺下来,心态小崩。现在可以单独设置一个页面的小程序头了,但是前提是要微信7.0以上的版本,考虑到兼容性问题,还是不要贸然的上了,所以用老版本的替换所有页面的小程序头来做。

    ​ 参考了jiuyucha的文章,但是没有解决自定义背景的和返回按钮的颜色的问题,还有因为IOS的橡皮筋效果,对IOS端不太友好,屏幕会乱划。所以针对性的改动了这些功能,因为才学小程序两三天,所以其中踩了很多坑,但好在最后效果还是达到了。

    下面是效果图:

    ​ 原理其实就是通过将原来的头禁用,然后PAGE自然而然的顶上去以后,定义一个头的组件,将他设置成fixed布局固定在原来头的部分,然后给page加上Margin-top,所以还原原来的感觉。背景待会再说。

    1.app配置

    ​ 首先禁用所有头导航,在app.json的window里加一行这个,你会发现所有头都消失了。然后禁止滑动页面,滑动问题用scroll-view解决

    "window": {
        "navigationStyle": "custom"
    }, 
    "disableScroll": true
    

    ​ 然后在app.js里获取导航头的高度的全局数据

    // app.js
    
    App({
      globalData: {
        statusBarHeight: wx.getSystemInfoSync()['statusBarHeight']
      },
      // 判断是否由分享进入小程序
        if (e.scene == 1007 || e.scene == 1008) {
          this.globalData.share = true
        } else {
          this.globalData.share = false
        }
        //获取设备顶部窗口的高度(不同设备窗口高度不一样,根据这个来设置自定义导航栏的高度)
        //这个最初我是在组件中获取,但是出现了一个问题,当第一次进入小程序时导航栏会把
        //页面内容盖住一部分,当打开调试重新进入时就没有问题,这个问题弄得我是莫名其妙
        //虽然最后解决了,但是花费了不少时间
        wx.getSystemInfo({
          success: res => {
            this.globalData.height = res.statusBarHeight
          }
        })
      },
      globalData: {
        userInfo: null,
        share: false, // 分享默认为false
        height: 0 // 顶部高度
      }
    })
    
    

    ​ 在app.wxss给page加一个高度百分之百。

    /* app.wxss */
    page {
      height: 100%;
    }
    

    ​ app配置到这里应该完事了。

    2.组件配置

    组件结构:

    放源码吧

    // navbar.wxml
    
    <view class='nav-wrap' style='height: {{height*2 + 20}}px;'>
      <!-- 导航栏背景图片 -->
      <image class="backgroundimg" src="{{navbarData.address}}" bindload="imgLoaded" style="{{imageWidth}}px;height:{{imageHeight}}px" />
      <!-- // 导航栏 中间的标题 -->
      <view class='nav-title' wx:if='{{!navbarData.white}}' style='line-height: {{height*2 + 44}}px;'>
        {{navbarData.title}}
      </view>
      <view class='nav-title' wx:else='{{!navbarData.white}}' style='line-height: {{height*2 + 44}}px; color:#ffffff'>
        {{navbarData.title}}
      </view>
      <view style='display: flex; justify-content: space-around;flex-direction: column'>
        <!-- // 导航栏  左上角的返回按钮 -->
        <!-- //  其中wx:if='{{navbarData.showCapsule}}' 是控制左上角按钮的显示隐藏,首页不显示 -->
        <view class='nav-capsule' style='height: {{height*2 + 44}}px;' wx:if='{{navbarData.showCapsule}}'>
          <!-- //左上角的返回按钮,wx:if='{{!share}}'空制返回按钮显示 -->
          <!-- //从分享进入小程序时 返回上一级按钮不应该存在 -->
          <!-- navbarData.white是控制按钮颜色的,因为背景有深浅色,返回按钮自己找图片 -->
          <view bindtap='_navback' wx:if='{{!share&&navbarData.white}}'>
            <image src='../../images/返 回 (1).svg' mode='aspectFit' class='back-pre'></image>
          </view>
          <view bindtap='_navback' wx:else='{{!share}}'>
            <image src='../../images/返 回.svg' mode='aspectFit' class='back-pre'></image>
          </view>
        </view>
      </view>
    </view>
    <!-- 导航栏下面的背景图片 -->
    <image class="backgroundimg" src="{{navbarData.address}}" bindload="imgLoaded" style="{{imageWidth}}px;height:{{imageHeight}}px" />
    

    CSS:

    /* navbar.wxss */
    
    /* 顶部要固定定位   标题要居中   自定义按钮和标题要和右边微信原生的胶囊上下对齐 */
    .nav-wrap {
      /* display: none; */
      position: fixed;
       100%;
      top: 0;
      background: #fff;
      color: #000;
      z-index: 9999999;
      background: #000;
      overflow: hidden;
    }
    /* 背景图 */
    .backgroundimg {
      position: absolute;
      z-index: -1;
    }
    /* 标题要居中 */
    .nav-title {
      position: absolute;
      text-align: center;
      max- 400rpx;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      margin: auto;
      font-size: 36rpx;
      color: #2c2b2b;
      font-weight: 450;
    }
    
    .nav-capsule {
      display: flex;
      align-items: center;
      margin-left: 30rpx;
       140rpx;
      justify-content: space-between;
      height: 100%;
    }
    
    .back-pre {
       32rpx;
      height: 36rpx;
      margin-top: 4rpx;
      padding: 10rpx;
    }
    .nav-capsule {
       36rpx;
      height: 40rpx;
      margin-top: 3rpx;
    }
    
    

    在JSON里声明我是个组件

    {
      "component": true,
      "usingComponents": {}
    }
    

    最后是js。

    const app = getApp()
    Component({
      properties: {
        navbarData: {
          //navbarData   由父页面传递的数据,变量名字自命名
          type: Object,
          value: {},
          observer: function(newVal, oldVal) {}
        }
      },
      data: {
        height: '',
        //默认值  默认显示左上角
        navbarData: {
          showCapsule: 1
        },
        imageWidth: wx.getSystemInfoSync().windowWidth, // 背景图片的高度
        imageHeight: '' // 背景图片的长度,通过计算获取
      },
      attached: function() {
        // 获取是否是通过分享进入的小程序
        this.setData({
          share: app.globalData.share
        })
        // 定义导航栏的高度   方便对齐
        this.setData({
          height: app.globalData.height
        })
      },
      methods: {
        // 返回上一页面
        _navback() {
          wx.navigateBack()
        },
        // 计算图片高度
        imgLoaded(e) {
          this.setData({
            imageHeight:
              e.detail.height *
              (wx.getSystemInfoSync().windowWidth / e.detail.width)
          })
        }
        //返回到首页
        // _backhome() {
        //   wx.switchTab({
        //     url: '/pages/index/index'
        //   })
        // }
      }
    })
    
    

    ​ 大概就是这么多,怎么在页面上用呢

    3.具体页面配置

    ​ 页面的HTML,我是内容里面放页面的东西。

    <nav-bar navbar-data='{{nvabarData}}'></nav-bar>
    <scroll-view scroll-y style="height: 100%;">
      <view class="scroll-view-item" style='padding-top: {{height}}px;'>我是内容</view>
    </scroll-view>
    

    ​ 页面的JSON,navigationBarTextStyle是用来配置胶囊颜色的,因为胶囊是微信给的,不能自定义,只能改颜色,所以委屈一下从这里改一下吧

    {
      "usingComponents": {
        "nav-bar": "../../components/navbar/navbar"
      },
      "navigationBarTextStyle": "white"
    }
    
    

    ​ 页面JS,图片自己填上地址就好了。注意getApp()不要省。

    const app = getApp()
    Page({
      data: {
        // 导航头组件所需的参数
        nvabarData: {
          showCapsule: 1, //是否显示左上角图标   1表示显示    0表示不显示
          title: '标题', //导航栏 中间的标题
          white: true, // 是就显示白的,不是就显示黑的。
          address: '../../images/蒙版组 1@2x.png' // 加个背景 不加就是没有
        },
        // 导航头的高度
        height: app.globalData.height * 2 + 20
      }
    })
    
    

    4.存在的问题

    上拉刷新

    ​ 我没有试过哈,不过原生的微信上拉刷新这么用是准定不行了,如果喜欢IOS橡皮筋模式的同学或者想要刷新的同学可以在具体页面里删掉scroll-view组件换成view(记得保留那个padding-top!),然后把app.json的禁用滑动删除掉。具体的我也没有深入,大家自行解决吧。

    5.踩的坑

    ​ 单纯分享下,不看也可以,首先就是设置页面的背景的时候,我考虑过直接在css上设置background image,但是有一个问题是,小程序的background image 只支持在线的地址或者是base64。我不知道为什么要这么做。真的很迷。但是线上的不稳定,base64太长了,代码不好看也不好整理,所以考虑了一下还是用Image组件吧。

    ​ 然后第二个坑又来了,image组件自带宽高,而且用Mode里的任何值都不能完成需求。如果我设置成100%占满父元素的话,他的长还是默认的340px,所以还是鼓捣了鼓捣,先设置宽度不是100%了,而是通过wx.**getSystemInfoSync**().windowWidth;来获取的屏幕宽度。然后再通过image组件的事件获取原图的长宽,探后计算屏幕宽和原图宽的率,然后再将这个率乘上原图长度,就可以获取到一个占满父元素又对着比例的图了,然后给父元素套上overflow:hidden就好了。

    ​ 第三个坑,就是怎么做背景的拼接,想了想也不是个坑,直接在组件的最外层再加一个一模一样的image标签就行了,这样就做到了标签上显示半个背景图,然后在他的下层又能显示一个完整的背景图,因为上面被盖住了,所以地下的下半部分和导航栏的上半部分背景正好拼接起来,所以问题也就这么解决了。

    ​ 最后的话欢迎大家指正我的问题,毕竟小白一个,不是很懂小程序这方面。

  • 相关阅读:
    datalist分页
    css渐变色
    4月25日
    今天
    DataView Distinct
    心情复杂啦
    高数矩阵
    计算机视觉学习OpenCV Java 调用
    大数据学习关于hdfs
    摄影学习构图技巧
  • 原文地址:https://www.cnblogs.com/wangzirui98/p/11249317.html
Copyright © 2011-2022 走看看