[blame upgrade] applet custom head navigation bar "perfect" solution

Keywords: Javascript JSON Mobile Android Attribute

Why do you do this?

Mainly in the project, some problems found by zhikujun

  • Some pages are accessed by scanning codes and subscribing to messages. There is no direct way to click to go to the home page. You need to add a home link.
  • Need to add custom search feature
  • Some function buttons need to be customized

In fact, the first problem has been optimized in the latest wechat version update. If you come from the applet template message, the system will automatically add the home button, but there is no support for other access methods.~

A small problem: the problem of misaligned ICON on both sides

Zhikujun has tried various solutions before, and found that there is a problem, that is, there are too many kinds of mobile screens, such as traditional head, wide / narrow banged screen, water drop screen, etc., there are no eight doors, many solutions are unable to solve the special head, the system "capsule button" and custom button may have several pixels misaligned on the Android screen (nightmare of obsessive-compulsive disorder) )

Here is the next relatively complete solution:

Snippet DEMO

Link: https://developers.weixin.qq....
ID: cuUaCimT72cH

Zhikujun has made a demo code segment, which is convenient for you to view the source code directly with IDE tool.~

Page configuration

1. Page JSON configuration
{
  "usingComponents": {
    "NavComponent": "/components/nav/common"  //Introduced as a plug-in
  },
  "navigationStyle": "custom"  //Custom header needs to be set
}

If you need to customize the header, you need to set navigationStyle to "custom"

2. Page code
<!-- home Type of menu -->
<NavComponent v-title="Custom header" bind:commonNavAttr="commonNavAttr"></NavComponent>
<!-- Search menu -->
<NavComponent is-search="true" bind:commonNavAttr="commonNavAttr"></NavComponent>

You can add the attribute configuration to the custom navigation tab to set the function, as required.

3. Directory structure
│
├─components
│  └─nav
│          common.js
│          common.json
│          common.wxml
│          common.wxss
│
├─images
│      back.png
│      home.png
│
└─index
        index.js
        index.json
        index.wxml
        index.wxss
        search.js
        search.json
        search.wxml
        search.wxss

For reference only

JS part of plug-in

components/nav/common.js section
const app = getApp();
Component({
  properties: {
    vTitle: {
      type: String,
      value: ""
    },
    isSearch:{
      type: Boolean,
      value: false
    }
  },
  data: {
    haveBack: true, // Whether there is a return button, true whether there is false no return button if you enter from the sharing 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
    },
    cusnavH: 0, //title height
  },
  // Wechat 7.0.0 supports wx.getMenuButtonBoundingClientRect() to get the height of capsule button
  attached: function () {
    if (!app.globalData.systeminfo) {
      app.globalData.systeminfo = wx.getSystemInfoSync();
    }
    if (!app.globalData.headerBtnPosi) app.globalData.headerBtnPosi = wx.getMenuButtonBoundingClientRect();
    console.log(app.globalData)
    let statusBarHeight = app.globalData.systeminfo.statusBarHeight // Status bar height
    let headerPosi = app.globalData.headerBtnPosi // Capsule location information
    console.log(statusBarHeight)
    console.log(headerPosi)
    let btnPosi = { // The actual position of the capsule, coordinate information is not the origin of the upper left corner
      height: headerPosi.height,
      width: headerPosi.width,
      top: headerPosi.top - statusBarHeight, // Capsule top - status bar height
      bottom: headerPosi.bottom - headerPosi.height - statusBarHeight, // Capsule bottom - capsule height - status bar height (capsule actual bottom is the length from the bottom of the navigation bar)
      right: app.globalData.systeminfo.windowWidth - headerPosi.right // The screen width cannot be obtained here. There will be BUG when opening the applet on the PC side. To obtain the window height - capsule right
    }
    let haveBack;
    if (getCurrentPages().length != 1) { // When there is only one page, and it is from the sharing page.
      haveBack = false;
    } else {
      haveBack = true;
    }
    var cusnavH = btnPosi.height + btnPosi.top + btnPosi.bottom // Navigation height
    console.log( app.globalData.systeminfo.windowWidth, headerPosi.width)
    this.setData({
      haveBack: haveBack, // Get whether the applet is entered through sharing
      statusBarHeight: statusBarHeight,
      navbarHeight: headerPosi.bottom + btnPosi.bottom, // Capsule bottom + capsule actual bottom
      navbarBtn: btnPosi,
      cusnavH: cusnavH
    });
    //Pass the actual nav height to the parent page
    this.triggerEvent('commonNavAttr',{
      height: headerPosi.bottom + btnPosi.bottom
    });
  },
  methods: {
    _goBack: function () {
      wx.navigateBack({
        delta: 1
      });
    },
    bindKeyInput:function(e){
      console.log(e.detail.value);
    }
  }
})

The ultimate solution to different screen head misalignments is wx.getMenuButtonBoundingClientRect()
This method starts from wechat 7.0.0. Through this method, we can get the top, height, right and other attributes of the right system capsule, so that whether it is the water drop screen, the Liu Hai screen or the alien screen, it can perfectly align the default capsule bar of the right system, and perfectly cure obsessive-compulsive disorder.~

APP.js
//app.js
App({
  /**
   * Loading page
   * @param {*} options 
   */
  onShow: function (options) {
   
  },
  onLaunch: async function () {
    let self = this;

    //Set default share
    this.globalData.shareData = {
      title: "Zhiku equation"
    }

    // this.getSysInfo();
  },
  globalData: {
    //Default shared copy
    shareData: {},
    qrCodeScene: false, //QR code scanning into parameter transmission
    systeminfo: false,   //system information
    headerBtnPosi: false,  //Head menu height
  }
});

Storing the obtained parameters in a global variable, globalData, can reduce the performance consumption of repeated calls.

Plug in HTML section

<view class="custom_nav" style="height:{{navbarHeight}}px;">
    <view class="custom_nav_box" style="height:{{navbarHeight}}px;">
        <view class="custom_nav_bar" style="top:{{statusBarHeight}}px; height:{{cusnavH}}px;">
            <!-- Search part-->
            <block wx:if="{{isSearch}}">
                <input class="navSearch"
                    style="height:{{navbarBtn.height-2}}px;line-height:{{navbarBtn.height-4}}px; top:{{navbarBtn.top+1}}px; left:{{navbarBtn.right}}px; border-radius:{{navbarBtn.height/2}}px;"
                    maxlength="10" bindinput="bindKeyInput" placeholder="Enter text search" />
            </block>
            <!-- HOME Part-->
            <block wx:else>
                <view class="custom_nav_icon {{!haveBack||'borderLine'}}"
                    style="height:{{navbarBtn.height}}px;line-height:{{navbarBtn.height-2}}px; top:{{navbarBtn.top}}px; left:{{navbarBtn.right}}px; border-radius:{{navbarBtn.height/2}}px;">
                    <view wx:if="{{haveBack}}" class="icon-back" bindtap='_goBack'>
                        <image src='/images/back.png' mode='aspectFill' class='back-pre'></image>
                    </view>
                    <view wx:if="{{haveBack}}" class='navbar-v-line'></view>
                    <view class="icon-home">
                        <navigator class="home_a" url="/pages/home/index" open-type="switchTab">
                            <image src='/images/home.png' mode='aspectFill' class='back-home'></image>
                        </navigator>
                    </view>
                </view>
                <view class="nav_title" style="height:{{cusnavH}}px; line-height:{{cusnavH}}px;">
                    {{vTitle}}
                </view>
            </block>
        </view>
    </view>
</view>

It is mainly the judgment of several States and the calculation of positioning.

Plug in CSS section

/* components/nav/test.wxss */
.custom_nav {
    width: 100%;
    background: #3a7dd7;
    position: relative;
    z-index: 99999;
}
.custom_nav_box {
    position: fixed;
    width: 100%;
    background: #3a7dd7;
    z-index: 99999;
    border-bottom: 1rpx solid rgba(255, 255, 255, 0.3);
}
.custom_nav_bar {
    position: relative;
    z-index: 9;
}
.custom_nav_box .nav_title {
    font-size: 28rpx;
    color: #fff;
    text-align: center;
    position: absolute;
    max-width: 360rpx;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    z-index: 1;
}
.custom_nav_box .custom_nav_icon {
    position:absolute;
    z-index: 2;
    display: inline-block;
    border-radius: 50%;
    vertical-align: top;
    font-size:0;
    box-sizing: border-box;
}
.custom_nav_box .custom_nav_icon.borderLine {
    border: 1rpx solid rgba(255, 255, 255, 0.3);
    background: rgba(0, 0, 0, 0.1);
}
.navbar-v-line {
    width: 1px;
    margin-top: 14rpx;
    height: 32rpx;
    background-color: rgba(255, 255, 255, 0.3);
    display: inline-block;
    vertical-align: top;
}
.icon-back {
    display: inline-block;
    width: 74rpx;
    padding-left: 20rpx;
    vertical-align: top;
    /* margin-top: 12rpx;
    vertical-align: top; */
    height: 100%;
}
.icon-home {
    /* margin-top: 8rpx;
    vertical-align: top; */
    display: inline-block;
    width: 80rpx;
    text-align: center;
    vertical-align: top;
    height: 100%;
}
.icon-home .home_a {
    height: 100%;
    display: inline-block;
    vertical-align: top;
    width: 35rpx;
}
.custom_nav_box .back-pre,
.custom_nav_box .back-home {
    width: 35rpx;
    height: 35rpx;
    vertical-align: middle;
}
.navSearch {
  width: 200px;
  background: #fff;
  font-size: 14px;
  position: absolute;
  padding: 0 20rpx;
  z-index: 9;
}

summary

  • Through wechat API:

getMenuButtonBoundingClientRect() results the screen adaptation of various mobile phones

  • The calculated parameters are stored in the global variables, which are used for global calculation once.~

Previous review:

Posted by ErcFrtz on Tue, 22 Oct 2019 01:09:19 -0700