2013年6月6日木曜日

TitaniumでiOSとAndroidの同時開発をする際の注意点

  • このエントリーをはてなブックマークに追加

TitaniumはiOSとAndroidが、
JavaScriptで同時に開発出来るという利点があるが、
実際のところはAndroidのせいで諸々制約が出てきてしまうものであったりする。
なのである程度のところまでは同時に開発できるけど、
細かく作る場合にはしょうがないから出し分けをする必要があったりする。

で、共通のコードを作っている際にこれは注意しておこうというものをまとめてみた。


■ActivityIndicatorのstyle指定

var ai = Titanium.UI.createActivityIndicator({
  height:"50dp",
  width:"50dp",
  zIndex:10
});

if(Ti.Platform.name === 'iPhone OS')
  ai.style = Titanium.UI.iPhone.ActivityIndicatorStyle.BIG;

win.add(ai);
ai.show();
※ActivityIndicatorでのstyleはAndroidで使えないので分割必須。


■SwitchのtitleOnとtitleOff

Ti.UI.createSwitch({
  value:false,
  titleOn:'ID表示する  ',
  titleOff:'ID表示しない'
});
※SwitchはAndroidで使う場合、「titleOn」・「titleOff」を記入必須。
なのでiOSの場合はいらないけど共通ならば二つとも書いておかないといけない。


■labelのwordWrap指定

Ti.UI.createLabel({
  text:"ごにゃごにゃほにゃほにゃあいうえおかきくけこ",
  width:"10%",
  wordWrap:false
});
※iOSでは自動的にwordWrap=falseと指定しなくてもなるけど、
Androidでは指定しないと折り返しされてしまうので要注意。


■dpおよび単位の指定

//OK
Ti.UI.createLabel({
  text:"ほにゃほにゃ",
  width:"300dp",
  font:{
    fontSize:"12dp"
  }
});
//NG
Ti.UI.createLabel({
  text:"ほにゃほにゃ",
  width:300,
  font:{
    fontSize:12
  }
});
※Android向けに作るときは単位としてちゃんと「dp」を指定する必要あり。
そうしないと機種によっては小さくなってしまうため。
ただsize計算するときとかそういったときはdp指定されているので、
parseInt()するなりなんなりしないとエラーになるので要注意。

ただいちいちdp指定するのが面倒だなぁという場合は、tiapp.xmlを編集すればよい。
//tiapp.xml
<ti:app〜〜〜>
  ・
  ・
  ・
  <android xmlns:android="http://schemas.android.com/apk/res/android">
    <manifest>
      <supports-screens android:anyDensity="false"/>
    </manifest>
  </android>
</ti:app>

//
Ti.UI.createLabel({
  text:"ほにゃほにゃ",
  width:300,
  font:{
    fontSize:12
  }
});
※tiapp.xmlの第二階層にandroidを作ってあげて、
その中にmanifestとしてanyDensity=falseを指定してあげればよい。
ちなみにこれでタブのアイコンサイズがおかしい問題が同時に修正される。

ただAndroidはピクセル密度が機種によって3種類に分かれており、
高密度機種の場合、画像などがちょっとぼやけて見えてしまったりする。
正直これを使うのはいいんだけど、綺麗なものを作るならばdp指定がよい。

ちなみに「dp指定」して「anyDensity=false」にすると表示が崩れるのでNG。


■tableViewでscrollEnd時のe.contentOffsetとe.contentSize

var table = Ti.UI.createTable();

var rows = [];
for(var i = 0;i < 2000;i++){
  rows.push({title:i});
}

table.startLayout();
table.setData(rows);
table.finishLayout();

var flg = 0;

if(Ti.Platform.name !== 'iPhone OS'){
  table.addEventListener("scroll",function(e){
    if((e.firstVisibleItem + e.visibleItemCount) == e.totalItemCount) flg = 1;
    else flg = 0;
  });
}
table.addEventListener("scrollEnd",function(e){
  if(Ti.Platform.name === 'iPhone OS'){
    if(e.contentOffset.y + e.size.height >= e.contentSize.height) flg = 1;
    else flg = 0;
  }

  if(flg){
    //テーブルの一番下までスクロールした際のイベント処理
  }
});
※AndroidではscrollEndにて、e.contentOffsetとe.contentSizeが取得不可。
なのでscrollEndイベントのみを使って、
スクロールが最下部まで来たときにrowを追加するということが出来ない。

ということでこれを対処するにはAndroidの場合は違う方法で取得をする。
scrollイベントにて最下部に来てるかどうかを判断する方法を取る。
(e.firstVisibleItem + e.visibleItemCount) == e.totalItemCount
これでAndroidのテーブルビューにて最下部かどうか判断出来る。
ただscroll状態でrowの追加処理を書いてしまうと、
スクロールの慣性でscrollイベントは何度も発火されているから、
flgという形で状態を保持する事にして、
scrollEndで判断するといった形で実装を行えば問題がない。

こういったイベント時の挙動の違いっていうのは要注意。


■imagesフォルダの指定方法

//OK
Ti.UI.createButton({
  image:"/images/button.png"
});

//NG
Ti.UI.createButton({
  image:"images/button.png"
});
※NGのやり方はiOSだと問題なく動作するが、Androidだと動作しないので要注意。


■win.add()などadd()の使い方

var btn1 = Ti.UI.createButton();
var btn2 = Ti.UI.createButton();

//OK
win.add(btn1);
win.add(btn2);

//NG
win.add(btn1,btn2);
※NGのやり方はiOSだと問題なく動作するが、Androidだと動作しないので要注意。


多分もっと注意するべき点っていうのはあると思うけど、
とりあえずここら辺を特に気をつけておけばよいのではないかと。

やっぱりTitaniumを使っているとiOSアプリを簡単に作るためのもので、
あくまでAndroidはおまけ程度なのかなぁと思ってしまう。
もちろんそもそものiOSとAndroidの設計思想が違うのもあるんだけど、
色々と問題があるのに対処される事がほとんどないなぁと。

出来たらネイティブで両方開発するのがいいんじゃないかと思う。
もちろんスケジュール的なもの、受託なのか、予算はどれくらいかなどが関係するが。
もしくはphonegapを通してあげてwebアプリで開発するのもありなんじゃないかなと。

Adsense