Onsen UI 2 + Monacaで洋服管理アプリ作ってみたメモ


超便利なUIフレームワークOnsen UIを使って洋服管理アプリを作ってみたので、感想やハマりポイントなどを書いてみようと思います。

Onsen UIとは?

独自のタグを埋めるだけでネイティブアプリっぽいUIを作ることができるライブラリです。
私はデザインがまったくできないので、タグの組み合わせだけで見栄えするUIが作れるのはとても助かります。

使い方は公式サイトの、チュートリアルページが一番わかりやすいです。

最近リリースされたOnsen UI 2からは、OSに合わせて自動的にスタイルが変化する機能が追加されていて、これがすごい!

こんな感じになります。

iOS(フラットデザイン)

Android(マテリアルデザイン)

(Onsen UIで作ったソースコードをMonacaでスマホアプリ化しています。)

これぜんぶワンソースで作られてます。
ただし登録ボタン(⊕ボタン)はiOSの場合ツールバー上のポップオーバー、Androidの場合フローティングアクションボタンのスピードダイヤルとして実装しているので、
そこだけはOSの種類を見て切り分けるようにしています。

iOS
<ons-if platform="ios">
  <ons-toolbar-button onclick="getElementById('popover').show(this)">
    <ons-icon icon="ion-ios-plus-outline"></ons-icon>
  </ons-toolbar-button>
</ons-if>

<ons-popover id="popover" cancelable direction="down">
 <ons-row>
  <ons-col class="menu-item-col">
    <span class="icon-item"></span>
    <div class="menu-item-label">アイテム登録</div>
  </ons-col>
  <ons-col class="menu-item-col">
    <span class="icon-coordinate"></span>
    <div class="menu-item-label">コーデ登録</div>
  </ons-col>
 </ons-row>
</ons-popover>
Android
<ons-if platform="android">
  <ons-speed-dial position="bottom center" direction="up">
    <ons-fab>
      <ons-icon icon="plus" size="20px"></ons-icon>
    </ons-fab>
    <ons-speed-dial-item>
      <span class="icon-item"></span>        
      <div class="fab-label">アイテム登録</div>
    </ons-speed-dial-item>        
    <ons-speed-dial-item>
      <span class="icon-coordinate"></span>      
      <div class="fab-label">コーデ登録</div>
    </ons-speed-dial-item>
  </ons-speed-dial>
</ons-if>

ハマったポイント

チュートリアルページを見れば、それぞれのコンポーネントの使い方はすぐにわかります。
ただ、複数のコンポーネントを組み合わせる方法がよくわからず悩みました。
今回作ったアプリは以下のような構造になっているのですが、これがなかなか作れない!

まずは単純に、以下のように <ons-toolbar><ons-tabbar> を両方index.html内に書いてみました。

index.html
<body>
  <ons-toolbar>
    <div class="center">Onsen Closet</div>
    <div class="right">
      <ons-if platform="ios">
        <ons-toolbar-button onclick="getElementById('popover').show(this)">
          <ons-icon icon="ion-ios-plus-outline"></ons-icon>
        </ons-toolbar-button>
      </ons-if>
    </div>
  </ons-toolbar>

  <ons-tabbar position="top" id="tabbar">
    <ons-tab page="top.html" active>
      <span>Top</span>
    </ons-tab>
    <ons-tab page="my_item.html">
      <span>Myアイテム</span>
    </ons-tab>
    <ons-tab page="my_coordinate.html">
      <span>Myコーデ</span>
    </ons-tab>
  </ons-tabbar>
</body>

結果その1

むむ……タブバーの上にツールバーが重なって描画されてしまいました……

チュートリアルページを確認すると、まず最初に読み込まれるHTMLファイルに <ons-tabbar> を配置して、<ons-tab> の参照先HTMLファイルに <ons-toolbar> が配置されていました。

とりあえずチュートリアルを真似てみます。

index.html
<body>
  <ons-tabbar position="bottom" id="tabbar">
    <ons-tab page="top.html" active>
      <span>Top</span>
    </ons-tab>
    <ons-tab page="my_item.html">
      <span>Myアイテム</span>
    </ons-tab>
    <ons-tab page="my_coordinate.html">
      <span>Myコーデ</span>
    </ons-tab>
  </ons-tabbar>
</body>
top.html
<ons-page>
  <ons-toolbar>
    <div class="center">Onsen Closet</div>
    <div class="right">
      <ons-if platform="ios">
        <ons-toolbar-button onclick="getElementById('popover').show(this)">
          <ons-icon icon="ion-ios-plus-outline"></ons-icon>
        </ons-toolbar-button>
      </ons-if>
    </div>
  </ons-toolbar>

  <h1>今日のおすすめ<br>コーディネート</h1>
  <!-- 以下省略 -->
</ons-page>

結果その2

おお、両方描画されました。タブバーは上部に置きたいので、 <ons-tabbar>position プロパティを top に変更します。

  <ons-tabbar position="top" id="tabbar">

結果その3

ツールバーを上にしたいのおおお!

で、いろいろ悩んだ結果、以下のようにすると実現できました。

index.html
<body>
  <ons-navigator id="navi" page="tabbar.html">
  </ons-navigator>
</body>
tabbar.html
<ons-page>
  <ons-toolbar>
    <div class="center">Onsen Closet</div>
    <div class="right">
      <ons-if platform="ios">
        <ons-toolbar-button onclick="getElementById('popover').show(this)">
          <ons-icon icon="ion-ios-plus-outline"></ons-icon>
        </ons-toolbar-button>
      </ons-if>
    </div>
  </ons-toolbar>

  <ons-tabbar position="top" id="tabbar">
    <ons-tab page="top.html" active>
      <span>Top</span>
    </ons-tab>
    <ons-tab page="my_item.html">
      <span>Myアイテム</span>
    </ons-tab>
    <ons-tab page="my_coordinate.html">
      <span>Myコーデ</span>
    </ons-tab>
  </ons-tabbar>
</ons-page>
top.html
<ons-page>
  <h1>今日のおすすめ<br>コーディネート</h1>
  <!-- 以下省略 -->
</ons-page>

結果その4

<ons-navigator> というのは複数のページを管理する役割を持つコンポーネントで、これを最上位に配置することで実現できました。

2016/12/20 追記

実は次のように、<ons-page> 内に <ons-toolbar><ons-tabbar> を含めるだけで意図した通りにツールバーとタブバーを描画することができます。
(GIFアニメを見てもらうとわかりますが、このアプリでは次のページに遷移した場合にはタブを消したかったので、最上位に <ons-navigator> を配置しています。)

index.html
<body>
 <ons-page>
  <ons-toolbar>
    <div class="center">Onsen Closet</div>
    <div class="right">
      <ons-if platform="ios">
        <ons-toolbar-button onclick="getElementById('popover').show(this)">
          <ons-icon icon="ion-ios-plus-outline"></ons-icon>
        </ons-toolbar-button>
      </ons-if>
    </div>
  </ons-toolbar>

  <ons-tabbar position="top" id="tabbar">
    <ons-tab page="top.html" active>
      <span>Top</span>
    </ons-tab>
    <ons-tab page="my_item.html">
      <span>Myアイテム</span>
    </ons-tab>
    <ons-tab page="my_coordinate.html">
      <span>Myコーデ</span>
    </ons-tab>
  </ons-tabbar>
 </ons-page>
</body>

まとめ

Onsen UIを使いこなすには各コンポーネントの特性を深く理解する必要があるものの、とにかく手軽にUIが作れるので感動しました!
HTML5モバイルアプリ/モバイルサイトを素早く実装したいなら、Onsen UIを使わない手はありません!
みなさんもぜひ試してみてくださいね。

この記事は、Onsen UI Advent Calendar 2016 の2日目の記事として作成しました。
それでは、Have a Merry Christmas☆