Titanium Mobileで作る! iPhone/Androidアプリ

第15回端末ごとにデザインを変更する

最近のTitanium

つい先日(6月13日)にTitanium Mobile 1.7がリリースされ、Android開発に便利な機能がいくつか増えました。特にFastdev for Androidという、コードの変更を高速にエミュレータに反映する機能はAndroid開発をかなり加速してくれそうです。この機能については今回の記事の後半で解説します。また今回は解説しませんが、Titanium Stduioという統合開発環境も正式版が発表になり、今後はTitainum Developerからこちらに移行されていくことが表明されています。

デバイスごとのUIデザイン

さて、前回の記事でなんとかAndroidでもTwitter Clientが動作するようになりました。HVGAの解像度を指定してエミュレーター実行すると調度よいデザインで表示されます。しかしWVGA800やWVGA854といった解像度で表示すると、解像度がかなり大きいためデザインがくずれたり、相対的に文字が小さく表示されるようになって表示が見にくくなったりと不都合がでてきます。今回はこの、デバイスごとにUIデザインをどうにかする方法を解説します。

図1 高解像度では若干デザインが崩れる
図1 高解像度では若干デザインが崩れる

JSS

TitaniumではUIのデザインとロジックを切り分ける方法の一つとして、JSS(JS Stylesheets)が用意されています。これはCSSと似たような記法でUI部品のwidth, heightといったプロパティを書いておくことでUIのデザインを共通化し、また別ファイルにすることができるものです。次のようなルールで適用されます。

  • ファイル名はwindow_js_name.jss
  • ファイルは何処にあっても上のルールが適応される
  • idかclassを指定してデザインの指定を書く
  • 記法はcssとほとんど同じ

ファイル名にあるwindow_js_nameのところは、自分がUI部品をデザインしたいWindowの定義をしているjavascriptのファイル名(拡張子は除く)です。つまりサンプルアプリでツイート一覧を表示しているtable_view.jsのデザインをしたい場合はtable_view.jssというファイルを用意します。このファイルはResources以下のどのディレクトリにあっても適応されるので注意が必要です。

また、CSSの記法では、tagを指定したり色々なセレクタがありますが、JSSではクラス名かidを指定します。各UIオブジェクトにもクラス名かidを割り振ることで適応されるJSSが決まります。ということで、サンプルコードを見てみましょう。

table_view.js
function updateTimeline (timeline) {
    var currentData = [];
    for (var i=0;i<timeline.length;i++) {
        var tweet = timeline[i];
        var row = Ti.UI.createTableViewRow({ id:'row' });
        var imageView = Ti.UI.createImageView(
            {
                image: tweet.user.profile_image_url,
                className: 'tweetIcon'
            }
        );
        row.add(imageView);

        var nameLabel = Ti.UI.createLabel({ id: 'nameLabel' });
        nameLabel.text = tweet.user.screen_name;
        row.add(nameLabel);

        var commentLabel = Ti.UI.createLabel({ id: 'commentLabel' });
        commentLabel.text = tweet.text;
        row.add(commentLabel);

        var dateLabel = Ti.UI.createLabel({ id: 'dateLabel' });
        dateLabel.text = tweet.created_at;
        row.add(dateLabel);

        currentData.push(row);
    }
    tableView.setData(currentData);

    //以下省略

まずは、JSのコードからです。この部分はタイムラインのツイートに含まれるユーザー名や日付の情報をラベルにして、TableViewのrowとして追加しているところです。 今まではTi.Ui.createLabelなど画面部品を作成しているところで、直接widthやheightを渡していましたが、このコードではそういったデザイン要素がなくなり、代わりにidプロパティが指定されています。全体としてデザインのためのコードがほとんどなくなりコードが見やすくなっています。

そして、ここで指定されているidごとにデザインを指定しているのが、このtable_view.jsに対応するtable_view.jssです。

table_view.jss:一部抜粋
#row {
    height: 'auto';
    layout: 'vertical';
}

.tweetIcon {
    width: 48;
    height: 48;
    top: 5;
    left: 5;
}

#nameLabel {
    width: 120;
    height: 'auto';
    left: 58;
    top: -48;
    fontSize: 6;
    fontWeight: 'bold';
    color: '#2b4771';
}

cssとほぼ同様の書き方ができ、#rowのように # から始めるセレクタはidを示し、.tweetIconのように . で始まるセレクタはクラスを示しています。各プロパティは今までTi.UI.createLabelに渡していたものと同じです。当然ですが、JSのオブジェクトではないので各プロパティはカンマ区切りではなく、セミコロンで区切るようにする必要があります。一方でfontSizeはfont-sizeと書くべきなのがCSSのルールのように思えますが、これはどちらで書いても有効になります。しかしfontSizeと書いた場合とfont-sizeと書いた場合で基準となる単位が変わるようなので注意が必要です。

classNameでの指定はCSSと同様に複数のクラスを指定できて便利なのですが、classNameで指定するとAndroidで上手く動かないバグも報告されているので、うまく指定できないときはidで指定するとよいでしょう。

端末ごとに異なるJSSを利用する

さてJSSについて紹介してきましたが、今回の記事の目的は解像度が異なるデバイスごとに異なるデザインを当てる方法について解説することでした。そこでこのJSSが活躍してくれます。先程の例ではtable_view.jsに対してtable_view.jssを用意しましたが、Androidの端末サイズごとに異なるJSSが用意できるのです。具体的には

  • table_view.android.low.jss
  • table_view.android.medium.jss
  • table_view.android.heigh.jss

の3つを用意することができ、解像度にあわせてそれぞれのJSSが選択されます。よって想定される端末ごとに、この3つのJSSファイルを書くことで、ロジックのコードに手を入れずに複数端末に対応することができます。ファイル名のルールは見たままですが、今までと同じように、

  • Windowの定義が書いてあるJSのファイル名.android.サイズ.jss

というようになります。

low, medium, heighの閾値はTitanium側というよりはAndroidのAPIで規定されるもののようで、ディスプレイのdpiの値によって決められます。

などを参考にしてください。

また、今回Android開発の流れの中でJSSについて紹介しましたが、JSSはiOSアプリでも有効です。

FastDev を使ってみる

JSSについての話は以上にして、ここからは少し毛色のちがうFastDevというエミュレーターへの反映方法について解説します。

FastDevはJSへの変更をリビルドなしにエミュレータに反映できるので、非常に高速に、コードの変更とテストを繰り返すことができます。つまりコードに変更を加えると即座にその変更を確認できるようになります。もしエミュレータがそれなりの速度で動く環境であれば、iPhone開発と近い感覚で(あるいはもっと高速に)開発ができます。

この機能はTitanium 1.7.0からの機能なので、かならずTitanium Mobile SDKを最新にバージョンアップしておいてください。

では実際の使い方です。まず、準備としてtitaniumコマンドをターミナルから呼び出せるようにする必要があります。以下、bashをターミナルで利用している前提で解説していきます。titaniumコマンドはTitanium Mobile SDKのあるディレクトリに含まれているので、次のようなaliasを.bashrcに記載します。

alias titanium='/Library/Application\ Support/Titanium/mobilesdk/osx/1.7.0/titanium.py'

これでtitainumコマンドが呼び出せるようになったので、ターミナルを開いて次のコマンドを入力します

titanium fastdev start &

これでコードの管理を行うサーバーが起動します。次に、通常の方法で開発中のアプリを起動します。つまりTitanium DeveloperのRun EmulaterタブにあるAndroidタブからLaunchをクリックします。そして、無事アプリが起動したら、

titanium run --platform=android --android=/path/to/android-sdk

と入力します。/path/to/android-sdkはこの連載に書いてある手順に従っていれば、/Users/YOURNAME/AndroidSDKになります。かなり時間がかかりますが、もう一度アプリが起動すれば準備完了です。

これ以降はコードに変更を加えると、変更があったWindowを開いたタイミングで新しいコードが読み込まれるようになります。app.jsへの変更や、Ti.includeを使って読み込んだファイルの変更は読み込まれないので、

titanium fastdev restart-app

というコマンド入力してリスタートする必要があります。このコマンドでも反映されないときは、再度

titanium run --platform=android --android=/path/to/android-sdk

と入力すると全体がリビルドされるので上手くいく可能性が高くなります。

また、今回の記事の前半で解説したJSSの機能もjavaのソースファイルを書きだすことで実装されているので、残念ながらtitanium runコマンドで再度ビルドしないと反映ができません。

この機能の詳しいドキュメントはhttp://wiki.appcelerator.org/display/guides/Fastdev+Reference+for+Androidにあります。

おすすめ記事

記事・ニュース一覧