この記事は GMOインターネットグループ Advent Calendar 2024 12日目の記事です。
こんにちは、GMOペパボでシニアエンジニアを務めている酒井です。
私は現在、minneの開発を担当しているモバイルアプリエンジニアとして活動しています。
今回は、11月14日に開催された「Spectrum Tokyo Meetup #15」での登壇内容を振り返り、改めてまとめました。この時のテーマは「デザインエンジニアリングにまつわるお話」でした。
そこで使用した登壇資料にいくつかの補足を加えて、皆様にポイントをご紹介していきます。
目次
登壇のきっかけ
私が今回の登壇を決意したきっかけは、これまでの経験にありました。過去にデザイナーとしての経験があり、その後はモバイルエンジニアとしてUI実装に携わってきました。このため、業務内外で得られた知見や事例を共有することで、少しでも皆様のお役に立てればと考えたのです。
iOSとAndroidにおいて、同じUI体験をネイティブで実現しようとする場面は、日常の業務や個人開発で頻繁に直面する課題です。例えば、実装の難易度を見誤ったり、無意味に複雑な実装をしてしまったりして、標準の動きと比較して違和感が生じることがあります。
本発表では、この様な課題にどのように向き合い、上手に付き合いながらプロジェクトを進めていくかという考え方とアプローチをお伝えしたいと思いました。
意外とこの様なケースってありませんか?

iOSとAndroidのネイティブアプリ開発において、振る舞いが似ているように見えても、実際には異なる方向性が必要になることがあります。例えば、1つのOSではスムーズに進む一方で別のOSでは苦戦するケースや、純正部品が提供されていない場合があります。同様に、他のアプリで見られるような表現でも難解で複雑な構造が問題となることもあります。こうした状況では、異なるプラットフォーム間での注意深い対応が求められます。

アプリ開発でのiOSとAndroid間の違いを減らすには、いくつかの着眼点が重要です。まず、両プラットフォームで提供されている純正部品への理解を深めること。また、新旧を問わず、実現方法やOSSの活用法についても理解が求められます。さらに、デザインデータを実際に構築する際のイメージを具体化することも有用です。こうした視点を持つことで、予期しない問題に対処しやすくなります。

ネイティブアプリ開発において、iOSとAndroidそれぞれのガイドラインに立ち返ることが重要です。特に、機能を考える際に対応するUIを設計するためには、各OSの純正部品もこのガイドラインに沿って提供されるので、Human Interface GuidelineやMaterial Designの確認が不可欠です。やむを得ずカスタマイズが必要な場合でも、ガイドラインから逸脱しないよう注意し、保守性の高い実装を心がけることが大切です。
実際に出会したややこしいケースをご紹介

私は2023年と2024年に、DroidKaigi公式アプリでiOS側のコントリビューションを行いました。
特に私が担当したUI実装に関連する部分では、AndroidとiOSでそれぞれのプラットフォームに応じた異なるアプローチが必要でした。本稿では2023年に取り組んだ事例を紹介します。
Android版のUI構築では、純正Componentを活用する方針を採用していました。UI要素はJetpack Composeの基本Componentを組み合わせることで実現し、スクロールの変化量をScrollStateで管理していました。また、NestedScrollの特性を活用して、Tab要素とContents要素におけるスクロール動作を実現していました。

一方iOS版では、SwiftUIを使用したUI構築においてカスタマイズが必要でした。難しかったのは、ScrollViewの拡張でOffset値を取得し、LazyVStackを基にしてTab要素の動きを再現する工夫が必要な点でした。取得したスクロール変化量を利用して、SectionHeaderに配置したTab要素の状態を変化させる処理がポイントになりますが、この表現はAndroid版の振る舞いを参考にし、できる限り近い形となる様に自作しました。

複雑なGrid表現の例として、iOSとAndroidのアプローチを比較します。
iOSでは、UICollectionViewを使用し、高さやアスペクト比を元に工夫が必要です。一方、AndroidではStaggeredGridLayoutManagerを用いることで、よりシンプルに実現できます。
これにより、プラットフォーム間での考え方や実装方法の相違が明確になります。

Swipe切替表現の実装に関して、iOSとAndroidではアプローチが異なります。
iOSでは、UIKitを利用する事で表示要素や位置変化を活用し、工夫次第で多様な表現が可能です。一方、Androidでは、ViewPagerとTabLayoutの組み合わせが基本で、細かなデザインのカスタマイズは難しい場合があります。
カスタマイズの余地を考慮し、どちらのプラットフォームにも適した実装を選ぶことが重要です。

iOSに存在しないがAndroidにはある表現(またはその逆)を実装する際は、慎重にアプローチを検討する必要があります。特に、汎用的な形で多用途に活用される場合には、特に注意が必要です。
用意されていない表現を自作し、汎用的で活用しやすい形に整えるには、かなりの工数がかかります。そのため、こうした場合にはOSSの活用も視野に入れると良いでしょう。

端末固有機能である動画再生やプッシュ通知の実装には、プラットフォームごとに大きな違いがあります。同じ機能でもiOSとAndroidでは振る舞いが異なるため、実装方針には注意が必要です。また、OS準拠機能の違いを理解し、必要な知識を把握することも重要です。
スライドで紹介しているのは、アプリがバックグラウンド状態になる際も音声が途切れることなく再生できる機能の例です。一見、同様の機能に見えても、実装方針は全く異なります。それぞれのOSに応じた対応が求められる点に注意が必要です。
落とし穴をうまく回避するために

デザインから逆算して実装の難易度を正確に見積もることが、落とし穴を回避する鍵になると考えています。
デザインからは、実装イメージやハマりそうな点、想定工数など、実装に役立つ様々な情報を読み取ることができます。その情報を見逃さず、曖昧な見積もりを避けるために、見えない情報を具体化することが重要だと思います。

モバイルアプリ開発における難易度の見積もりで重要な観点として、UIコンポーネントの複雑さやプラットフォーム間の差異に加え、データフロー・パフォーマンス・API連携・セキュリティ・アクセシビリティ・ローカライズ・テスト・メンテナンス性等の項目挙げられると思います。
これらの要素を考慮してデザインから逆算し、実装難易度を正確に見積もることが、長期的なプロジェクトの成功と円滑な進行につながると考えています。

iOSとAndroidのUI実装では、それぞれのプラットフォーム間で考え方やコンポーネントにおける相違点を理解することが重要だと考えています。
アニメーションやトランジション・カスタムUIコンポーネントの実装・システムUIとの統合・アプリのライフサイクルなどが異なるため、アジャイル開発の観点からもこれらの違いを把握して計画することが求められます。これにより、スプリント計画の精度が向上し、リソースを最適に配分することが可能になります。

正確な見積もりを行うと同時に、「実現しやすい手段や方法」を模索すると良いでしょう。スライドで紹介しているのは、従来の手法では難しかったUI実装を、宣言的UIを活用してシンプルに実現する例です。
SwiftUIやJetpack Composeを用いてSection構造を工夫することで、視覚的に分かりやすいデザインが可能になります。選択する方針次第では、View構造が簡素化され、実装が一層容易になることもあります。
1つのUI実装に対して様々なアプローチを知っておくことで、選択肢を広げることができ、見積もりや実装に対する引き出しが増えるため、とても有益だと考えています。
実装イメージを整理して言葉に直してみる


私が個人的に実践していることの一つに、気になったUI実装や表現に関する事例を紐解き、ポイントになり得る点をノートにまとめる作業があります。
情報源としては海外ブログ記事やYouTubeの解説動画など多岐にわたります。動作するサンプルコードにも触れ、自分の言葉でまとめるとともに、図解を用いてイメージを整理し、応用事例を深く理解しながら、今後の実装に活かすことを心がけています。
まとめ

本記事を通じて、一見すると簡単そうに見えるものでも、実は複雑であることを認識する重要性をお伝えしました。
iOSとAndroidの共通点と相違点を理解し、困難な事例に備えることで、自分なりの解決策を持つことが重要だと考えています。そして、デザインを基に難易度を逆算し、実装イメージを固めるアプローチを取るためには、実装経験から得た気づきや、目に見えない情報を大切にする姿勢が重要になると思います。
参考資料
円滑なUI&機能実装やデザイナーとの共同作業を進めるために心がけてきた事
iOSエンジニアがAndroid・Kotlinでの開発を加速させた3年間の実践テクニック
Androidアプリでバックグラウンド再生機能を実現するためのヒントとiOSアプリとの見比べた際の特徴を簡単にまとめてみた
Footprints about Contribution of DroidKaigi 2023
あとがき
今回の5分間のスライドは、予想以上に盛りだくさんとなり、当日はかなり早口で話すことになりました。しかし、参加者の方々から共感やお褒めの言葉をいただき、大変嬉しく思いました。
私は、モバイルアプリのUI実装に関連するトピックや事例に触れることが好きなので、今後もこのような活動を続けていきたいと考えています。
ブログの著者欄
採用情報
GMOインターネットグループ採用情報
関連記事
KEYWORD
CATEGORY
-
技術情報(458)
-
イベント(164)
-
カルチャー(38)
-
デザイン(21)
TAG
- 5G
- Adam byGMO
- AI
- AWX
- BIT VALLEY
- blockchain
- ChatGPT
- cloudflare
- cloudnative
- CloudStack
- CM
- CNDO
- CNDT
- CODEGYM Academy
- ConoHa
- CS
- CSS
- CTF
- DC
- Designship
- Desiner
- DeveloperExpert
- DevSecOpsThon
- DNS
- Docker
- DTF
- GitLab
- GMO Developers Day
- GMO Developers Night
- GMO GPUクラウド
- GMO Hacking Night
- GMO kitaQ
- GMO SONIC
- GMOアドパートナーズ
- GMOアドマーケティング
- GMOイエラエ
- GMOグローバルサイン
- GMOソリューションパートナー
- GMOデジキッズ
- GMOブランドセキュリティ
- GMOペイメントゲートウェイ
- GMOペパボ
- GMOリサーチ
- Go
- GTB
- Hardning
- Harvester
- HCI
- iOS
- IoT
- ISUCON
- JapanDrone
- Java
- JJUG
- K8s
- Kaigi on Rails
- Kids VALLEY
- LLM
- MetaMask
- MySQL
- NFT
- NVIDIA
- OpenStack
- Perl
- perplexity
- PHP
- PHPcon
- PHPerKaigi
- PHPカンファレンス
- QUIC
- Rancher
- RPA
- Ruby
- Selenium
- Spectrum Tokyo Meetup
- splunk
- SRE
- SSL
- Terraform
- TLS
- TypeScript
- UI/UX
- VLAN
- VS Code
- アドベントカレンダー
- インターンシップ
- オブジェクト指向
- オンボーディング
- お名前.com
- カルチャー
- コンテナ
- スクラム
- スペシャリスト
- セキュリティ
- ソフトウェアテスト
- チームビルディング
- ドローン
- ネットワーク
- プログラミング教育
- ブロックチェーン
- マルチプレイ
- ミドルウェア
- モバイル
- ゆめみらいワーク
- リモートワーク
- レンタルサーバー
- 京大ミートアップ
- 協賛レポート
- 基礎
- 多拠点開発
- 大学授業
- 宮崎オフィス
- 応用
- 技育プロジェクト
- 新卒
- 暗号
- 機械学習
- 決済
PICKUP