SvelteとIonicで始めるモバイルアプリケーション開発入門 Part2. アプリケーション開発編(レイアウト)
IonicのComponentを使ったアプリケーション開発
はじめに
この記事は前回の記事の続きとなります。
前回の記事では、Svelteのプロジェクトを作成し、Ionic Framework(以下、Ionic)を導入しました。
今回は、Ionicの主要なComponentを使って、モバイルアプリの基礎的なレイアウトを実装していきます。
IonicのComponentについて
前提
前回の記事にも記載しましたが、IonicのComponentを使う際には、各ComponentのdefineCustomElement関数を実行する必要があります。
内部的には、おそらく以下のような処理が実行されており、Custom Elementsとして利用できるようになっているのではないかと思います。
customElements.define("ion-xxx", Component);
詳しくはIonicのComponentの開発に使われている、Stencilの実装を見れば分かりそうですね。
main.tsの初期化処理に、利用したいComponentの定義を追加するのを忘れないようにしましょう。
(例)ion-appの場合
/** 全Componentで同じ関数名が使われているため as xxx で別名に変更している*/
import { defineCustomElement as defineCustomElementIonApp } from '@ionic/core/components/ion-app'
/** 変更後の名称で defineCustomElement関数を実行 */
defineCustomElementIonApp()
ここからは、いくつかの主要なComponentについて紹介していきたいと思います。事前に公式のドキュメントを読んでおくと、より理解が深まるのではないかと思います。
Content
ion-app
ion-appは、アプリケーションのコンテナとなる要素です。
アプリケーション内に1つだけ定義します。基本的にはbody直下に置いておけば良いでしょう。この要素の中に、その他の様々な要素を追加していきます。
ion-appの直下に定義するのは、主にion-header, ion-content, ion-footerの3つのComponentになりますが、ion-madalやion-action-sheetなどの動的なオーバーレイ要素も、ion-appの直下にDOMが生成されるようになっています。
<body>
<ion-app>
<!-- ここに追加していく -->
</ion-app>
</body>
ion-content
ion-contentはスクロール可能なコンテンツ領域を描画するためのコンテナです。基本的に、ページ内の要素はこの中に書いていくことが多くなるかと思います。
以下のコードでは、ion-contentにion-paddingというCSSのclassを適用していますが、これは前の記事で紹介した、グローバルスタイルシートに定義されているclassです。これにより、ion-contentにpaddingが付与されています。
<ion-app>
<ion-content class="ion-padding">
<h1>タイトル</h1>
<h2>サブタイトル</h2>
<p>本文</p>
</ion-content>
</ion-app>
Toolbar
ion-header, ion-toolbar, ion-title
どんどん見た目をアプリっぽくしていきましょう。
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>タイトル</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<h1>タイトル</h1>
<h2>サブタイトル</h2>
<p>本文</p>
</ion-content>
</ion-app>
ion-headerは、文字通り、ヘッダーを作るための要素です。ion-appの直下に設置します。また、ion-headerは子要素にion-toolbarを持ちます。
ion-toolbarはion-buttons, ion-back-buton, ion-titleなどを子要素に持ち、モバイルアプリで一般的によく使われるヘッダーのレイアウトを簡単に再現することができます。
上記のコードで、以下の画像のようにヘッダーが追加されました。
さらに、少しコードを追加します。(変更箇所のみ抜粋)
<ion-app>
<!-- headerを透過させる (iOSのみ有効) -->
<ion-header translucent ></ion-header>
<!-- ion-contentがheaderの下に潜り込めるようにする -->
<ion-content class="ion-padding" fullscreen></ion-content>
</ion-app>
<style>
/** 透過をわかりやすくするために、0.1に設定 */
ion-toolbar {
/** CSSカスタムプロパティに値を渡す */
--opacity: 0.1;
}
/** 透過をわかりやすくするために、文字色を赤に設定 */
h1, h2 {
color: red;
font-weight: bold;
}
/** content領域がスクロールするように高さを付与 */
p {
height: 100vh;
}
</style>
ion-headerにtranslucentを、ion-contentにfullscreenを設定することで、コンテンツのスクロール領域がフルスクリーンとなり、コンテンツ領域をスクロールした際に、ヘッダーの下に潜り込むような表現が可能になります。
上のコードでは省略していますが、それぞれのプロパティにtrueが渡されています。この設定はiOSのみ有効になっており、よりネイティブに近いデザインで実装することができます。
また、styleタグ(SvelteのCSS定義)の中で、ion-toolbarの — opacityに0.1という値を設定していますが、IonicのComponentの一部の構成要素は、CSSカスタムプロパティ(CSS変数)でスタイルが定義されているため、値を渡すだけで簡単に見た目を整えることができます。
今回は以下のように、ヘッダーの透過をわかりやすくするために0.1を設定しました。
以下の画像は、Ionicの公式ドキュメントの実装例です。このように、複数のComponentを組み合わせることによって、リッチなレイアウトを簡単に実装することができます。
Tabs
ion-tabs, ion-tab, ion-tab-bar, ion-tab-button
次に紹介するのはタブベースのルーティング機能です。俗に言うボトムタブですね。今や、ほとんどのアプリで採用されているレイアウトかと思います。
コードを見ながらの方がイメージしやすいかと思いますので、先に実装サンプルをご覧ください。
まず、タブ内に表示するページのコンテナとなるComponentを作成します。
<!-- Page.svelte -->
<script lang="ts">
export let title: string
export let content: string
</script>
<ion-header>
<ion-toolbar>
<ion-title>{title}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<div>
<h1>{title}</h1>
<p>{content}</p>
</div>
</ion-content>
そして、App.svelteを次のように書き換えてみましょう。
<!-- App.svelte -->
<script lang="ts">
import * as icons from 'ionicons/icons'
import Page from './Page.svelte'
</script>
<ion-app>
<!-- タブのコンテナ -->
<ion-tabs>
<!-- 各タブ画面 (tabの値が一意になるように設定する) -->
<ion-tab tab="tab-home">
<Page title="ホーム" content="ホーム画面" />
</ion-tab>
<ion-tab tab="tab-search">
<Page title="検索" content="検索画面" />
</ion-tab>
<ion-tab tab="tab-fab">
<Page title="お気に入り" content="お気に入り画面" />
</ion-tab>
<ion-tab tab="tab-settings">
<Page title="設定" content="設定画面" />
</ion-tab>
<!-- タブバー -->
<ion-tab-bar slot="bottom">
<!-- タブボタン (tabの値をion-tabと揃える) -->
<ion-tab-button tab="tab-home">
<ion-icon icon={icons.home}></ion-icon>
<ion-label>ホーム</ion-label>
</ion-tab-button>
<ion-tab-button tab="tab-search">
<ion-icon icon={icons.search}></ion-icon>
<ion-label>検索</ion-label>
</ion-tab-button>
<ion-tab-button tab="tab-fab">
<ion-icon icon={icons.heart}></ion-icon>
<ion-label>お気に入り</ion-label>
</ion-tab-button>
<ion-tab-button tab="tab-settings">
<ion-icon icon={icons.settings}></ion-icon>
<ion-label>設定</ion-label>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
</ion-app>
繰り返しになりますが、main.tsに使いたいComponentのdefine関数を追加するのを忘れないようにしましょう。
書き換えたコードを実行してみると、以下のように、タブベースでルーティングする画面が作成できました。
簡単に、各Componentとコードの説明をしていきます。
以下は、上のコードを一部抜粋したものになります。
<!-- コンテナ -->
<ion-tabs>
<!-- タブ (表示したい要素を内部に書く) -->
<ion-tab tab="tab-home">
<Page title="ホーム" content="ホーム画面" />
</ion-tab>
...
<!-- タブバー (ボトムナビ部分) -->
<ion-tab-bar slot="bottom">
<!-- タブボタン(ボタン部分。ion-tabと'tab'の値を揃える) -->
<ion-tab-button tab="tab-home">
<ion-icon icon={icons.home}></ion-icon>
<ion-label>ホーム</ion-label>
</ion-tab-button>
...
</ion-tab-bar>
</ion-tabs>
ion-tabsはタブのコンテナとしての役割を持ちます。
ion-tabsの直下に、ion-tabやion-tab-barといったComponentを設置していきます。
ion-tabは、tabプロパティを持ち、この値はタブのid(識別子)として機能します。ion-tabの内部には、そのタブ内で表示したい要素を記述していきます。今回はそれぞれのタブがPageというComponentを表示するようになっています。
また、表示するtabをコントロールするために、ion-tab-barとion-tab-buttonを設置します。ion-tab-buttonのtabプロパティにion-tabのtabプロパティと同じ値を設定することで、ボタンとタブをリンクさせます。
ion-icon
また、今回はタブのボタンにion-iconを使っています。ion-iconは、Ionicが提供するオープンソースのアイコンライブラリで、様々な種類のアイコンを簡単に使うことができます。
まとめ
今回は、主要なIonicのレイアウトに関するComponentを紹介しました。
他にも、様々なComponentが用意されていますが、全ては説明しきれないので、公式ドキュメントを参照いただければと思います。
次回はion-navというComponentを使って、ナビゲーションの仕組みを実装する方法について説明できればと思います。おそらく、IonicとSvelteの組み合わせを検討している方が、最も気になっている部分の一つではないかと思います。
関連記事リンク
We are hiring!
「人口減少社会において必要とされるインターネット事業を創造し、ニッポンを元気にする。」
を理念に掲げ一緒に働く仲間を募集しております。