这两天由于要作一个带背景的小程序头,哭了,小程序导航栏有背景也就算了,还得让导航栏上的背景顺下来,心态小崩。如今能够单独设置一个页面的小程序头了,可是前提是要微信7.0以上的版本,考虑到兼容性问题,仍是不要贸然的上了,因此用老版本的替换全部页面的小程序头来作。javascript
参考了jiuyucha的文章,可是没有解决自定义背景的和返回按钮的颜色的问题,还有由于IOS的橡皮筋效果,对IOS端不太友好,屏幕会乱划。因此针对性的改动了这些功能,由于才学小程序两三天,因此其中踩了不少坑,但好在最后效果仍是达到了。css
下面是效果图:html
原理其实就是经过将原来的头禁用,而后PAGE天然而然的顶上去之后,定义一个头的组件,将他设置成fixed布局固定在原来头的部分,而后给page加上Margin-top,因此还原原来的感受。背景待会再说。java
首先禁用全部头导航,在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
组件结构: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' // }) // } } })
大概就是这么多,怎么在页面上用呢
页面的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 } })
我没有试过哈,不过原生的微信上拉刷新这么用是准定不行了,若是喜欢IOS橡皮筋模式的同窗或者想要刷新的同窗能够在具体页面里删掉scroll-view组件换成view(记得保留那个padding-top!),而后把app.json的禁用滑动删除掉。具体的我也没有深刻,你们自行解决吧。
单纯分享下,不看也能够,首先就是设置页面的背景的时候,我考虑过直接在css上设置background image,可是有一个问题是,小程序的background image 只支持在线的地址或者是base64。我不知道为何要这么作。真的很迷。可是线上的不稳定,base64太长了,代码很差看也很差整理,因此考虑了一下仍是用Image组件吧。
而后第二个坑又来了,image组件自带宽高,并且用Mode里的任何值都不能完成需求。若是我设置成width:100%
占满父元素的话,他的长仍是默认的340px,因此仍是鼓捣了鼓捣,先设置宽度不是100%了,而是经过wx.**getSystemInfoSync**().windowWidth
;来获取的屏幕宽度。而后再经过image组件的事件获取原图的长宽,探后计算屏幕宽和原图宽的率,而后再将这个率乘上原图长度,就能够获取到一个占满父元素又对着比例的图了,而后给父元素套上overflow:hidden
就行了。
第三个坑,就是怎么作背景的拼接,想了想也不是个坑,直接在组件的最外层再加一个如出一辙的image标签就好了,这样就作到了标签上显示半个背景图,而后在他的下层又能显示一个完整的背景图,由于上面被盖住了,因此地下的下半部分和导航栏的上半部分背景正好拼接起来,因此问题也就这么解决了。
最后的话欢迎你们指正个人问题,毕竟小白一个,不是很懂小程序这方面。