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

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

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

使い方は[公式サイト](https://ja.onsen.io/)の、[チュートリアル](https://ja.onsen.io/tutorial/)ページが一番わかりやすいです。


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

こんな感じになります。

### iOS（フラットデザイン）
![iOS](https://qiita-image-store.s3.amazonaws.com/0/152304/d0e1a456-173f-226c-cdf9-a3dbe6a111fb.gif)

### Android（マテリアルデザイン）
![Android](https://qiita-image-store.s3.amazonaws.com/0/152304/4aed2026-f183-01cf-9d7c-cb35233847c2.gif)

（Onsen UIで作ったソースコードを[Monaca](https://ja.monaca.io/)でスマホアプリ化しています。）


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

```html: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>
```


```html: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>
```

# ハマったポイント
[チュートリアル](https://ja.onsen.io/tutorial/)ページを見れば、それぞれのコンポーネントの使い方はすぐにわかります。
ただ、複数のコンポーネントを組み合わせる方法がよくわからず悩みました。
今回作ったアプリは以下のような構造になっているのですが、これがなかなか作れない！

<img width="255" alt="完成イメージ.png" src="https://qiita-image-store.s3.amazonaws.com/0/152304/72a9a732-9be6-b570-30db-cd5831430851.png">


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

```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](https://qiita-image-store.s3.amazonaws.com/0/152304/e949a183-a5a0-2454-6d0f-cd03b29e573c.jpeg)

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

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

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

```html: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>
```
```html: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](https://qiita-image-store.s3.amazonaws.com/0/152304/f06fa22a-3e23-50d8-03cf-907ab5fa370a.jpeg)


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

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

### 結果その３
![結果3](https://qiita-image-store.s3.amazonaws.com/0/152304/6f022d65-5732-e376-96cd-44e17fe80a32.jpeg)

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

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

```html:index.html
<body>
  <ons-navigator id="navi" page="tabbar.html">
  </ons-navigator>
</body>
```

```html: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>
```

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

### 結果その４
![結果4](https://qiita-image-store.s3.amazonaws.com/0/152304/413d75ae-8429-e7ff-e136-49ce5b88c95a.jpeg)

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

### 2016/12/20 追記

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

```html: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](http://qiita.com/advent-calendar/2016/onsenui) の2日目の記事として作成しました。
それでは、Have a Merry Christmas☆