Preface:

Recently in the small program development will encounter the need to customize the navigation bar requirements, small program development platform has long provided this ability, and in the previous project I also mentioned the solution to this problem: wechat small program to achieve the page top navigation bar transparent, hidden effect.

We made some mistakes while developing this part of the function. Here I will summarize the problems I encountered in the development process and provide a complete set of custom navigation bar components, which can be used directly.

Source address: GitHub

I. Problem analysis:

In order to better adapt our project to all models, we need to analyze the following:We can find:

  1. Android and iOS top difference, performance in the top to the capsule button between the distance has a height difference;
  2. The capsule button is 32pt high, the same on iOS and Android.

1. Too many mobile phone models: the height of the custom navigation bar cannot be visually unified in different models

2, the capsule button position is not fixed: navigation bar elements (text, ICONS, etc.) how also on the capsule button

We can use wx.getSystemInfosync () to get the height of the status bar.

Ii. Problem solving:

Overall idea:

  1. When you customize the navigation component, split the component structure into two parts: the status bar and the title bar
  2. Status bar height is passablewx.getSystemInfoSync().statusBarHeightTo obtain
  3. Navigation bar height = capsule button height + distance from status bar to capsule button * 2 (this is the key to customize the navigation bar, need to calculate the height of these two pieces)
  4. Since the capsule button is a native component, for performance consistency, its units are for all systemspx, so our custom navigation bar must be in units of each heightpx(Remember not to use itrpx), to be a perfect fit

Specific configuration:

  1. inapp.jsonwindowObject to define the style of the navigation:

json "window":{ ... "navigationStyle": "custom" }, You will notice that the navigation bar is missing from all pages.

  1. Get the phone system information in the Attached file of index.js to calculate the height of the navigation bar

    attached: function () {
        var that = this;
        that.setNavSize();
        that.setStyle();
    },
    methods: {
        // Calculate the height of the navigation bar by obtaining system information
        setNavSize: function () {
            var that = this
                , sysinfo = wx.getSystemInfoSync()
                , statusHeight = sysinfo.statusBarHeight
                , isiOS = sysinfo.system.indexOf('iOS') > -1
                , navHeight;
            if(! isiOS) { navHeight =48;
            } else {
                navHeight = 44;
            }
            that.setData({
                status: statusHeight,
                navHeight: navHeight
            })
        },
        setStyle: function () {
            var that = this
                , containerStyle
                , textStyle
                , iconStyle;
            containerStyle = [
                'background:' + that.data.background
            ].join('; ');
            textStyle = [
                'color:' + that.data.color,
                'font-size:' + that.data.fontSize + 'px'
            ].join('; ');
            iconStyle = [
                'width: ' + that.data.iconWidth + 'px'.'height: ' + that.data.iconHeight + 'px'
            ].join('; ');
            that.setData({
                containerStyle: containerStyle,
                textStyle: textStyle,
                iconStyle: iconStyle
            })
        },
    Copy the code
  2. Set component WXML:

    <view class='nav' style='height: {{status + navHeight}}px'>
        <view class='status' style='height: {{status}}px; {{containerStyle}}'></view>
        <view class='navbar' style='height:{{navHeight}}px; {{containerStyle}}'>
            <view class='back-icon' wx:if="{{backIcon}}" bindtap='back'>
                <image src='{{backIcon}}'></image>
            </view>
            <view class='home-icon' wx:if="{{homeIcon}}" bindtap='home'>
                <image src='{{homeIcon}}'></image>
            </view>
            <view class='nav-icon' wx:if="{{titleImg}}">
                <image src='{{titleImg}}' style='{{iconStyle}}'></image>
            </view>
            <view class='nav-title' wx:if="{{titleText && ! titleImg}}">
                <text style='{{textStyle}}'>{{titleText}}</text>
            </view>
        </view>
    </view>
    Copy the code

Complete code example (GitHub) :

  1. Components /index.wxml (Component layout)

    <view class='nav' style='height: {{status + navHeight}}px'>
        <view class='status' style='height: {{status}}px; {{containerStyle}}'></view>
        <view class='navbar' style='height:{{navHeight}}px; {{containerStyle}}'>
            <view class='back-icon' wx:if="{{backIcon}}" bindtap='back'>
                <image src='{{backIcon}}'></image>
            </view>
            <view class='home-icon' wx:if="{{homeIcon}}" bindtap='home'>
                <image src='{{homeIcon}}'></image>
            </view>
            <view class='nav-icon' wx:if="{{titleImg}}">
                <image src='{{titleImg}}' style='{{iconStyle}}'></image>
            </view>
            <view class='nav-title' wx:if="{{titleText && ! titleImg}}">
                <text style='{{textStyle}}'>{{titleText}}</text>
            </view>
        </view>
    </view>
    Copy the code
  2. Component JS (component logic and parameter passing)

    Component({
        /** * Component property list */
        properties: {
            background: {
                type: String.value: 'rgba(255, 255, 255, 1)'
            },
            color: {
                type: String.value: 'rgba(0, 0, 0, 1)'
            },
            titleText: {
                type: String.value: 'Navigation bar'
            },
            titleImg: {
                type: String.value: ' '
            },
            backIcon: {
                type: String.value: ' '
            },
            homeIcon: {
                type: String.value: ' '
            },
            fontSize: {
                type: Number.value: 16
            },
            iconHeight: {
                type: Number.value: 19
            },
            iconWidth: {
                type: Number.value: 58}},data: {},attached: function () {
            var that = this;
            that.setNavSize();
            that.setStyle();
        },
        methods: {
            // Calculate the height of the navigation bar by obtaining system information
            setNavSize: function () {
                var that = this
                    , sysinfo = wx.getSystemInfoSync()
                    , statusHeight = sysinfo.statusBarHeight
                    , isiOS = sysinfo.system.indexOf('iOS') > -1
                    , navHeight;
                if(! isiOS) { navHeight =48;
                } else {
                    navHeight = 44;
                }
                that.setData({
                    status: statusHeight,
                    navHeight: navHeight
                })
            },
            setStyle: function () {
                var that = this
                    , containerStyle
                    , textStyle
                    , iconStyle;
                containerStyle = [
                    'background:' + that.data.background
                ].join('; ');
                textStyle = [
                    'color:' + that.data.color,
                    'font-size:' + that.data.fontSize + 'px'
                ].join('; ');
                iconStyle = [
                    'width: ' + that.data.iconWidth + 'px'.'height: ' + that.data.iconHeight + 'px'
                ].join('; ');
                that.setData({
                    containerStyle: containerStyle,
                    textStyle: textStyle,
                    iconStyle: iconStyle
                })
            },
            // Return the event
            back: function () {
                wx.navigateBack({
                    delta: 1
                })
                this.triggerEvent('back', { back: 1})},home: function () {
                this.triggerEvent('home'{}); }}})Copy the code
  3. Component style WXSS

    .navbar{
        position: relative
    }
    .back-icon..home-icon{
        width: 28px;
        height: 100%;
        position: absolute;
        transform: translateY(-50%);
        top: 50%;
        display: flex;
    }
    .back-icon{
        left: 16px;
    }
    .home-icon{
        left: 44px
    }
    .back-icon image{
        width: 28px;
        height: 28px;
        margin: auto;
    }
    .home-icon image{
        width: 20px;
        height: 20px;
        margin: auto;
    }
    .nav-title..nav-icon{
        position: absolute;
        transform: translate(-50%, -50%);
        left: 50%;
        top: 50%;
        font-size: 0;
        font-weight: bold;
    }
    Copy the code
  4. Using the component

    {
      "usingComponents": {
        "navigateBar": ".. /.. /components/navigateBar/index"}}Copy the code
    <navigateBar 
      title-text="Custom navigation bar" 
      back-icon="/images/back.png"
      home-icon="/images/home_icon.png"
      background="#f2f2f2"
      bindback="back"
    />
    Copy the code
  5. Results show

conclusion

After a series of continuous exploration and learning, finally fixed a perfect fit for all types of custom navigation bar, specific complete code has been uploaded to git, welcome everyone star🌟 oh.

If you have a better solution, feel free to leave a comment.

Finally, don’t forget one key three even oh ~ everyone! Come on!