モバイルデザイン
概要
各プラットフォームでネイティブアプリのように感じられるモバイルアプリを設計、構築します。このスキルでは、React Native、Flutter、SwiftUI を対象に、プラットフォーム固有のヒューマンインターフェイスガイドライン(Apple HIG)と Material Design、ジェスチャー処理、レスポンシブレイアウト、オフラインファーストのパターン、アプリストアへの申請要件について詳しく扱います。
フェーズ 1:プラットフォーム分析
- 対象プラットフォームを特定します(iOS、Android、両方)
- フレームワークを選択します(React Native、Flutter、SwiftUI、またはクロスプラットフォーム)
- プラットフォーム固有のデザインガイドラインを確認します
- ナビゲーションアーキテクチャを定義します
- オフライン要件を整理します
停止 — デザインに着手する前に、根拠を添えてプラットフォームとフレームワークの推奨案を提示します。
フレームワーク選択の判断表
| 要件 | React Native | Flutter | SwiftUI | Kotlin/Compose |
|---|
| iOS のみ | 可能 | 可能 | 最適 | 不可 |
| Android のみ | 可能 | 可能 | 不可 | 最適 |
| クロスプラットフォーム | 良好 | 最適 | 不可 | 不可 |
| ネイティブ性能が重要 | 良好 | 良好 | 最適 | 最適 |
| 既存の React ウェブチーム | 最適 | 学習コストあり | 学習コストあり | 学習コストあり |
| 複雑なアニメーション | 良好 | 最適 | 良好 | 良好 |
| 迅速なプロトタイピング | 良好 | 良好 | 最適(iOS) | 良好 |
| 大規模な既存コードベース(JS) | 最適 | 書き換え | 書き換え | 書き換え |
フェーズ 2:デザインの実装
- プラットフォーム別のバリエーションを備えたコンポーネントライブラリを構築します
- ナビゲーションを実装します(タブバー、スタック、ドロワー)
- セーフエリアとノッチに対応します
- ジェスチャー認識機能を追加します
- スマートフォン/タブレット向けのレスポンシブレイアウトを実装します
停止 — レビュー用に、ナビゲーションアーキテクチャとコンポーネント一覧を提示します。
プラットフォーム固有の HIG への準拠
Apple Human Interface Guidelines
| 領域 | ガイドライン |
|---|
| ナビゲーション | UINavigationController(push/pop)、画面下部のタブバー(最大 5 個) |
| タイポグラフィ | SF Pro / SF Pro Rounded、Dynamic Type(全 11 サイズ)に対応 |
| セーフエリア | safeAreaInsets を尊重します — ノッチやホームインジケーターの下に入り込ませません |
| ジェスチャー | ナビゲーション用のスワイプバック、コンテキストメニュー用の長押し |
| 触覚フィードバック | UIFeedbackGenerator(衝撃、選択、通知) |
| 色 | セマンティックなシステムカラー(label、secondaryLabel、systemBackground) |
| モーダル | ドラッグで閉じられるシート(.sheet、.fullScreenCover) |
| リスト | 設定にはグループ化されたインセット形式、コンテンツフィードには標準形式 |
| アイコン | SF Symbols ライブラリ(5000 以上のアイコン、可変の太さ/サイズ) |
Material Design(Android)
| 領域 | ガイドライン |
|---|
| ナビゲーション | ボトムナビゲーションバー、ナビゲーションドロワー、トップアプリバー |
| タイポグラフィ | Roboto / 製品フォント、Material のタイプスケール |
| エッジツーエッジ | システムバーの背後まで描画し、ウィンドウインセットに対応します |
| ジェスチャー | 予測型戻るジェスチャー(Android 14 以降)、スワイプで閉じる |
| 触覚フィードバック | HapticFeedbackConstants(クリック、長押し、キーボード) |
| 色 | 壁紙から生成される Material You の動的カラー、トーンパレット |
| コンポーネント | FAB、スナックバー、ボトムシート、チップ |
| モーション | 共有要素トランジション、コンテナ変形 |
クロスプラットフォームパターンの判断表
| 機能 | iOS のパターン | Android のパターン |
|---|
| 戻るナビゲーション | 左端からスワイプ | システムの戻るボタン |
| 主なアクション | 右側のナビゲーションバーボタン | FAB |
| アラート | UIAlertController | MaterialAlertDialog |
| 読み込み | UIActivityIndicator | CircularProgressIndicator |
| セグメント選択 | UISegmentedControl | タブ/チップ |
| 日付選択 | ホイールピッカー | カレンダーピッカー |
| 引っ張って更新 | ネイティブ対応 | SwipeRefreshLayout |
| コンテキストメニュー | 長押し+触覚フィードバック | 長押し+ポップアップ |
セーフエリアの処理
React Native
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
function Screen() {
const insets = useSafeAreaInsets();
return (
<View style={{ flex: 1, paddingTop: insets.top, paddingBottom: insets.bottom }}>
{/* Content */}
</View>
);
}
Flutter
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: // Content
),
);
}
SwiftUI
var body: some View {
VStack {
// Content automatically respects safe areas
}
.ignoresSafeArea(.keyboard) // Only ignore keyboard if needed
}
ジェスチャーナビゲーションのパターン
| ジェスチャー | 用途 | 最小ターゲットサイズ |
|---|
| タップ | 主なアクション | 44x44pt |
| 長押し | コンテキストメニュー/二次アクション | 44x44pt |
| 横スワイプ | ナビゲーション、閉じる、アクションの表示 | 行全体 |
| 縦スワイプ | スクロール、引っ張って更新、シートを閉じる | 領域全体 |
| ピンチ | 画像/マップのズーム | コンテンツ領域 |
| パン/ドラッグ | 並べ替え、要素の移動 | ドラッグハンドル |
タッチターゲットのルール
| ルール | 値 |
|---|
| 最小サイズ(iOS) | 44x44pt |
| 最小サイズ(Android) | 48x48dp |
| 最小間隔 | ターゲット間に8pt |
| 視覚サイズとタッチサイズ | 視覚サイズは小さくても構いません。タッチ領域にはパディングを使用します |
| 主なアクション | 画面下部の1/3(親指が届く範囲) |
フェーズ3:プラットフォームごとの仕上げ
- プラットフォーム固有のアニメーションとトランジション
- 触覚フィードバックの統合
- アプリアイコンと起動画面
- ダークモードとDynamic Typeのサポート
- アプリストアのメタデータとスクリーンショット
停止 — 完了と宣言する前に、実機でテストしてください。
レスポンシブレイアウトの判断表
| フォームファクター | レイアウト | ナビゲーション |
|---|
| スマートフォン(縦向き) | 1列 | 下部タブ |
| スマートフォン(横向き) | 1列または分割 | サイドタブ |
| タブレット(縦向き) | 2列 | サイドバー |
| タブレット(横向き) | 3列 | 常時表示のサイドバー |
React Nativeのレスポンシブ対応
import { useWindowDimensions } from 'react-native';
function useResponsive() {
const { width } = useWindowDimensions();
return {
isPhone: width < 768,
isTablet: width >= 768 && width < 1024,
isDesktop: width >= 1024,
columns: width < 768 ? 1 : width < 1024 ? 2 : 3,
};
}
Flutterのレスポンシブ対応
class ResponsiveLayout extends StatelessWidget {
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < 600) return MobileLayout();
if (constraints.maxWidth < 1200) return TabletLayout();
return DesktopLayout();
},
);
}
}
オフラインファーストアーキテクチャ
| レイヤー | パターン | 実装 |
|---|
| データ | ローカル優先 | SQLite/Realmをプライマリストアとして使用し、サーバーを同期先とします |
| 更新 | 楽観的 | ローカルに適用し、バックグラウンドで同期します |
| 競合 | 解決戦略 | 最終書き込み優先、またはフィールド単位のマージ |
| キュー | 永続化された操作 | 保留中の操作を保存し、接続時に再試行します |
| キャッシュ | stale-while-revalidate | キャッシュを提供し、バックグラウンドで更新します |
実装チェックリスト
アプリストアガイドラインの概要
| 要件 | Apple App Store | Google Play Store |
|---|
| スクリーンショット | 6.7インチと5.5インチが必須、iPadは12.9インチ | デバイスごとに最小2枚、最大8枚 |
| アプリアイコン | 1024x1024px、アルファなし、角丸なし | 512x512px、アダプティブ形式を推奨 |
| プライバシー | プライバシーラベルが必須 | データセーフティセクションが必須 |
| 審査時間 | 通常24~48時間 | 数時間~数日 |
| よくある却下理由 | クラッシュ、プレースホルダーコンテンツ | ポリシー違反、クラッシュ |
パフォーマンス目標
| 指標 | 目標 |
|---|
| コールドスタート | < 2秒 |
| 画面遷移 | < 300ms |
| タッチ応答 | < 100ms |
| スクロールFPS | 60fps(フレーム落ちなし) |
| メモリ使用量 | < 200MB(ベースライン) |
| アプリサイズ | < 50MB(ダウンロード) |
アンチパターン/よくある間違い
| アンチパターン | 問題点 | 代わりに行うこと |
|---|
| モバイルでのWebパターン(ホバー状態) | タッチデバイスにはホバーがありません | 押下/タップ状態を使用します |
| 小さすぎるタッチターゲット(< 44pt) | 操作しにくく、アクセシビリティ上の問題になります | 最小44x44ptのタッチ領域を確保します |
| AndroidでiOS風のボタンを使用 | 違和感があり、ユーザーを混乱させます | プラットフォーム標準のコンポーネントを使用します |
| 画面サイズを1種類に固定したレイアウト | タブレットや折りたたみ端末で崩れます | ブレークポイントを設けたレスポンシブレイアウトを使用します |
| I/Oでメインスレッドをブロック | UIがフリーズし、ANRダイアログが表示されます | 非同期I/Oとバックグラウンドスレッドを使用します |
| キーボードの表示を考慮しない | キーボードの背後にコンテンツが隠れます | キーボード表示時にレイアウトを調整します |
| 常時接続を前提とする | オフライン時にアプリがクラッシュまたはハングします | オフラインファーストアーキテクチャを採用します |
| dp/ptではなくピクセル値を使用 | 画面によってサイズが異なります | 密度非依存の単位を使用します |
| 触覚フィードバックを省略 | アプリが安っぽく、反応が鈍く感じられます | 重要な操作に触覚フィードバックを追加します |
ドキュメントの検索(Context7)
最新のドキュメントを取得するには、mcp__context7__resolve-library-id、続いてmcp__context7__query-docsを使用します。取得したドキュメントは、記憶している知識より優先されます。
react-native — コンポーネント API、ナビゲーション、またはプラットフォーム固有のモジュール向け
flutter — ウィジェットカタログ、状態管理、またはプラットフォームチャネル向け
統合ポイント
| スキル | 統合 |
|---|
ui-ux-pro-max | カラーパレット、タイポグラフィ、UX ガイドライン |
ui-design-system | モバイル向けに調整されたデザイントークン |
canvas-design | モバイルのデータ可視化とチャート |
ux-researcher-designer | モバイルのユーザビリティテスト |
senior-frontend | React Native コンポーネントの実装 |
deployment | アプリストアへの提出パイプライン |
performance-optimization | モバイルのパフォーマンスプロファイリング |
スキルの種類
柔軟 — 選択したフレームワークと対象プラットフォームに合わせてパターンを調整します。単一のプラットフォームを対象とする場合はプラットフォーム固有のガイドラインに従い、クロスプラットフォームアプリでは各プラットフォームの慣習を適切に組み合わせます。