hifive と Onsen UIを組み合わせてスマートフォン/タブレット向けのUIを簡単に実現する(タブ & ナビゲーション)
Onsen UIというモバイルアプリ向けのUIフレームワークがあります。HTML5とJavaScript、CSSを使ってスマートフォンアプリを作るハイブリッドアプリ用のUIフレームワークになります。UIをネイティブアプリ風にしてくれるのはもちろん、画面のスワイプであったり、リスト表示などをネイティブアプリ風の操作にしてくれます。
そんなOnsen UIをhifiveと組み合わせて使う方法を紹介します。今回はタブバーとナビゲーションを組み合わせた使い方を紹介します。

利用するソフトウェア/ライブラリ
- Bower
- hifive
- Onsen UI
- jQuery
インストール
まず各ライブラリをインストールします。インストールはBowerを使って行います。
| $ bower install hifive jquery onsenui --save |
今回は .bowerrc という設定ファイルを作成し、ライブラリのインストール先を指定しています。
| { | |
| "directory": "public/components" | |
| } |
index.htmlの作成
次に public/index.html を作成します。タブバーを定義します。
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
| <title></title> | |
| <meta charset="utf-8" /> | |
| <meta name="description" content="" /> | |
| <meta name="author" content="" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <link rel="stylesheet" href="components/onsenui/css/onsenui.min.css" /> | |
| <link rel="stylesheet" href="components/onsenui/css/onsen-css-components.min.css" /> | |
| <!--[if lt IE 9]> | |
| <script src="//cdn.jsdelivr.net/html5shiv/3.7.2/html5shiv.min.js"></script> | |
| <script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script> | |
| <![endif]--> | |
| <link rel="shortcut icon" href="" /> | |
| </head> | |
| <body> | |
| <ons-page> | |
| <ons-toolbar id="toolbar"> | |
| <div class="center">メイン</div> | |
| </ons-toolbar> | |
| <ons-tabbar swipeable position="auto" id="tabbar"> | |
| <ons-tab page="tab1.html" label="Tab 1" icon="ion-home, material:md-home" badge="7" active> | |
| </ons-tab> | |
| <ons-tab page="tab2.html" label="Tab 2" icon="md-settings" active-icon="md-face"> | |
| </ons-tab> | |
| </ons-tabbar> | |
| </ons-page> | |
| <script src="components/onsenui/js/onsenui.js"></script> | |
| <script src="components/jquery/dist/jquery.min.js"></script> | |
| <script src="components/hifive/ejs-h5mod.js"></script> | |
| <script src="components/hifive/h5.dev.js"></script> | |
| <script src="js/app.js"></script> | |
| </body> | |
| </html> |
タブバーの画面
まず最初に表示される tab1.html の画面を用意します。タブ1の中身でナビゲーションを行いますので、ここではナビゲーションだけを定義します。
| <ons-page id="tab1"> | |
| <ons-navigator swipeable id="tab1nav" page="tab1-main.html"></ons-navigator> | |
| </ons-page> |
そして最初に表示するのは tab1-main.html です。
| <ons-page id="tab1main"> | |
| <p style="text-align: center;"> | |
| <p>ここはメインページです。</p> | |
| <p> | |
| <ons-input id="message" modifier="underbar" placeholder="メッセージ" float></ons-input> | |
| </p> | |
| <ons-button class="btn" modifier="large">詳細画面に移動</ons-button> | |
| </p> | |
| </ons-page> |
JavaScriptの実装
まずメイン画面でボタンを押したら詳細画面に移動する部分を作ります。 tab1MainController を定義します。そしてナビゲーションのpushPageを使って画面遷移します。
ここでヘッダー部の文字を詳細に変えるようにイベントを設定します。コントローラのトリガーを使います。
| <ons-page id="tab1main"> | |
| <p style="text-align: center;"> | |
| <p>ここはメインページです。</p> | |
| <p> | |
| <ons-input id="message" modifier="underbar" placeholder="メッセージ" float></ons-input> | |
| </p> | |
| <ons-button class="btn" modifier="large">詳細画面に移動</ons-button> | |
| </p> | |
| <script> | |
| ons.getScriptPage().onInit = function() { | |
| const tab1MainController = { | |
| __name: 'Tab1MainController', | |
| '.btn click'() { | |
| this.trigger('changeTitle', { | |
| back: true, | |
| title: '詳細' | |
| }); | |
| $('#tab1nav')[0].pushPage('tab1-detail.html', { | |
| message: this.$find('#message').val() | |
| }); | |
| } | |
| }; | |
| h5.core.controller('#tab1main', tab1MainController); | |
| } | |
| </script> | |
| </ons-page> |
トリガーは js/app.js 内に定義する全体のコントローラに実装します。 {rootElement} changeTitle でイベントを受け取ることができます。
| const appController = { | |
| __name: 'AppController', | |
| _tab1Controller: Tab1Controller, | |
| _tab2Controller: Tab2Controller, | |
| __ready() { | |
| }, | |
| '{rootElement} changeTitle'(context) { | |
| let back = ''; | |
| if (context.evArg.back) { | |
| back = `<div class="left"> | |
| <ons-back-button id="backButton">Back</ons-back-button> | |
| </div>`; | |
| } | |
| const outerHTML = ons.createElement(` | |
| <ons-toolbar id="toolbar"> | |
| ${back} | |
| <div class="center">${context.evArg.title}</div> | |
| </ons-toolbar> | |
| `); | |
| this.$find('#toolbar').prop('outerHTML', outerHTML.outerHTML); | |
| }, | |
| '#tabbar prechange'() { | |
| this.trigger('changeTitle', { | |
| title: "メイン", | |
| back: false | |
| }); | |
| } | |
| }; | |
| h5.core.controller('body', appController); |
なお、 Tab1Controller と Tab2Controller は別な画面に定義されています。そのため、変数が定義されているかどうかを確認する必要があります。今回は以下のような仕組みで回避しています。変数があるかどうか調べて、なければ100ms待って変数の確認をしています。
| ons.ready(() => { | |
| resolveVariable(['Tab1Controller', 'Tab2Controller']) | |
| .then(() => { | |
| // 変数定義済み | |
| }); | |
| }); | |
| const resolveVariable = (ary) => { | |
| return new Promise((res, rej) => { | |
| setTimeout(() => { | |
| let bol = true; | |
| for (let index in ary) { | |
| if (!(ary[index] in window)) { | |
| bol = false; | |
| return resolveVariable(ary) | |
| } | |
| } | |
| if (bol) res(); | |
| }, 100); | |
| }) | |
| } |
画面遷移を戻る
詳細画面に移動したら、逆に戻ってくる処理を作ります。これは tab1-detail.html に実装します。こちらでもトリガーを使っています。
| <ons-page id="tab1detail"> | |
| <p style="text-align: center;"> | |
| こちらは詳細画面です | |
| <ons-button class="btn" modifier="large">戻る</ons-button> | |
| </p> | |
| <script> | |
| ons.getScriptPage().onInit = function() { | |
| const tab1DetailController = { | |
| __name: 'Tab1DetailController', | |
| '.btn click'() { | |
| this.trigger('changeTitle', { | |
| back: false, | |
| title: 'メイン' | |
| }); | |
| $('#tab1nav')[0].popPage(); | |
| } | |
| }; | |
| h5.core.controller('#tab1detail', tab1DetailController); | |
| } | |
| </script> | |
| </ons-page> |
ここまでの処理でタブバーとナビゲーションバーを組み合わせた処理が実現します。

タブバーとナビゲーションバーを組み合わせた動きはスマートフォンアプリでよくある実装だと思います。hifiveのコントローラ連携を使うことで、機能を画面毎に分けつつ、分かりやすい実装が実現します。
コードはhifiveWithOnsenUI/tabbar_navigation at master · hifivemania/hifiveWithOnsenUIにアップロードされています。実装時の参考にしてください。
コメントは受け付けていません。