株式会社インフィニットループ PHPとスマホアプリ開発を行う札幌のシステム会社

技術ブログ

  1. トップ>
  2. 技術ブログ>
  3. Titanium Mobile で Android, iOS 両対応のアプリを開発する際の注意点

2012年09月21日 (金)

著者 : 

Titanium Mobile で Android, iOS 両対応のアプリを開発する際の注意点

大学生活にも慣れてきました。 18 歳の夏を満喫している take です。こんにちは!

会社では、 JavaScript を書くお仕事をしています。楽しいです!

さて、 前回 は Titanium Mobile で Android アプリを書く際にハマるポイントをいくつか紹介しました。

最近、Titanium Mobile なのだから、1つのコードで Android, iOS 両対応するアプリを書こう!ということで、コードを書きながら、予め知っておくと開発が捗るポイントを何点か見つけましたので、ここで紹介したいと思います。

※これから紹介する方法 (コード) は私個人が勝手に考えて実践しているものなので、ベストプラクティスであると保証することはできません。間違っている点や、さらに良い方法があればコメント等お待ちしています。

方針は、 Android も iOS も共通のコードで同じ UI のアプリを作る事です。

Menu を実装する

Android と iOS の両対応でまずはじめに問題になるのは、iOS にはメニューを表示する機能が無い事です。

Android も ICS 以降では、基本的にメニューキーがありません。(古いアプリのためにメニューを表示する事は可能)

「メニューが無いなら実装すれば良いじゃない」

無いものは実装してしまいましょう。最近の Android のアプリには「≡」みたいなマークの付いたメニューが実装されているので、それを参考にします。

menu - ios

iOS

menu - android

Android

iOS ではアプリ側からアプリを終了することができないため、 Exit の項目を設置していません。

Android では、 Ti.UI.createWindow した Window を全て close() するとアプリが終了します。 iOS で同じ事を試すと、真っ白な画面が表示されるだけでアプリは終了されません。

[追記] Menu と同様に、 Back ボタンも iOS にはありませんので、実装する必要があります。
方法としては、今表示している Window を close するだけです。 (iOS のみ、最後の Window は close しないように注意してください)

シングルコンテキスト

Mobile Best Practices にも書かれている通り、公式でシングルコンテキストを用いることが推奨されています。

シングルコンテキストで書く利点は、

  • パフォーマンスが良い
  • JavaScript らしい書き方ができる
  • CommonJS モジュールが活用できる (Ti.include は使わない)

などがあるそうです。

var win = Ti.UI.createWindow({url: "source.js"});
Ti.include("source.js");

という書き方はもう古いです。

これからは

var obj = require("view");

と書きましょう。

CommonJS の require を使う利点は、

  • コードが分離される
  • 変数スコープが変わるので変数名が衝突しない
  • オブジェクト指向ができる

注意点ですが、 require するときのパスは、どこから呼び出す場合でも Resources ディレクトリからの相対パスで指定します。(Android, iOS 共にこの方法で動きます)

Resources ディレクトリ直下に置くファイルは app.js のみにして、他のコードは、android, iphone, ui, lib に分けます。

View 毎にコードを分離する

先程の view.js に書かれるのはこのようなコードです

module.exports = function () {
  var view = Ti.UI.createView();
  var label = Ti.UI.createLabel({
    text: "Hello"
  });
  view.add(label);
  return view;
};

view.js を呼び出すコード

var win = Ti.UI.createWindow();
var view = require("view")();
win.add(view);
win.open();

こうすることで、View 毎に コードを分離する事ができます。

View を分離するときは、画面遷移を考えると簡単に分離する事ができます。

(1つの Window には、1つの View しか add しないと考えると分かりやすくなります)

View という分かりやすい単位毎にコードを分離することで、コードの見通しが良くなりメンテナンスがしやすくなります。

ここで、分離された View 毎に同じデータを共有する問題が出てきます。

View を require するときに、変数として g (グローバルオブジェクト) と 呼び出す View で必要になる引数を与えます。

グローバルオブジェクトは app.js で定義し、 View を呼び出す際に必ず 第一引数に渡すことで共有します。

Menu と Window はそれぞれ分離する

Menu を実装する、 View 毎に分離すると言いましたが、 Menu と Window のコードはどこに書くでしょうか。

Menu は1つのかたまりで CreateMenu.js として分離し、Window は生成部分だけ抜き出してまとめ、 CreateWindow.js として分離します。

CreateWindow.js に全ての Window が集まり、見通しが良くなります。

複数の View から利用するロジックは UI から分離する

View 毎に分離したコードの中に ロジックを書く事になりますが、その View 以外でも同じ処理をする場合は UI から分離します。

Resources/lib 辺りに入れて、必要な View から require しましょう。

View 等のサイズ指定は dip で行う

Android でマルチディスプレイ対応する場合の問題ですが、 android:anyDensity=”false” に設定して、 “dip” という単位でサイズを指定します。

anyDensity=”true” で数値を直接指定した場合と同じサイズになりますが、 anyDensity=”true” にすると Titanium のモジュールを使う場合等に問題になることがあります。

グローバルオブジェクトに

g.dip = function (size) {return String(size + "dip")};

を追加して、 g.dip(20) のように指定する事をお勧めします。

すると、万が一 px 指定に戻したくなった場合でも、 “dip” を “px” に直すだけの書き換えで済むため、かなり手間が省けます。

iOS で動くが Android で動かない コードや UI に注意する (逆もあるかも)

UI では、 TableView で TableViewRow に View を重ねた場合に、 View をタップしたときの click event が TableViewRow に伝播しないという問題があります。

コードでは、

String.prototype.hoge = function () {return this + "hoge"};

を app.js で定義したとして、require される MainView.js で “hoge”.hoge すると、
Uncaught TypeError: Object hoge has no method ‘hoge’
と言われてしまいます。

このどちらの例も、 iOS では動きます。

要点をまとめると以下の通りです。

  • Menu を実装する
  • シングルコンテキストで書く
  • require するパスは Resources からの相対パス (.js は不要)
  • グローバルオブジェクトを定義して全ての View に引数として渡す
  • 画面遷移を意識して View 毎に分離する (1Window 1View)
  • Menu と Window はそれぞれ分離する
  • 複数の View から利用するロジックは UI から分離する
  • サイズ指定は dip で行う
  • iOS で動くが Android で動かないコード, UI に注意する

最後まで読んでいただきありがとうございました。

2件のコメント

  1. おー。そういえばメニューを出さないといけなくなるのでしたね。すっかり忘れておりました。
    もしよかったら、具体的にどうやってメニューを実装したかの記事書いていただけるとうれしいです!

    2012年9月21日 11:52

    投稿者 : mogya
  2. […] 前回の記事で、メニューの具体的な実装方法を教えて欲しいというコメントがありましたので、遅ればせながら公開します。 […]

    2012年12月21日 11:05

  • このブログについて

    このブログは、札幌市の「株式会社インフィニットループ」が運営する技術ブログです。
    お仕事で使えるITネタを社員たちが発信します!

    最新の記事