微信小程序におけるカスタムナビゲーションバーの実装

微信のナビゲーションバーは、JSON設定によりカスタマイズできますが、プロジェクトの要件によっては独自のナビゲーションバーが必要になる場合があります。以下のようなデザインの場合を想定します。

以下の手順に従って実装を行います。

実装手順:

1. app.json の "navigationStyle" を "custom" に変更

この設定を行うことで、ナビゲーションバーは右上の胶囊ボタンのみが残ります。

2. 各種値の計算

端末ごとにナビゲーションバーの高さが異なるため、複数の端末に対応するために以下の3つの値を計算する必要があります:

  1. ナビゲーションバー全体の高さ
  2. 胶囊ボタンから上部までの距離
  3. 胶囊ボタンから右端までの距離

微信では wx.getMenuButtonBoundingClientRect() で胶囊ボタンの情報を取得し、wx.getSystemInfo() で端末情報を取得できます。

これらの情報をもとに以下の式で計算します:

  1. ナビゲーションバーの高さ = statusBarHeight + height + (top - statusBarHeight) * 2
  2. 胶囊ボタンから上部までの距離 = top
  3. 胶囊ボタンから右端までの距離 = windowWidth - right

上記の式における2倍の係数は、表示領域の調整のためです。

App.js のコード例は以下の通りです:

App({
  globalData: {},
  onLaunch: function () {
    let menuButtonObject = wx.getMenuButtonBoundingClientRect();
    wx.getSystemInfo({
      success: res => {
        let statusBarHeight = res.statusBarHeight,
          navTop = menuButtonObject.top,
          navHeight = statusBarHeight + menuButtonObject.height + (menuButtonObject.top - statusBarHeight) * 2;
        this.globalData.navHeight = navHeight;
        this.globalData.navTop = navTop;
        this.globalData.windowHeight = res.windowHeight;
      },
      fail(err) {
        console.log(err);
      }
    })
  }
})

3. 共通コンポーネントとしてナビゲーションバーを作成

コンポーネント名は「navbar」とします。

index.wxml:

<view class="navbar custom-class" style='height:{{navHeight}}px;background-color:{{bgColor}}'>
  <view wx:if="{{showNav}}" class="navbar-action-wrap navbar-action-group row item-center" style='top:{{navTop}}px;background-color:rgba(255,255,255,.6)'>
    <ss-icon name="back" color="{{iconColor}}" size="15px" block="{{true}}" class="navbar-action_item" bind:click="_navBack"></ss-icon>
    <ss-icon name="index" color="{{iconColor}}" size="15px" block="{{true}}" class="navbar-action_item last" bind:click="_toIndex"></ss-icon>
  </view>
  <view class='navbar-title' style='top:{{navTop}}px'>
    {{pageName}}
  </view>
</view>

index.js:

// components/navbar/index.js
const App = getApp();

Component({
  options: {
    addGlobalClass: true,
  },
  properties: {
    pageName: String,
    showNav: {
      type: Boolean,
      value: true
    },
    showHome: {
      type: Boolean,
      value: true
    }
  },

  data: {},

  lifetimes: {
    attached: function () {
      this.setData({
        navH: App.globalData.navHeight
      })
    }
  },

  methods: {
    navBack: function () {
      wx.navigateBack({
        delta: 1
      })      
    },
    toIndex: function () {
      wx.navigateTo({
        url: '/pages/admin/home/index/index'
      })
    },
  }
})

index.wxss:

/* components/navbar/index.wxss */

.navbar {
  width: 100%;
  overflow: hidden;
  position: relative;
  top: 0;
  left: 0;
  z-index: 10;
  flex-shrink: 0;
}

.navbar-title {
  width: 100%;
  box-sizing: border-box;
  padding-left: 115px;
  padding-right: 115px;
  height: 32px;
  line-height: 32px;
  text-align: center;
  position: absolute;
  left: 0;
  z-index: 10;
  color: #333;
  font-size: 16px;
  font-weight: bold;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}

.navbar-action-wrap {
  display: -webkit-flex;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  -webkit-align-items: center;
  align-items: center;
  position: absolute;
  left: 10px;
  z-index: 11;
  line-height: 1;
  padding-top: 4px;
  padding-bottom: 4px;
}

.navbar-action-group {
  border: 1px solid #f0f0f0;
  border-radius: 20px;
  overflow: hidden;
}

.navbar-action_item {
  padding: 3px 0;
  color: #333;
}

.navbar-action-group .navbar-action_item {
  border-right: 1px solid #f0f0f0;
  padding: 3px 14px;
}

.navbar-action-group .last {
  border-right: none;
}

index.json:

{
  "component": true,
  "usingComponents": {
    "ss-icon": "../icon/index"
  }
}

ss-icon はカスタムアイコンコンポーネントであり、必要に応じて他のアイコンコンポーネントに置き換え可能です。

コンポーネントの使用方法:

例えば index.wxml でこのコンポーネントを使用する場合:

1. index.json でコンポーネントをインポート:

{
  "usingComponents": {
    "navbar": "/components/navbar/index"
  }
}

2. index.wxml でコンポーネントを呼び出す:

<view class='view-page'>
  <navbar page-name="ページ名"></navbar>
  <view class='page-content'>
    <!-- コンテンツ -->
  </view>
</view>

最終的な表示結果は以下のようになります。

3. パラメータ一覧

パラメータ 説明 初期値
page-name ページ名 String --
show-nav 左側のアイコンボタンの表示 Boolean true
bg-color ナビゲーション背景色 String #fff
icon-color アイコン色 String #000
custom-class ナビゲーションスタイル

GitHubリポジトリ:微信小程序カスタムナビゲーションバー

タグ: 微信小程序 ナビゲーションバー カスタムUI コンポーネント開発 wxss

7月15日 00:05 投稿