My brother is studying the small program for the first time. I hope you can point out any problems in time when you see them. Thank you

The project code: https://github.com/Shay0921/header-navbar.git

In a small program, the small programs from forwarding message card to enter, because there is only one page stack, so there will not be back button, for some electric business platform, after the goods is forwarded will be influence customer to check other products and home page, then you need to use a custom navigation bar himself wrote a “capsule” button. As shown below:

[Fixed] There are back and home buttons when clicking from another page to the product page.

When entering the commodity page from the share page, there is only one page stack, so there is only the home button.

NavigationStyle? NavigationStyle

In previous versions, this configuration item could only be configured in app.js and was a global property, but now it can be configured in a separate page JSON to achieve a customized navigation bar for a separate page.

The overall train of thought

When navigationStyle: Custom is used, the previous top title bar is removed and the capsule button on the right is fixed in the upper right corner. I then added three views (status bar, title bar, and main content) to the current page to see the layout of the three blocks. I wrote the height of the status bar 20px and the title bar 44px. This is the key to a custom navigation bar, need to calculate the height of the two pieces, and the location of the return capsule | front page button. Basic library 2.1.0 began to use wx. GetMenuButtonBoundingClientRect () to get the location information button on the right side of capsule, and with this information, can be relatively to figure out what we want on the left side to add capsule the location of the button. Find the height of the status bar by using statusBarHeight in wx.getSystemInfosync ().

The directory structure

├ ─ ─ components components │ ├ ─ ─ headerNavbar top custom navigation │ │ └ ─ ─ headerNavbar. Js │ │ └ ─ ─ headerNavbar. Json │ │ └ ─ ─ │ ├─ ├─ ├─ sci-1.txt ├─ sci-1.txt ├─ sci-1.txt ├─ sci-1.txt ├─ sci-1.txt ├─ sci-1.txt │ ├─ ├─ ├─ ├─ ├─ ├─ WXSS │ ├─ ├─ WXSS │ ├─ ├─ WXSS │ ├─ ├─ WXSS │ ├─ ├─ WXSS │ ├─ ├ ─ ├ ─ garbage, ├ ─ garbage. Json │ ├ ─ garbagetest│ │ ├ ─ ├.js route test page.js route test PagetestPage. Json │ │ └ ─ ─testPage. WXML │ │ └ ─ ─testPage.wxssCopy the code

The global variable

app.js

In app.js, the height of the status bar and the position of the capsule on the right should be obtained first

App({
    onLaunch: function (options) {
      // Functions such as logging in and retrieving user information are omitted
      // BECAUSE I need this information on other pages, I don't get statusBarHeight alone
      wx.getSystemInfo({ // Obtain device information
        success: (res) = > {
          this.globalData.systeminfo = res
        },
      })
      // Get the location information of the capsule button
      this.globalData.headerBtnPosi = wx.getMenuButtonBoundingClientRect()
    },
    globalData: {
        systeminfo: {}, // System information
        headerBtnPosi: {} // Capsule button position information}})Copy the code

Note here wx. GetMenuButtonBoundingClientRect (), not like wx. GetSystmInfo has success callback function, But like object wx. GetMenuButtonBoundingClientRect (). The height to use.

Component code

headerNavbar.wxml

<! -- Custom navigation bar -->
<view class='navbar-wrap' 
  style='height:{{navbarHeight}}px; padding-top:{{statusBarHeight}}px; '>  
  <view class="navbar-text"
    style='line-height:{{navbarBtn.height + navbarBtn.top}}px; '>
    {{navbarData.title ? navbarData.title : "Default title"}}{{navbarHeight}}
  </view>
  <view class="navbar-icon"
    wx:if='{{navbarData.showCapsule ? navbarData.showCapsule : true}}'
    style="top:{{navbarBtn.top + statusBarHeight}}px; left:{{navbarBtn.right}}px; height:{{navbarBtn.height}}px;"> 
      <image wx:if='{{haveBack}}' bindtap="_goBack" class="floatL" src="/img/navbar_back_white.png"></image>      
      <view wx:if='{{haveBack}}' class="floatL"></view>
      <image bindtap="_goHome" src="/img/navbar_home_white.png"></image>
  </view>
</view>
<! -- Handwriting loading -->
<view class="navbar-loading" style='height:{{navbarHeight}}px; line-height:{{navbarHeight}}px; '>
  <text>.</text>
</view>Copy the code

The height and the position of the capsule button need to be assigned in HTML to fit different phone screens. The height calculation is explained in detail below. The component of the custom navigation bar is divided into two parts, one is the navigation bar at the top and the other is the loading written by oneself.

Since the custom navigation bar is fixed to the top, in order not to block the main content below, we need to add a height between the navigation bar and the main content of the same as the navigation bar. Class is called box first. This keeps the navigation bar out of the way of the main content. However, there is another problem. If this page supports pull-down refresh, the navigation bar will block the native loading style of the small program, and a blank box will appear in front of the main content. Although it does not affect the use of the page, it will seem strange to users that there will be an extra block. The box will only go up after loading has ended. Therefore, I need to put a loading animation effect at the bottom of the component by hand, which is the same height as the navigation bar.

You can see the final effect below. The three dots below the blue navigation bar are the native loading of the small program, and the next three dots are the self-written loading.

What we want is that when the native loading of small programs is implemented, the self-written loading can replace the native loading

headerNavbar.js

The status bar height = app. GlobalData. Systeminfo. StatusBarHeight

It should be noted that the origin of the location information of the capsule is in the upper left corner of the page, so it needs to be converted. The original location information of the capsule is named as capsule, and the converted information is called the existing capsule.

/ iphone6 capsule location information * * * * wx. GetMenuButtonBoundingClientRect () coordinate information to the origin of the left upper corner of the screen for the * capsule width: capsule height: 87 * 32 * capsule left boundary coordinates: 278 * Upper boundary coordinates of the capsule: 26 * right boundary coordinates of the capsule: 365 * Lower boundary coordinates of the capsule: 58 * Status bar height: 20*/Copy the code

Present capsule top distance = capsule upper boundary coordinates – status bar height


Present capsule right distance = screen width – capsule right boundary coordinates


Present capsule bottom distance = capsule bottom boundary coordinates – capsule height – status bar height


Navigation bar height = coordinates of the lower boundary of the capsule + the lower distance of the present capsule

Note: The coordinates of the lower boundary of the capsule include the status bar, the height of the capsule and the distance between the status bar and the height of the capsule. Because the capsule is centered in the navigation bar, the upper distance and the lower distance should be the same, so it is the coordinates of the lower boundary of the capsule – the height of the capsule – the height of the status bar.

const app = getApp();
Component({
  properties: {
    navbarData: { // The data passed by the parent page
      type: Object.value: {},
      observer: function (newVal, oldVal) {}}},data: {
    haveBack: true.// Whether there is a return button, true with false no false if entered from the share page
    statusBarHeight: 0.// Status bar height
    navbarHeight: 0.// Top navigation bar height
    navbarBtn: { // Capsule location information
      height: 0.width: 0.top: 0.bottom: 0.right: 0}},/ / WeChat 7.0.0 support wx. GetMenuButtonBoundingClientRect capsule button () to be highly
  attached: function () {
    let statusBarHeight = app.globalData.systeminfo.statusBarHeight // Status bar height
    let headerPosi = app.globalData.headerBtnPosi // Capsule location information
    / * * * wx. GetMenuButtonBoundingClientRect () coordinate information to the origin of the left upper corner of the screen for the * menu button width: 87 * menu button height: 32 * menu buttons left boundary coordinates: 278 * menu button on the boundary coordinates: 26 * Right boundary coordinate of menu button: 365 * Lower boundary coordinate of menu button: 58 */
    let btnPosi = { // The actual location of the capsule, the coordinate information is not the origin of the upper left corner
      height: headerPosi.height,
      width: headerPosi.width,
      // Capsule top - Status bar height
      top: headerPosi.top - statusBarHeight,
      // Capsule bottom - capsule height - status bar height (now capsule bottom is the length from the bottom of the navigation bar)
      bottom: headerPosi.bottom - headerPosi.height - statusBarHeight,
      // Screen width - capsule right
      right: app.globalData.systeminfo.screenWidth - headerPosi.right
    }
    let haveBack;
    if (getCurrentPages().length === 1) { // When there is only one page
      haveBack = false;
    } else {
      haveBack = true;
    }
    this.setData({
      haveBack: haveBack, // Get whether the applets are entered through sharing
      statusBarHeight: statusBarHeight,
      navbarHeight: headerPosi.bottom + btnPosi.bottom, // Original capsule bottom + present capsule bottom
      navbarBtn: btnPosi
    })
  },
  methods: {
    _goBack: function () {
      wx.navigateBack({
        delta: 1
      });
    },
    _goHome: function () {
      wx.switchTab({
        url: '/pages/index/index'}); }}})Copy the code

GetCurrentPages () is used to determine whether the current page is entered from the share page, because if you enter from the share page there should be only one piece of data in the page stack, the length of the page stack increases when you jump to other pages, and the back and home buttons are displayed on other pages.

. Note: WeChat 7.0.0 support wx getMenuButtonBoundingClientRect (), if you want to be compatible with the low version of WeChat, can only write the height of the navigation bar to death, the height of the calculated by some bosses:

‘iPhone’: 64,


‘iPhone X’: 88,


‘android’: 68

Specific view:

https://developers.weixin.qq.com/community/develop/doc/0006c012dc8028f04b070dd0551004

If you use the wx getMenuButtonBoundingClientRect have decimal () to get information, as shown below

{height: 24, width: 65.25, top: -0.5, bottom: -0.5, right: 101.25}

You may have scaled the view in the developer tool and restored it to 100%.

headerNavbar.wxss

.navbar-wrap {
	position: fixed;
	width: 100%;
	top: 0;
	z-index: 9999999;
	background-color: #3281FF;
	box-sizing: border-box;
}

.navbar-text {
	text-align: center;
	font-size: 36rpx;
	color: #fff;
	font-weight: 600;
}

.navbar-icon {
	position: fixed;
	display: flex;
	border-radius: 64rpx;
	border: 0.5 px. solid rgba(255255255, 0.3);box-sizing: border-box;
}

.navbar-icon image {
	height: 20px;
	width: 20px;
	padding: 5px 10px 10px;
	display: inline-block;
	overflow: hidden;
}

.navbar-icon view {
	height: 18px;
	border-left: 0.5 px. solid rgba(255255255, 0.3);margin-top: 6px;
}

.navbar-loading {
	background: #fff;
	text-align: center;
}
Copy the code

Reference component page code

navigationStyle.json

{
    "navigationStyle": "custom"."enablePullDownRefresh": true."backgroundTextStyle": "light"."usingComponents": {
        "headerNavbar": "/components/headerNavbar/headerNavbar"}}Copy the code

Start by adding navigationStyle: Custom to the JSON page where you want to use the custom navigation bar

EnablePullDownRefresh: true Enables the drop-down refresh function

BackgroundTextStyle: Light changes the loading style to white, so that the three loading points will not be displayed

navigationStyle.wxml

<headernavbar navbar-data="{{nvabarData}}"></headernavbar> 
<view class="home-page"> 
   <text>Above that is the custom navigation bar</text> 
   <text>The following is the main content ↓↓↓</text> 
   <navigator url="./testPage">Jump to the test page</navigator> 
</view>
Copy the code

navigationStyle.js

Page({
    data: {
        // Parameters required by the component
        nvabarData: {
            showCapsule: 1.// Whether to display the upper left capsule button 1 displays 0 does not display
            title: 'Component List' // The title in the middle of the navigation bar
        }
    },

    onPullDownRefresh() {
        setTimeout(() = >{
            wx.stopPullDownRefresh(); // Stop the dropdown
        },
        2000); }})Copy the code

Note: although this looks correct in applets, the resulting navigation bar height is 64px, when tested on a real phone, it is still wrong, 60px on the iphone8 plus.

You can obviously see the difference by a few pixels in this image. If you are using custom navigation on several separate pages, careful users may notice it, but it is basically unaffected. This problem does not exist if custom navigation is used globally.

The project code: https://github.com/Shay0921/header-navbar.git