Titaniumでのリソース配置についてのメモ

TitaniumでiPhone版アプリを作る場合、retina用に倍の解像度の画像を準備して使用する。hiresフラグを立てておけば、retina機で高解像度で表示(非retina機では半分の解像度に縮小表示)される。

Androidの場合、複数の解像度(ldpi/mdpi/hdpi)毎の画像を準備しておくのが吉。
リソースや画面上の配置の調整をプログラム(Titaniumのランタイム?)に任せる場合は、TiAppを

    
        
            
        
    

という感じにしておく。
上記の場合、画面のデザインは横幅320pxの画面を想定してプログラムを書いておけば、別な解像度でもそれに合った倍率に調整されるイメージ。

画像リソースを320px用で準備していた場合、自動的に伸縮されて表示されるが、それでは見た目が悪くなる。
Androidの場合は画像リソースをldpi/mdpi/hdpiの3パターン準備しておけば、ランタイムが(というよりAndroidアプリの仕様として)実行端末の解像度にあわせて自動的に参照するリソースを切り替える機能がある。

例えば、
Resource/android/images/res-long-land-ldpi/IMG.png
に置かれた画像は、非タブレット端末(long)の横置き(land)でDensityがldpiの時に参照される。
プログラム側では「'images/IMG.png'」と書いておけばよい。
同じプログラムを縦置きのXperiaで実行した場合、全く同じプログラムでも自動的に
Resource/android/images/res-long-port-hdpi/IMG.png
を参照してくれる。

もちろん、それぞれの解像度のフォルダに同じ画像を置いていてはメリットが無いわけで、
ldpiは120dpi相当の画像密度(画面幅240pxでデザインしたときに相当)
mdpiは160dpi相当の画像密度(画面幅320pxでデザインしたときに相当)
hdpiは240dpi相当の画像密度(画面幅480pxでデザインしたときに相当)
それぞれの解像度で画像を準備しておく。
ただし、
/Resource/android/images/res-long-port-****/IMG.png
/Resource/images/IMG.png
というファイルがそれぞれ存在した場合、mdpi以外の場合は上段のファイルを参照するが、mdpiの場合は下段のファイルが参照されてしまう。
もしiPhone用素材を、retinaを考慮しない(画面幅320px)で作成していた場合、下段の場所にiPhoneandroidのmdpiの素材を置くことで、全く同じコードでiPhoneAndroid全解像度をカバーすることができる。

ただし現実的にはiPhoneretinaを考慮をせねばならず、プログラム側でiPhoneの場合のファイル参照先を切り替える(たとえばResource/iphone/images/IMG.pngとか)ような構造にすることになると思われる。

Android版作成時は、まず/Resource/images/IMG.pngを準備してmdpiベースで開発を行い、別途/Resource/android/images/ほにゃらら/IMG.pngを準備してmdpi以外の解像度に最適化する、というのが理想的なパターンかもしれない。

iPhone側でもretinaを自動認識して切り替えるような仕組みが欲しいな。
たとえば
Resource/iphone/images/noretina/IMG.png
Resource/iphone/images/retina/IMG.png
みたいな感じで切り替わってくれるとか。
そうすれば、プログラム側でプラットフォームで参照先をコントロールする必要が一切なくなり、Resource/android と Resource/iphone の中にルールに沿ったフォルダ名で画像を分類しておけば、全てが一つのコードで済んでしまう。

おそらくTitaniumの元々のコンセプトとしてはそういう設計だったはず。ただretina対応が出来ていない(iPhone環境は単一の解像度であることを前提にしている)という仕様なのがイマイチってことだと思う。


このへん、理屈じゃなかなか分かりにくいと思う。
時間が許せば実験するのが一番。

以下は

var sImg = Ti.UI.createImageView({
	image: "images/testimg.png",
	width: "320dp",
	height: "320dp",
	left: "0dp",
	top: "0dp"
});
win.add(sImg);

という同じコードを複数の解像度で実行させた場合の例。

ldpi(QVGA)の例
(Resource/android/images/res-long-port-ldpi/testimg.png が参照された)

mdpi(HVGA)の例
(Resource/android/images/res-long-port-mdpi/testimg.png が参照された)

hdpi(WVGA854)の例
(Resource/android/images/res-long-port-hdpi/testimg.png が参照された)

同じコードをiPhone(非retinaなので640pxが320pxに縮小表示されている)で走らせた例
(Resource/images/testimg.png が参照された)

mdpiだがiPhone用素材(この場合はretina用の640pxが320pxに縮小表示されている)が参照された例
(Resource/images/testimg.png が参照された)