loading
Development

TitaniumでiOSのNavBarにローディング中を示す表示をしてみる 後編

前回はWindowのタイトルエリアに複数のLabelを追加して中央位置に方法をご紹介しました。今回はこれを応用してグルグルと回りいかにもローディング中ですよ!という感じの見た目にしてみたいと思います。

ImageViewでGIFアニメは動かない

Webの技術を応用してネイティブアプリ開発が出来るTitaniumですがImageViewにGIFアニメを表示させてみても動かないのです。

ではどうするか。ImageViewには画像のパスやバイナリを入れる image というプロパティの他に images というものも用意されてます。

Array of images to animate, defined using local filesystem paths, File objects, remote URLs (Android only), or Blob objects containing image data.Blob and File objects are not supported on Mobile Web.

ドキュメントでは上記のように説明されていて、画像パスの文字列か、画像のバイナリデータか、Fileオブジェクトのインスタンス、いずれかのデータを配列に格納したパラメータを設定できます。
この配列にアニメのコマごとの画像を渡すことでアニメーションを実現できる仕組みです。若干めんどくさいですね。

ローディング画像を用意する

ではローディング画像を用意しましょう。Ajaxload – Ajax loading gif generator というサイトで手軽にいわゆる”ぐるぐる”が生成できるのでこれを利用します。

スクリーンショット 2014-02-10 11.24.51

 

ダウンロードしたGIFをphotoshopで開くとコマごとにレイヤーに分割されて読み込まれました。全部で12個のレイヤーがあります。

スクリーンショット 2014-02-10 11.26.28

 

ちょっとめんどくさいんですが、レイヤーごとにWeb用に保存でpngに書き出しました。もしかしたら全レイヤーを別々に書きだす方法もあるかもしれませんが見つけられませんでした。

スクリーンショット 2014-02-10 11.28.42

 

ちなみにフォルダに入れてファイル名にコマの番号を振っておくと扱いやすいかと思います。

素材ができたのでImageViewに設定してみます。ControllerでImageViewを生成してimagesに複数画像を設定します。材画像は66×66サイズだったのでRetinaを考慮して33×33にしておきます。

var spinner = Ti.UI.createImageView({
 images: [
 '/images/spinner/1.png',
 '/images/spinner/2.png',
 '/images/spinner/3.png',
 '/images/spinner/4.png',
 '/images/spinner/5.png',
 '/images/spinner/6.png',
 '/images/spinner/7.png',
 '/images/spinner/8.png',
 '/images/spinner/9.png',
 '/images/spinner/10.png',
 '/images/spinner/11.png',
 '/images/spinner/12.png'
 ],
 width: 33,
 height: 33
 });

前回で紹介した通りコンテナとなるViewを生成して格納しておきます。

var titleContainer = Ti.UI.createView({
 width: Ti.UI.SIZE,
 height: Ti.UI.SIZE,
 layout: 'horizontal'
 });
titleContainer.add(spinner);
 $.mainWindow.titleControl = titleContainer;

ここでビルドしてみるとわかるのですが、画像は表示されません。

スクリーンショット 2014-02-10 11.40.46

 

これは画像は複数セットされているがアニメーションがスタートしていないためです。なので以下のようにstartメソッドを実行するようにしてビルドすれば画像が表示されます。

spinner.start();

スクリーンショット 2014-02-10 11.43.27

 

画像とNavBarの背景色があっていないのでちょっと変ですが、大目に見てください。style設定でNavigationWindowのbackgroundColorを#fffにすれば馴染むと思います。

Labelも一緒に入れてみる

これだけだとちょっと物足りないのでNow Loading…というLabelも並べてみます。

var title = Ti.UI.createLabel({
 text: 'Now Loading...'
 });
titleContainer.add(title);

するとこうなります。

スクリーンショット 2014-02-10 11.47.38

 

画像と文字がくっついてしまっていて見栄えが悪いので、Labelのleftプロパティに10を設定して再ビルドしてみると以下のようになりました。

スクリーンショット 2014-02-10 11.49.00

 

いい感じです。

まとめ

Titanium Mobileでの開発にはiOS SDKを直接あつかう本来の開発に比べると不自由な部分があるのは否めません。しかし今回ぐらいのカスタマイズが出来るのであれば割りと一般的なUIの構築には困らないのではないかと思います。まだまだ応用の効くAPIもあるかもしてないのでこれからも発見次第お伝えしていきたいと思います。

標準
loading
Development

TitaniumでiOSのNavBarにローディング中を示す表示をしてみる 前編

今回はTitaniumでiOS開発をしていて見つけたテクニックを紹介します。慣れている人なら当たり前のことかもしれませんが僕は自分でこのテクニックを見つけてTitaniumのコツを掴んだような気がしました。

NavBarとは

Windowの上部に表示されるエリアでiOSではウィンドウのタイトルや、画面遷移するボタンを左右に表示させるためのものです。

これは Ti.UI.NavigationWindow や TabGroup を親に持つWindowで表示されます。なので親の存在しないWindowオブジェクトに対していくらtitle要素やbarColorを設定しても全く表示されないので注意が必要です。

<Alloy>
  <NavigationWindow platform=”ios”>
<Window title=”test”>
</Window>
</NavigationWindow>
</Alloy>

=>この場合はNavBarが表示されてタイトルにtestが入る

スクリーンショット 2014-02-08 15.52.26

<Alloy>
<Window title=”test”>
</Window>
</Alloy>

=> NavBarエリアは表示されない

スクリーンショット 2014-02-08 15.53.23

 

NavBarのタイトルエリアのAPI

タイトルエリアには通常、Windowのtitleプロパティにセットされた文字列が表示されます。これを独自のUIを変えるためにはWindowのtitleControlというプロパティを利用します。

Titanium 3.Xドキュメントには以下のように書いてあります。(2014年2月8日現在)

titleControl : Titanium.UI.View
View to show in the title area of the nav bar.

つまりWindow.titleControlには Ti.UI.View そのものか Ti.UI.View を継承しているオブジェクトがセットできるということです。

ただしこれは1つまでという制限があります。例えばLabelはTi.UI.Viewを継承しているオブジェクトなのでtitleControlにセットできますが、2つ連続でセットしても後勝ちになってしまい、この方法では複数のLabelは表示できません。

views/index.xml

<Alloy>
<NavigationWindow id=”navigationWindow”>
<Window id=”mainWIndow”>
</WIndow>
</NavigationWindow>
</Alloy>

controllers/index.js

$.navigationWindow.open();
$.mainWindow.titleControl = Ti.UI.createLabel({ text: ‘hoge’ });
$.mainWindow.titleControl = Ti.UI.createLabel({ text: ‘fuga’ });

=> これではタイトルエリアに fuga が表示される(厳密にはhogeが一瞬表示された後にfugaに置き換わる挙動をする)

スクリーンショット 2014-02-08 16.09.06

 

Ti.UI.Viewでラップすれば複数表示できる

そうなんです。Viewオブジェクトは子供を持てる仕様なのです。ですから複数の要素を表示させたい場合はプレーンなViewをコンテナーとして扱い子供に複数のオブジェクトを配置すればいいんですね。

var titleContainer = Ti.UI.createView();
titleContainer.add(Ti.UI.createLabel({ text: ‘hoge’ }));
titleContainer.add(Ti.UI.createLabel({ text: ‘fuga’ }));
$.mainWindow.titleControl = titleContainer;

=> titleControlには1つのViewしかセットしていないので複数のLabelが表示される

スクリーンショット 2014-02-08 16.14.42

 

あ、でも重なってしまった…という場合は

layoutオプションで子供たちを重ならないように配置させる

こんな時のためにlayoutオプションという便利なものがTianiumには用意されているんですね。

使いかたは並ばせたい複数の要素を内包している親要素に対して指定します。今回は横に重ならないように並ばせたいので layout: ‘horizontal’ を使いました。

var titleContainer = Ti.UI.createView({ layout: ‘horizontal’ });

=> 子どもたちは重ならずに整列

スクリーンショット 2014-02-08 16.21.21

 

あれ…でも今度は変な位置になってしまいましたね。

Ti.UI.SIZEで中身の要素のサイズに合わせる

なぜ左上にLabelが移動してしまったのか、それはコンテナビューのエリアが割りと広めに確保されているかなんですね。
背景色をつけてみるとわかりやすいです。

スクリーンショット 2014-02-08 16.24.19

 

この状態で「横に並んで!」と言ったら左上に来てしまうのも無理は無いかと。

またこんな時のためにTitaniumには便利なAPIが用意してあって、コンテナ要素のwidthとheightにTi.UI.SIZEというものをセットしておくと、子供の要素の大きさに合わせて自身のサイズを設定してくれるんですね。

var titleContainer = Ti.UI.createView({
layout: ‘horizontal’,
width: Ti.UI.SIZE,
height: Ti.UI.SIZE
});

=> 子供のサイズが親に反映される

スクリーンショット 2014-02-08 16.28.22

 

いい感じです。

次回につづく

なんか一つ一つ順を追って紹介していたら長くなってしまったのでこの続きは後編にしたいと思います。

次は今回の配置テクニックを活かしてローディング感のある見た目にしてみたいと思います。

標準
Native American 12
Development

JavaScriptでネイティブアプリを開発できるTitanium MobileとAlloyをつかってみよう その3

前回はalloy generateコマンドでcontrollerとviewとstyleを生成してモーダルウィンドウを表示してみました。
今回は右から新しいウィンドウがスライドして現れる画面遷移を作成してみたいと思います。

コントローラーの初期状態

まずはメインのコントローラであるindex.jsの中身を以下のようにして、初期画面を表示するだけにしてみます。

$.index.open();

スクリーンショット 2014-01-31 10.09.19

ここで使っている $ はalloyの提供するBaseControllerクラスを継承したindexコントローラのインスタンスです。
また$.indexはビュー内のWindowにid属性がふられていない場合にビューファイルの名称でWindowオブジェクトにアクセスできるようです。

ビューを画面遷移に対応させる

ビューファイルを以下のように書き換えて右へ右へと画面遷移を出来るように準備します。

<Alloy>
    <NavigationWindow id="navigationWindow" platform="ios">
        <Window class="container" title="First Win">
             <Button title="click me" />
         </Window>
     </NavigationWindow>
</Alloy>

WindowをNavigationWindowというオブジェクトでラップしています。こうすることで画面上部にタイトルや前の画面に戻るためのナビゲーションバーが表示されるようになります。

ビューファイルでNavigationWindowを追加し、id属性を定義したのでコントローラーで $.index.open() のままだとエラーしてしまいます。
なので「navigationWindowというidのWindowを開く」というコードに変更します。

controllers/index.js

$.navigationWindow.open();

ビルドしてみると以下のように表示されます。

スクリーンショット 2014-01-31 10.27.42

 

ボタンのイベントハンドラを定義

そして中央に配置したボタンのタグにonClick属性を追加してここをタップすると遷移する動作を行うようにしてみます。

<Button title="click me" onClick="openWin" />

またコントローラーに戻って以下のようにボタンに紐付けたイベントハンドラを定義してみます。

function openWin(e) {
  console.log(e);
}

まずは単に受け取ったイベントオブジェクトをconsole.logしてみるだけにしました。このままビルド(titanium build -p ios)してボタンを押すと以下のようなログが出力されます。

[INFO] {
[INFO]     bubbles = 1;
[INFO]     cancelBubble = 0;
[INFO]     source = "[object __alloyId1]";
[INFO]     type = click;
[INFO]     x = "38.5";
[INFO]     y = "20.5";
[INFO] }

今回は特にイベントオブジェクトの中身に応じて処理を切り替えることはしませんが、こうして書いたコードを一つ一つビルドして確認すればなにか不具合が起きた時に手戻りが少なくて済むようになる事が多いのでなるべくこまめにconsole.logをするようにしています。

さて、このopenWinの中で新たなWindowを生成し画面遷移を起こさせてみたいと思います。

function openWin(e) {
  var win = Ti.UI.createWindow({
     title: 'Sub Win',
     backgroundColor: '#fff'
   });
   $.navigationWindow.openWindow(win);
}

TiとはTitaniumオブジェクトのエイリアスでどちらでも同じものです。Ti.UIというオブジェクトに様々なビューオブジェクトを生成するcreateXxxといったメソッドが定義されています。createWindowメソッドを使うと真っ黒で何も無いWindowが生成されるのでtitleに「Sub Win」、背景色を白に設定しました。

次に$.navigationWindowのopenWindowメソッドに生成した新しいWindowを渡すことでアニメーション付きで画面遷移をしてくれるようになります。
画面遷移の途中は早すぎてキャプチャできないですが遷移後は以下の様な画面が表示されます。

スクリーンショット 2014-01-31 10.49.34

真っ白なWindowを生成しただけですが左上に最初の画面に戻るためのボタンが用意されていますね。これがモーダルにはないNavigationWindowの特徴です。

まとめ

今回紹介した画面遷移はかなりポピュラーなUIデザインパターンなのでこれを覚えておくだけでも簡単なアプリが作れてしまいそうですよね。
しかしNavigationWindowはiOSにしか定義されていないクラスのようです。Androidは端末そのものに戻るボタンを実装しアプリケーション側では意識する必要がないようにデザインされているためでしょう。

要約すると

  1. NavigationWindowにidをふる
  2. コントローラーからふったidを参照して初期画面を表示する
  3. ボタンのonClick属性でイベントハンドラを定義する
  4. 新しいウィンドウを生成してNavigationWindowのopenWindowメソッドに渡す

以上です。

標準
Native American 12
Development

JavaScriptでネイティブアプリを開発できるTitanium MobileとAlloyをつかってみよう その2

こんにちは山形です。
さて今回は前回につづいてTitaniumのAPIを使って具体的にUIの配置等を行っていきたいと思います。

前回はツールのインストールなどを行いました。

alloy generateコマンド

Alloyをインストールするとalloyコマンドが使えるようになります。これがrailsを意識しているようなのでrailsに慣れている人ならわかりやすいかと思います。

まず画面を追加してみたいのでgenerate controllerコマンドをつかって画面を追加してみます。

alloy generate controller my_modal

こうすると
app/controllers/my_modal.js
app/styles/my_modal.tss
app/views/my_modal.xml
の3つのファイルが作成されます。

この段階でtitanium buildしてみても前回同様Hello Worldという白い画面が表示されるだけです。これはTitaniumのデフォルト画面であるindex.jsというコントローラが表示されているだけなのでindexからmy_modalを呼び出す形になります。

それでは順をおって説明していきます。

controller

まずはコントローラー。app/controllers/my_modal.js等ですね。やろうと思えばここに全てのコードを書くこともできます。

しかしAlloyをつかってわざわざMVCスタイルになっているので、コントローラーには画面の遷移や、ボタンのタップに反応してモデルを呼び出すなどにとどめておいたほうがよいでしょう。

最初に呼び出されるコントローラであるindex.jsに以下のコードを追加してmy_modalを開く処理を追加してみます。

var myModal = Alloy.createController(‘my_modal’).getView();
myModal.open({ modal: true });

ここでとりあえずtitanium buildしみると以下の様な画面になりました。

スクリーンショット 2014-01-22 11.13.52

 

「myModalにはopenという関数は無いよ」と書いてありますね。
この原因を探るためにviewファイルを見てみましょう。

view

app/views/my_modal.xml というファイルがmy_modalのviewファイルです。XMLで書かれていますがhtmlの様な感覚でマークアップしていけます。

中身はこんなコードになっています。

<Alloy>
<View class=”container”>
</View>
</Alloy>

これではエラーしてしまいますね。ViewというのはTitanium.UI.Viewクラスのインスタンスなのですが、Viewにはopenという関数はありません。

なのでViewの部分をWindowに置き換えてもう一度ビルドしてみます。

<Alloy>
<Window class=”container”>
</Window>
</Alloy>

スクリーンショット 2014-01-22 11.24.05

 

なんか黒いっすね…

これはWindowのデフォルト背景色が黒だからです。このままじゃよくわかんないのでstyleを変更してウィンドウの存在感を出してみたいと思います。

style

スタイルファイルはapp/styles/my_modal.tssです。tssというのはcssとjsonを掛けあわせたような雰囲気のする形式です。

tssでビューに対置したオブジェクトのプロパティを操作してスタイルを変えていくという感じです。
なのでWindowに対してbackgroundColorの値を変更してみます。

“Window”: {
backgroundColor: “green”
}

なんか普通じゃつまらないので緑色にしてみました。
ついでにビューLabelを追加してこれにも色をつけてみます。

<Alloy>
<Window class=”container”>
<Label>My Modal</Label>
</Window>
</Alloy>

“Window”: {
backgroundColor: “green”
}
“Label”: {
color: “red”
}

そして出来上がった画面がこちらです。

スクリーンショット 2014-01-22 11.45.16

 

まぶしい!ださいですね。

まとめ

軽い感じで起動と同時にモーダル画面を表示させてみましたが、Titaniumの手軽さが伝わったでしょうか??JavaScriptでかけるというのはこんなにもさくさく進めていけるのですね。
次回はもっと複雑な画面遷移をご紹介したいと思います。

標準
Native American 12
Development

JavaScriptでネイティブアプリを開発できるTitanium MobileとAlloyをつかってみよう その1

こんにちは。山形です。
最近はマラソン大会に出るために走り始めました。走った時間や距離を測るのにRuntasticというiPhoneアプリが便利なのですが、今お気に入りの隅田川沿いコースだとルートの解析が出来なくて困っています。GPS機能を妨害するものでもあるんでしょうか?

さて今回はiPhoneアプリ等をJavaScriptで開発できるツールTitanium Mobile(タイタニウムと読みます)を使ってみたので導入部分についてご紹介したいと思います。

JavaScriptとは

best-javascript-sites

JavaScriptは元々ブラウザ内で動くプログラミング言語として開発されました。
今日ではブラウザだけでなくサーバーサイドのスクリプト言語としても使われることが多くなりまりました。Google Chromeに搭載されているJavaScriptエンジンV8を利用したNode.jsや、Javaで実装されたRhino等がそれにあたります。

Titanium Mobileで使用するJavaScriptの種類としてはNode.js環境に近いものと考えていいようです。

Titanium Mobileとは

TITANIUM_logo1

先に触れましたがJavaScriptでネイティブのモバイルアプリをクロスプラットフォームに開発できるツールです。
つまりiOSアプリとAndroidアプリのソースコードを共有しながら同時にビルド出来るということです。

しかし現実はなかなか厳しようです。iOSとAndroidではUIの仕組みが違いますし、iOSにはあってAndroidには無い機能(そのまた逆も)あるからです。その場合コード内で「iOSならばこちらをAndroidならば…」といった条件分岐をすることで解決します。

なんだ結局両方のコードを書くのかと僕も思いましたが、標準的なUIを使っていればそのような場面は少ないですし、アプリケーションのコアになるロジック部分はUIに依存しないことが多いと思いますのでTitaniumを使うメリットは十分にあると感じました。

Alloyとは

alloy

Alloy(アロイ)はTitaniumのためのRailsのようなジェネレーターを備えたMVCフレームワークです。

Alloy自体はNode.jsのライブラリとして配布されています。Node.jsを使ったことのある人であればお馴染みの npm install alloy -g でインストールができます。そしてTitanium CLIと組み合わせることでIDEに頼らない開発環境が手にはいります。

僕はVimmerでRails開発者なのでこれはRailsを使ってきた自分にとってはかなり嬉しい要素でした。

環境を整える

さて実際に環境を整える方法ですが、まずなにはともあれiOS開発ツールであるXCodeをインストールしましょう。
これはAppStoreアプリを立ち上げてXCodeを検索しインストールボタンを押すだけです。

XCodeがインストールできたら今度はNode.jsをインストールしましょう。こちらのオフィシャルサイトからインストーラーが落とせます。

次にTitaniumのインストールはこちらのオフィシャルサイトからインストーラを落としてきましょう。

最後にAlloyのインストールは先に触れた npm install -g alloy で完了です。

プロジェクトを作成してみる

プロジェクトの作成はこちらで手順が紹介されていますが軽く順を追って紹介したいと思います。

まずターミナルでプロジェクトを作成するディレクトリまで移動して以下のコマンドを打ちます。

titanium create --name=sampleapp --id=jp.halenohi.sampleapp --platforms=iphone

nameにはアプリの名前、idはお持ちのドメインを逆転させてサブドメインに当たる部分にアプリ名を入れるのが良いようです。platformは今回はiphoneのみにしました。
Directory to place project: というオプションを聞かれるのですが既にプロジェクトを置くディレクトリにいる場合はそのままエンターでOKです。
こうするとsampleappというフォルダと中にいくつかのファイルとフォルダが作られます。

.gitignore
LICENSE
README
Resources
tiapp.xml

次にsampleappフォルダへ移動して以下のコマンドを打ちます。

cd sampleapp
alloy new

これでappとpluginsというフォルダが作成されました。
以上でプロジェクト作成は完了です。

Hello World

プロジェクトを作成したらコードを書き始める前にそのままビルドしてみます。

titanium build -p ios

pオプションでプラットフォームを指定します。
するとビルドが始まり以下の様な画面でiOSシミュレータが起動しました。

スクリーンショット 2014-01-20 12.41.10

 

Hello World成功です。

まとめ

まだアプリのコードは1行も書いてないですが、ツールをインストールしコマンドを幾つか打つだけでHello Worldが出来てしまいました。これは本当にRailsをやってきた僕には馴染みやすくて嬉しいですね。これでもうXCode上でjkjkとかescキーを誤打しなくて済みますね!

次回で少しUIの作成方法等についてご紹介したいと思います。

標準