热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

微信小程序自定义头部导航栏和导航栏背景图片navigationStyle

这两天因为要做一个带背景的小程序头,哭了,小程序导航栏有背景也就算了,还得让导航栏上的背景顺下来,心态小崩。现在可以单独设置一个页面的小程序头了,但是前提是要微信7.0以上的版本,

这两天因为要做一个带背景的小程序头,哭了,小程序导航栏有背景也就算了,还得让导航栏上的背景顺下来,心态小崩。现在可以单独设置一个页面的小程序头了,但是前提是要微信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' hljs-string">'height: {{height*2 + 20}}px;'>

<image class="backgroundimg" src="{{navbarData.address}}" bindload="imgLoaded" hljs-string">"width:{{imageWidth}}px;height:{{imageHeight}}px" />

<view class='nav-title' wx:if='{{!navbarData.white}}' hljs-string">'line-height: {{height*2 + 44}}px;'>
{{navbarData.title}}
view>
<view class='nav-title' wx:else='{{!navbarData.white}}' hljs-string">'line-height: {{height*2 + 44}}px; color:#ffffff'>
{{navbarData.title}}
view>
<view hljs-string">'display: flex; justify-content: space-around;flex-direction: column'>


<view class='nav-capsule' hljs-string">'height: {{height*2 + 44}}px;' wx:if='{{navbarData.showCapsule}}'>



<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" hljs-string">"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 hljs-string">"height: 100%;">
<view class="scroll-view-item" hljs-string">'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标签就行了,这样就做到了标签上显示半个背景图,然后在他的下层又能显示一个完整的背景图,因为上面被盖住了,所以地下的下半部分和导航栏的上半部分背景正好拼接起来,所以问题也就这么解决了。



推荐阅读
  • 本文详细介绍了如何解决Uploadify插件在Internet Explorer(IE)9和10版本中遇到的点击失效及JQuery运行时错误问题。通过修改相关JavaScript代码,确保上传功能在不同浏览器环境中的一致性和稳定性。 ... [详细]
  • 导航栏样式练习:项目实例解析
    本文详细介绍了如何创建一个具有动态效果的导航栏,包括HTML、CSS和JavaScript代码的实现,并附有详细的说明和效果图。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 本文介绍了如何利用JavaScript或jQuery来判断网页中的文本框是否处于焦点状态,以及如何检测鼠标是否悬停在指定的HTML元素上。 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
  • 尽管某些细分市场如WAN优化表现不佳,但全球运营商路由器和交换机市场持续增长。根据最新研究,该市场预计在2023年达到202亿美元的规模。 ... [详细]
  • 自己用过的一些比较有用的css3新属性【HTML】
    web前端|html教程自己用过的一些比较用的css3新属性web前端-html教程css3刚推出不久,虽然大多数的css3属性在很多流行的浏览器中不支持,但我个人觉得还是要尽量开 ... [详细]
  • 本文详细介绍了网络存储技术的基本概念、分类及应用场景。通过分析直连式存储(DAS)、网络附加存储(NAS)和存储区域网络(SAN)的特点,帮助读者理解不同存储方式的优势与局限性。 ... [详细]
  • 本文详细介绍了 org.apache.commons.io.IOCase 类中的 checkCompareTo() 方法,通过多个代码示例展示其在不同场景下的使用方法。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
author-avatar
凌乱LW_502
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有