はじめに(前回までのおさらい)
AdobeからFlash Builderのマイナーアップデート版である「Flash Builder 4.5」が発売されたことで、Apple iOS、Android、BlackBerry Tablet OSに向けたアプリケーション開発がFlash Builder上でできるようになりました。つまり、従来のFlash/Flex/AIRの開発ノウハウをそのままスマートフォン/タブレット向け開発に活かせるということになります。
Flash Builderは、前回の記事『これからはスマートフォン開発もFlash Builder4.5で!~ Twitter API連動のiPhoneアプリを3分で構築 ~』で紹介したとおり、主にはプログラマ向けのAdobe Flash制作ツールです。元々デザイナー向けに進化を重ねて来たFlash Professionalと比べると、コードを書くという部分に特化しています。ですが、Flash Builderの機能はそれだけではありません。コンポーネントと呼ばれるあらかじめ用意された部品を組み合わせることで、アプリケーションの開発を進めて行くことができます。
前回作成したサンプルでは、コンポーネントをドラッグ&ドロップして画面に配置していくことで、アプリケーションを作りました。しかも、Twitter APIへの接続、解析、表示までもドラッグ&ドロップで行うことができたのは、驚きだったのではないでしょうか。
今回は、前回のサンプルを発展させていきますが、いよいよコードでの記述がメインとなっていきます。Flash BuilderでiOS向けアプリを作る際に、どんな形でコードを書き、形にしていくのかを、一緒にサンプルを作りながら見ていきましょう。コードの細かな部分がわからなくても、実際に打ち込んで実行させてみることをおすすめします。ただし、今回もMXML(Flexフレームワーク上で使われるXML)の編集がほとんどで、ActionScriptのコーディングはほとんど行いません。
Flash Builder 4.5は、Adobeのサイトよりダウンロードが可能です。まずは、下記のボタンから、60日間無料で利用できる体験版を使ってみましょう。60日あればFlash Builderでできる大抵のことを学ぶだけの時間があります。ダウンロードにはAdobe IDが必要ですが、以前作成したことがあれば、そのIDを利用可能です。詳細な導入手順は、前回の記事を参照ください。
今回作成するサンプルアプリケーション
前回作ったサンプルは、Twitterのアカウントとアイコンが表示されている画面の下部に、Twitterの最新のつぶやき1件を表示するというものでした。
このサンプルアプリケーションは、iPhone 3GS向けに表示をさせるときちんと表示されますが、実はiPhone 4やiPadで表示しようとすると表示がずれてしまいます。原因は解像度の違いで、iPhone 3GSが320×480の解像度なのに対し、iPhone 4は480×960、iPadは、768×1024のピクセル数となっているためです。前回のサンプルでは、表示場所をX座標、Y座標という形で指定していたために、違う解像度ではきちんと表示がされない事態になってしまいます。
今回のサンプルでは、そんな問題を解決すべく、いくつかの処理の追加を行います。例えば、解像度が変わることを踏まえてどう対処すべきか? 縦表示(ポートレート表示)と横表示(ランドスケープ表示)の切替に対応させるには? といった部分の解決です。
見た目的には大きく変わった部分はありませんが、一部変更があり、ラベルとアイコン画像がセンター寄せではなく、2段カラムで表示されるようになっています。こういったレイアウトに関する話も盛り込んだサンプルとなっているので、ぜひ実際に打ち込んで試してみてください。
さまざまなデバイスに対応できる柔軟なレイアウト構造
Webデザインの世界には「リキッドレイアウト」という言葉があります。リキッドレイアウトというのは、画面の幅に合わせて画面内の各要素の幅が伸び縮みするタイプのレイアウト手法で、amazon.comなどはこのような方式になっています。
ポイントとしては、レイアウトの指定にピクセル数ではなく、パーセント表示を使う点です。このおかげで、画面サイズに応じた幅でコンテンツを閲覧できます。
Flexフレームワークもピクセル数だけでなく、パーセント表示で要素のサイズを決めることができます。こうすることで、iPhoneを横向きにした場合はその幅に合わせたりといった柔軟なレイアウトが実現できるのです。また、iPhoneに限らずさまざまな画面サイズの端末がスマートフォンにはあるため、なるべく解像度に依存しないレイアウト手法を導入することで、汎用性が高いアプリケーションを作成できます。
前回のサンプルアプリを修正
さっそく、前回のサンプルコードを修正していきましょう。
まず、[パッケージエクスプローラー]パネルにあるプロジェクトを展開して、「src」フォルダを開きます。その中に「views」フォルダがあるので、その中にある「tweeeTweeeView.mxml」をダブルクリックして開きましょう。
まずは、「s:Label
」タグ、「s:Image
」タグ、「s:TextArea
」タグにあるx属性とy属性を取り除きます。x属性やy属性は表示する座標を指定する属性ですが、さまざまな解像度に対応させるため、表示座標の指定は行いません。
続いて、s:Label
タグ、s:Image
タグ、s:TextArea
タグ全体を「s:VGroup
」タグで囲います。VGroup
要素のVはVerticalの略で、縦方向に要素をグルーピングするというものです。わかりやすくいうと、このタグで囲った要素はHTMLでいうボックス要素と同等になり、ラベル、アイコン画像、テキストエリアが縦に並ぶように設定できます。座標で縦方向に並べていた部分の代わりです。
下記のようになっているソースの一部を、
<s:Label x="75" y="37" color="#FFFFFF" fontSize="26" text="FOLLOW ME!!
@kara_d" textAlign="center"/> <s:Image x="109" y="101" width="102" height="140" source="assets/utweet-kara_d.png"/> <s:TextArea id="textArea" x="7" y="263" height="139" creationComplete="textArea_creationCompleteHandler(event)" text="{Operation1Result.lastResult.status[0].text}"/>
下記のように変更してみましょう。
<s:VGroup width="100%" height="100%" horizontalAlign="center" paddingBottom="8" paddingLeft="8" paddingRight="8" paddingTop="8"> <s:Label color="#FFFFFF" fontSize="26" text="FOLLOW ME!!
@kara_d" textAlign="center"/> <s:Image width="102" height="140" source="assets/utweet-kara_d.png"/> <s:TextArea id="textArea" height="139" creationComplete="textArea_creationCompleteHandler(event)" text="{Operation1Result.lastResult.status[0].text}"/> </s:VGroup>
VGroup
の中にはいろいろな属性が書かれているのがわかると思います。「horizontalAlign
」というのは横方向の位置を決める属性です。CSSではtext-alignを指定したのと同等の効果を得られます。また、「paddingBottom
」「paddingLeft
」「paddingRight
」「paddingTop
」は、CSSでもおなじみのパディングの指定になります。
続いて、s:Label
タグとs:Image
タグを「s:HGroup
」タグで囲みます。HGroup
要素は、囲まれた要素を横方向に並べることができ、これはCSSでいうところのfloat:leftのような表示結果になります。並び順は囲われたタグの一番最初の要素が左側になるため、左側にアイコン画像を持ってくる場合はラベルと位置を入れ替える必要があります。下記のように変更をしてみましょう。
<s:VGroup width="100%" height="100%" horizontalAlign="center" paddingBottom="8" paddingLeft="8" paddingRight="8" paddingTop="8"> <s:HGroup width="100%" height="40%" > <s:Image width="102" height="140" source="assets/utweet-kara_d.png"/> <s:Label color="#FFFFFF" fontSize="26" text="FOLLOW ME!!
@kara_d" textAlign="center"/> </s:HGroup> <s:TextArea id="textArea" height="139" creationComplete="textArea_creationCompleteHandler(event)" text="{Operation1Result.lastResult.status[0].text}"/> </s:VGroup>
ここまでで、だいたいのレイアウトが完成しました。細かな属性を各タグに指定していきます。
まずは、s:Image
タグを下記のように指定します。
<s:Image width="50%" height="100%" source="assets/utweet-kara_d.png" verticalAlign="top" horizontalAlign="left" smooth="true"/>
横幅を50%、縦を100%にしました。横幅は、右側にラベルが入るため、半分の指定にしてあります。高さは100%としていますが、HGroup
の高さが40%なので画面全体では40%の高さにおさまるという形になります。
また、「verticalAlign
」「horizontalAlign
」という属性を指定していますが、これは画像を常に左上に表示させるために欠かせない指定となります。最後に「smooth
」という属性を指定しています。こちらは、アイコン画像が端末ごとにサイズが変わった場合でもスムージングをかけてジャギーを見えなくさせてくれる効果があります。
続いてはs:Label
タグの変更です。
<s:Label text="FOLLOW ME!!
@kara_d"id="myName"/>
「fontSize
」「color
」といった見栄えの指定がなくなりました。これは、今後スタイルシートで表示部分を管理するための布石です。
最後にs:TextArea
の「width
」「height
」属性もパーセント指定にします。アプリケーションの高さ全体を100%とすると、テキストエリア部分が60%、そしてs:HGroup
で指定した部分が40%という比率で表示される構成になっています。
<s:TextArea id="textArea" height="60%" width="100%" creationComplete="textArea_creationCompleteHandler(event)" text="{Operation1Result.lastResult.status[0].text}"/>
以上で、「tweeeTweeeView.mxml」の編集は終了です。ここまでの表示部分のソース(抜粋)は下記になります。
<s:VGroup width="100%" height="100%" horizontalAlign="center" paddingBottom="8" paddingLeft="8" paddingRight="8" paddingTop="8"> <s:HGroup width="100%" height="40%" > <s:Image width="50%" height="100%" source="assets/utweet-kara_d.png" verticalAlign="top" horizontalAlign="left" smooth="true"/> <s:Label text="FOLLOW ME!!
@kara_d" id="myName"/> </s:HGroup> <s:TextArea id="textArea" height="60%" width="100%" creationComplete="textArea_creationCompleteHandler(event)" text="{Operation1Result.lastResult.status[0].text}"/> </s:VGroup>
ここまでの状態を[実行]メニューから[実行]を選択し、プレビューしてみましょう。
画面にピッタリとフィットしているのがわかると思います。
iPadとiPhone 3GSの判別テクニック
さて、ここまでのコーディングで、スクリプトを書かなくてもMXMLの編集だけで柔軟なレイアウトを行うことができました。いったんiPadでも表示させてみましょう。[実行]メニューから[実行構成]を選び、[実行構成]ダイアログを表示させます。[モバイルアプリケーション]よりプロジェクト名を[起動方法]から[デスクトップ上]-[Apple iPad]を選択して[実行]ボタンを押してみます。
すると、きちんとレイアウトはされて表示されるものの、「FOLLOW ME!!」の文字サイズが、iPhone 3GSの時と変わらず微妙な感じになってしまっているのが分かると思います。これはなんとかしないといけません。
Flexフレームワークでは、このような解像度によって起きる問題に関する対応策を用意してくれています。スタイルシートにはMediaクエリーという指定方法があり、この中で解像度による振り分けを行うことができます。Flexフレームワークでは、160dpi向け、240dpi向け、320dpi向けの指定をそれぞれ行うことができ、また、OSの判定も行って振り分けることができます。
iOS系の端末の解像度は下記のようになっています。
デバイス | 解像度 | デバイスの実際のdpi |
iPhone 4 | 960x640 | 326dpi |
iPhone 3GS | 320x480 | 163dpi |
iPad | 1024x768 | 132dpi |
Flexフレームワークのデフォルトでは、下記のような判別になっています。
DPIClassification | デバイスの実際のdpi |
160dpi | 200dpi未満(iPhone 3GS、iPad) |
240dpi | 200dpi以上280dpi未満 |
320dpi | 280dpi以上(iPhone 4) |
つまり、iPhone 4は326dpiなので、320dpiという振り分けになりますが、困るのはiPhone 3GSとiPadです。これらは画面サイズが異なるにもかかわらず、同じ端末としてしか判定ができません。こういった場合には、画面サイズによる判定方法を変更するという方法があります。ただし、この方法はちょっと上級者向けなので、オフィシャルなドキュメントにも記載されている解像度設定の変更によって行ってみます。
今回行うのは、下記のように解像度の範囲を変更する機能を組み込む作業です。作業完了後には、下記のような構成に変わります。
DPIClassification | デバイスの実際のdpi |
160dpi | 140dpi未満(iPad) |
240dpi | 140dpi以上280dpi未満(iPhone 3GS) |
320dpi | 280dpi以上(iPhone 4) |
上記のように区分けできると、160dpiのときはiPad向けのスタイルを記述、240dpiのときはiPhone 3GS向けのスタイルを記述といったように区別できます。ただし、この方法はiOS以外のデバイス対応を考えた時や、新しい解像度のiOSデバイスが発売された場合は再考する必要があります。
ActionScriptファイルの作成
では、ActionScriptファイルを用意しましょう。ここで初めて今回ActionScriptを書く機会が出てきます。とはいっても、下記ソースをコピーしてペーストするのみなので、臆することなくチャレンジしてみましょう。
まずは、[パッケージエクスプローラー]パネルにあるプロジェクトを展開して、「src」フォルダで右クリックをしてコンテキストメニューを表示させます。続いて[新規]-[ActionScriptクラス]を選んで[新規ActionScriptクラス]ダイアログを表示します。[名前]のところには「DPIFixClass」と入力してください。
[終了]ボタンをクリックすると新しいエディタが表示されるので、下記ソースコードをコピーしてペーストします。保存したらこの作業は完了です。
package { import flash.system.Capabilities; import mx.core.DPIClassification; import mx.core.RuntimeDPIProvider; public class DPIFixClass extends RuntimeDPIProvider { public function DPIFixClass() { } override public function get runtimeDPI():Number { var dpi:Number = DPIClassification.DPI_160; if (Capabilities.screenDPI < 140) { dpi = DPIClassification.DPI_160; } if (Capabilities.screenDPI >= 140 && Capabilities.screenDPI < 280) { dpi = DPIClassification.DPI_240; } if (Capabilities.screenDPI >= 280) { dpi = DPIClassification.DPI_320; } return dpi; } } }
上記ActionScriptファイルに関する詳しい説明は省略します。解像度の振り分け機能を上書きするものだと認識してもらえればいいでしょう。
スタイルシートで、解像度ごとのスタイルを一括指定
続いて、いよいよスタイルシートを記述していきます。スタイルシートは、今までレイアウトなどを記述していた「tweeeTweeeView.mxml」ファイルではなく、別のファイルに記述します。
[パッケージエクスプローラー]パネルの「src」フォルダにある「(default package)」というフォルダを開いてください。中に「tweee.mxml」というファイルがあるので、これを開きましょう。
このファイルがアプリケーションの大元ファイルとなります。まずは、先ほど作った解像度振り分けクラスを読み込めるようにします。
<s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" firstView="views.tweeeTweeeView">
と書かれている部分を
<s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" firstView="views.tweeeTweeeView" runtimeDPIProvider="DPIFixClass">
としてください。これで読み込みは完了です。
続いて、スタイルシートを記述します。スタイルシートは、CSS3と記述形式が似ていますが、プロパティ名の単語のつなぎ目が「-
」ではなくキャメル形式(先頭の単語が小文字から始まり、単語の区切りごとに大文字にする形式)になる点が異なります。例えば「font-size
」は「fontSize
」となります。
では、下記のように記述してください。「fx:Declarations
」タグの上に書きます。
<fx:Style> @namespace s "library://ns.adobe.com/flex/spark"; @namespace mx "library://ns.adobe.com/flex/mx"; /* * IOS only @ 160dpi * for iPad */ @media (application-dpi: 160) and (os-platform: "IOS") { s|Label { fontSize: 60; color: #fcc; } } /* * IOS only @ 240dpi * for iPhone 3GS */ @media (application-dpi: 240) and (os-platform: "IOS") { s|Label { fontSize: 20; color: #cfc; } } /* * IOS only @ 320dpi * for iPhone 4 */ @media (application-dpi: 320) and (os-platform: "IOS") { s|Label { fontSize: 60; color: #ccf; } } </fx:Style> <fx:Declarations> <!-- 非ビジュアルエレメント (サービス、値オブジェクトなど) をここに配置 --> </fx:Declarations>
スタイルシートにおけるMediaクエリーの使い方についての詳細はここでは控えます。興味のある方はW3Cのドキュメントなどを参照してください。
ポイントとしては、s:Label
タグのフォントサイズや色を解像度ごとに変えています。iPadは画面サイズが広いので大きなサイズ、iPhone 3GSでは、画面サイズが小さいので小さなフォントサイズ、iPhone 4は解像度が高いのでiPhone 3GSよりも大きいサイズという指定にしています。また、確認用に解像度ごとにテキストの色を少しずつ変えています(iPhone 3GSは緑、iPadはピンク、iPhone 4は紫)。
iPhone 3GS、iPad、iPhone 4の画面サイズでの表示テストをする
以上で、全工程は終了です。各デバイス用の表示を行なってテストしてみましょう。[実行]-[実行の構成]にて、起動方法を[デスクトップ上]-[Apple iPhone 3GS]や[Apple iPhone 4]や[Apple iPad]のいずれかを選択して[実行]ボタンを押すと各デバイスで表示されます。
また、[Device]メニューより[Rotate Left]や[Rotate Right]を選ぶことで画面を回転させたりして表示を確認できます。
ぜひ、いろいろと試したり調節したりして、マルチ解像度アプリケーションの実験をしてみてください。
Androidにもさまざまなタイプの解像度が存在していますが、レイアウトは今回採用したフレキシブルなレイアウトを使うことで、ほとんどの端末へ対応が可能です。細かな表示の部分でスタイルシートを扱う場合は、下記のようにAndroid向けの振り分けを「fx:Style
」内に記述していくと良いでしょう。
/* * Android only @ 240dpi */ @media (application-dpi: 240) and (os-platform: "Android") { s|Label { fontSize: 20; color: #cfc; } }