微信小程序 自定義頭部導航欄和導航欄背景圖片 navigationStyle

​ 這兩天由於要作一個帶背景的小程序頭,哭了,小程序導航欄有背景也就算了,還得讓導航欄上的背景順下來,心態小崩。如今能夠單獨設置一個頁面的小程序頭了,可是前提是要微信7.0以上的版本,考慮到兼容性問題,仍是不要貿然的上了,因此用老版本的替換全部頁面的小程序頭來作。javascript

​ 參考了jiuyucha的文章,可是沒有解決自定義背景的和返回按鈕的顏色的問題,還有由於IOS的橡皮筋效果,對IOS端不太友好,屏幕會亂劃。因此針對性的改動了這些功能,由於才學小程序兩三天,因此其中踩了不少坑,但好在最後效果仍是達到了。css

下面是效果圖:html

​ 原理其實就是經過將原來的頭禁用,而後PAGE天然而然的頂上去之後,定義一個頭的組件,將他設置成fixed佈局固定在原來頭的部分,而後給page加上Margin-top,因此還原原來的感受。背景待會再說。java

1.app配置

​ 首先禁用全部頭導航,在app.json的window里加一行這個,你會發現全部頭都消失了。而後禁止滑動頁面,滑動問題用scroll-view解決json

"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配置到這裏應該完事了。app

2.組件配置

組件結構:xss

放源碼吧svg

// navbar.wxml

<view class='nav-wrap' style='height: {{height*2 + 20}}px;'>
  <!-- 導航欄背景圖片 -->
  <image class="backgroundimg" src="{{navbarData.address}}" bindload="imgLoaded" style="width:{{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="width:{{imageWidth}}px;height:{{imageHeight}}px" />

CSS:

/* navbar.wxss */

/* 頂部要固定定位   標題要居中   自定義按鈕和標題要和右邊微信原生的膠囊上下對齊 */
.nav-wrap {
  /* display: none; */
  position: fixed;
  width: 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-width: 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;
  width: 140rpx;
  justify-content: space-between;
  height: 100%;
}

.back-pre {
  width: 32rpx;
  height: 36rpx;
  margin-top: 4rpx;
  padding: 10rpx;
}
.nav-capsule {
  width: 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裏的任何值都不能完成需求。若是我設置成width:100%佔滿父元素的話,他的長仍是默認的340px,因此仍是鼓搗了鼓搗,先設置寬度不是100%了,而是經過wx.**getSystemInfoSync**().windowWidth;來獲取的屏幕寬度。而後再經過image組件的事件獲取原圖的長寬,探後計算屏幕寬和原圖寬的率,而後再將這個率乘上原圖長度,就能夠獲取到一個佔滿父元素又對着比例的圖了,而後給父元素套上overflow:hidden就行了。

​ 第三個坑,就是怎麼作背景的拼接,想了想也不是個坑,直接在組件的最外層再加一個如出一轍的image標籤就好了,這樣就作到了標籤上顯示半個背景圖,而後在他的下層又能顯示一個完整的背景圖,由於上面被蓋住了,因此地下的下半部分和導航欄的上半部分背景正好拼接起來,因此問題也就這麼解決了。

​ 最後的話歡迎你們指正個人問題,畢竟小白一個,不是很懂小程序這方面。

相關文章
相關標籤/搜索