SvelteとIonicで始めるモバイルアプリケーション開発入門 Part2. アプリケーション開発編(レイアウト)

IonicのComponentを使ったアプリケーション開発

Junya Kawai
nextbeat-engineering
16 min readMar 29, 2023

--

はじめに

こんにちは、ネクストビートでエンジニアをしている川井です。

この記事は前回の記事の続きとなります。

前回の記事では、Svelteのプロジェクトを作成し、Ionic Framework(以下、Ionic)を導入しました。

今回は、Ionic主要なComponentを使って、モバイルアプリの基礎的なレイアウトを実装していきます。

IonicのComponentについて

前提

前回の記事にも記載しましたが、IonicComponentを使う際には、各ComponentdefineCustomElement関数を実行する必要があります。

内部的には、おそらく以下のような処理が実行されており、Custom Elementsとして利用できるようになっているのではないかと思います。

customElements.define("ion-xxx", Component);

詳しくはIonicComponentの開発に使われている、Stencilの実装を見れば分かりそうですね。

main.tsの初期化処理に、利用したいComponentの定義を追加するのを忘れないようにしましょう。

(例)ion-appの場合

/** 全Componentで同じ関数名が使われているため as xxx で別名に変更している*/
import { defineCustomElement as defineCustomElementIonApp } from '@ionic/core/components/ion-app'

/** 変更後の名称で defineCustomElement関数を実行 */
defineCustomElementIonApp()

ここからは、いくつかの主要なComponentについて紹介していきたいと思います。事前に公式のドキュメントを読んでおくと、より理解が深まるのではないかと思います。

https://ionicframework.com/docs/ja/components

Content

ion-app

ion-appは、アプリケーションのコンテナとなる要素です。

アプリケーション内に1つだけ定義します。基本的にはbody直下に置いておけば良いでしょう。この要素の中に、その他の様々な要素を追加していきます。

ion-appの直下に定義するのは、主にion-header, ion-content, ion-footerの3つのComponentになりますが、ion-madalion-action-sheetなどの動的なオーバーレイ要素も、ion-appの直下にDOMが生成されるようになっています。

<body>
<ion-app>
<!-- ここに追加していく -->
</ion-app>
</body>

ion-content

ion-contentはスクロール可能なコンテンツ領域を描画するためのコンテナです。基本的に、ページ内の要素はこの中に書いていくことが多くなるかと思います。

以下のコードでは、ion-contention-paddingというCSSclassを適用していますが、これは前の記事で紹介した、グローバルスタイルシートに定義されているclassです。これにより、ion-contentpaddingが付与されています。

<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-toolbarion-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-headertranslucentを、ion-contentfullscreenを設定することで、コンテンツのスクロール領域がフルスクリーンとなり、コンテンツ領域をスクロールした際に、ヘッダーの下に潜り込むような表現が可能になります。

上のコードでは省略していますが、それぞれのプロパティにtrueが渡されています。この設定はiOSのみ有効になっており、よりネイティブに近いデザインで実装することができます。

また、styleタグ(SvelteCSS定義)の中で、ion-toolbarの — opacityに0.1という値を設定していますが、IonicComponentの一部の構成要素は、CSSカスタムプロパティ(CSS変数)でスタイルが定義されているため、値を渡すだけで簡単に見た目を整えることができます。

今回は以下のように、ヘッダーの透過をわかりやすくするために0.1を設定しました。

透過されたヘッダーの下に、スクロールされたコンテンツ領域が描画されている

以下の画像は、Ionic公式ドキュメントの実装例です。このように、複数のComponentを組み合わせることによって、リッチなレイアウトを簡単に実装することができます。

https://ionicframework.com/docs/ja/api/toolbar

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に使いたいComponentdefine関数を追加するのを忘れないようにしましょう。

書き換えたコードを実行してみると、以下のように、タブベースでルーティングする画面が作成できました。

簡単に、各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-tabion-tab-barといったComponentを設置していきます。

ion-tabは、tabプロパティを持ち、この値はタブのid(識別子)として機能します。ion-tabの内部には、そのタブ内で表示したい要素を記述していきます。今回はそれぞれのタブがPageというComponentを表示するようになっています。

また、表示するtabをコントロールするために、ion-tab-barion-tab-buttonを設置します。ion-tab-buttontabプロパティにion-tabtabプロパティと同じ値を設定することで、ボタンとタブをリンクさせます。

ion-icon

また、今回はタブのボタンにion-iconを使っています。ion-iconは、Ionicが提供するオープンソースのアイコンライブラリで、様々な種類のアイコンを簡単に使うことができます。

https://ionic.io/ionicons

まとめ

今回は、主要なIonicのレイアウトに関するComponentを紹介しました。

他にも、様々なComponentが用意されていますが、全ては説明しきれないので、公式ドキュメントを参照いただければと思います。

次回はion-navというComponentを使って、ナビゲーションの仕組みを実装する方法について説明できればと思います。おそらく、IonicSvelteの組み合わせを検討している方が、最も気になっている部分の一つではないかと思います。

関連記事リンク

We are hiring!

株式会社ネクストビートでは

「人口減少社会において必要とされるインターネット事業を創造し、ニッポンを元気にする。」
を理念に掲げ一緒に働く仲間を募集しております。

https://www.nextbeat.co.jp/recruit

--

--