アプリプログラムのソース
ちょいと昨日せこせことアプリの作成をしたので、作成にあたって押さえておきたい点を紹介したいと思います。
スクロールバーを付ける
Flex4からスクロールバーは自前で準備することとなったため以下のようにScrollerを配置します。
<s:Scroller width="100" height="100"> <s:Group> <s:Image source="hoge.jpg" height="200"/> </s:Group> </s:Scroller>
レイアウトクラスを駆使する
Flex4からは便利なレイアウトクラスが登場しました。これで縦、横の制御やタイル状に並べたりすることができます。
<s:Group> <s:layout> <s:HorizontalLayout verticalAlign="middle" horizontalAlign="left"/> </s:layout> <s:Image source="@Embed('assets/loader.png')"/> <s:Label text="Image Loading..." color="0x333333" top="0"/> </s:Group>
アニメーションクラスの autoCenterTransform を使う
Flex3でなかなか面倒だったのが画像を中心から回転させることでした。今回からは autoCenterTransform プロパティが登場し、画像の中心から回転させることが用意になりました。
<s:Parallel repeatCount="0"> <s:Rotate angleFrom="0" angleTo="360" duration="2000" autoCenterTransform="true" easer="{new Linear()}"/> </s:Parallel>
ViewNavigatorで表示するたびにViewを毎回作成させない
現在のAdobeさんのサンプルプログラムではページの遷移がある度にページを作成します。
これでは、HTTPServiceなど初期化の際に使用する場合はかなりまずいので以下ように View に destructionPolicy を設定します。
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" title="Maid Photo Gallery" destructionPolicy="none" >
メイドフォトギャラリギャラリー
簡単なものですが今回自分が作成したアプリです。
アプリはアンドロイドマーケットにて「メイド」などで検索すれば出てくるかと思います。
ソースは以下になります。
ちょっとでもアプリ作成の参考になればうれしいです。
MaidPhotoHome.mxml
トップに表示されるベージです。ネットから画像情報を取得して、タイル状に画像を配置します。
<?xml version="1.0" encoding="utf-8"?> <s:View xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" chromeColor="#FF8CE3" creationComplete="view1_creationCompleteHandler(event)" overlayControls="false" symbolColor="#FF74D0" title="Maid Photo Gallery" destructionPolicy="none" > <fx:Script> <![CDATA[ import com.adobe.serialization.json.JSON; import flash.net.navigateToURL; import mx.events.FlexEvent; import mx.rpc.events.ResultEvent; import spark.components.Image; import spark.events.IndexChangeEvent; //初期化 protected function view1_creationCompleteHandler(event:FlexEvent):void { myHts.send(); } //HTTPServiceの完了イベント private var obj:Object = new Object(); protected function onResult(e:ResultEvent):void { obj = JSON.decode(e.result.toString()); //画像をタイル状に配置していく for( var i:int = 0 ; i < obj.length ; i ++){ var image:Image = new Image(); image.name = "" + i; image.width = 110; image.height = 110; image.filters = [dsf]; image.source = obj[i].icon; image.setStyle( "backgroundColor" , 0xffffff ); image.addEventListener(Event.COMPLETE , onRender ); image.addEventListener(MouseEvent.CLICK , onClick ); moetenMaidPhotoGallery.imageArr[i] = image; tg.addElement( image ); } } //画像読み込み完了イベント private function onRender(e:Event):void { myAnim.play([e.currentTarget]); } //画像クリックイベント private function onClick( e:Event ):void { navigator.pushView( DetailView , obj[int( e.currentTarget.name ) ] ); } //ラベルクリックイベント private function label1_clickHandler(event:MouseEvent):void { navigateToURL( new URLRequest ('http://moeten.info/maidcafe/') ); } ]]> </fx:Script> <fx:Declarations> <!--アニメーション--> <s:Parallel id="myAnim" duration="1000"> <s:Fade alphaFrom="0.1" alphaTo="1" duration="1000" /> </s:Parallel> <!--配列--> <s:ArrayCollection id="listData" /> <!--HTTP--> <s:HTTPService id="myHts" url="http://moeten.info/maidcafe/json.php" fault="{}" invoke="{}" result="onResult(event)" resultFormat="text" showBusyCursor="true" /> <s:DropShadowFilter id="dsf" alpha="0.5" distance="0" blurX="4" blurY="4" color="0x000000"/> </fx:Declarations> <!--レイアウト--> <s:layout> <s:VerticalLayout horizontalAlign="center" paddingTop="10" paddingLeft="30" paddingRight="20"/> </s:layout> <!--画像配置用Group--> <s:Scroller id="myS" width="100%" height="100%" verticalCenter="0" horizontalCenter="0"> <s:Group id="tg" verticalCenter="0" horizontalCenter="0"> <s:layout> <s:TileLayout columnWidth="125" rowHeight="125" verticalGap="14" horizontalGap="14" verticalAlign="middle" horizontalAlign="center"/> </s:layout> </s:Group> </s:Scroller> <!--著作情報用Group--> <s:Group width="100%" height="20"> <s:layout> <s:BasicLayout/> </s:layout> <s:Rect width="140" height="100%" topLeftRadiusX="5" topLeftRadiusY="5" topRightRadiusX="5" topRightRadiusY="5" horizontalCenter="0"> <s:fill> <s:SolidColor color="0xffccff"/> </s:fill> </s:Rect> <s:Label click="label1_clickHandler(event)" color="0x666666" fontSize="12" bottom="5" buttonMode="true" verticalCenter="2" horizontalCenter="0" text="- moeten.info -"/> </s:Group> </s:View>
DetailVew.mxml
画像単体表示用です。画像をSDカードに保存したり、お店の説明を表示することができます。
<?xml version="1.0" encoding="utf-8"?> <s:View xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" destructionPolicy="none" xmlns:mx="library://ns.adobe.com/flex/mx" creationComplete="view1_creationCompleteHandler(event)" title="{data.title}" viewActivate="refresh()"> <fx:Script> <![CDATA[ import mx.events.FlexEvent; import spark.effects.Wipe; import spark.effects.easing.Linear; //初期化関数 protected function view1_creationCompleteHandler(event:FlexEvent):void { myPB.visible = true; startLoader(); } //リフレッシュイベント public function refresh():void { } //画像を読み込む private var loader:URLLoader; protected function startLoader():void{ var request:URLRequest = new URLRequest( data.image ); loader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE , onComp ); loader.load(request); } //画像読み込み完了 protected function onComp( e:Event ):void{ saveBtn.enabled = true; image.source = loader.data; this.removeElement(myPB); myAnim.play([image]); } //画像を保存 protected function saveButton_clickHandler(event:MouseEvent):void { var file:File = File.documentsDirectory.resolvePath( data.image_name ); var stream:FileStream = new FileStream(); try { stream.open(file, FileMode.WRITE ); var ba:ByteArray = loader.data; stream.writeBytes( ba ); } catch (e:EOFError) { // ファイル終端の処理 } catch (e:IOError) { // 入出力エラーの処理 } finally { // ストリームをクローズする saveBtn.label = "保存しました"; saveBtn.enabled = false; stream.close(); } } //お店ページへ飛ぶ protected function launchButton_clickHandler(event:MouseEvent):void { navigateToURL(new URLRequest(data.url)); } //お店ページへ飛ぶ protected function label1_clickHandler(event:MouseEvent):void { navigateToURL(new URLRequest(data.url)); } //お店紹介表示 protected function button1_clickHandler(event:MouseEvent):void { if( myComment.visible == true ){ myComment.visible = false; commentBtn.label = "お店説明"; }else{ commentBtn.label = "閉じる"; myComment.visible = true; } } ]]> </fx:Script> <fx:Declarations> <!--アニメーション--> <s:Parallel id="myAnim" effectEnd="{commentBtn.visible = true;myTitleBox.visible = true; myTitle.visible = true;}"> <s:Fade alphaFrom="0" alphaTo="1" duration="2000"/> <s:Rotate3D angleXFrom="-10" angleXTo="0" angleYFrom="-40" angleYTo="0" angleZFrom="-10" angleZTo="0" duration="2000" autoCenterTransform="true"/> </s:Parallel> <s:Parallel id="myMove" repeatCount="0" duration="20000"> <s:Move xFrom="{this.width}" xTo="{-myTitle.width}" easer="{new Linear()}" duration="20000"/> </s:Parallel> <s:Parallel id="myShow"> <s:Fade alphaFrom="0" alphaTo="1" duration="1000"/> <s:Rotate3D angleXFrom="90" angleXTo="0" autoCenterTransform="true" duration="1000"/> </s:Parallel> <s:Parallel id="myRotate3D" repeatCount="0"> <s:Rotate angleFrom="0" angleTo="360" duration="2000" autoCenterTransform="true" easer="{new Linear()}"/> </s:Parallel> <s:Sequence id="myFade" repeatCount="0"> <s:Fade alphaFrom="0.3" alphaTo="1" duration="900"/> <s:Fade alphaFrom="1" alphaTo="0.3" duration="900"/> </s:Sequence> </fx:Declarations> <!-- 縦のレイアウト --> <s:Scroller width="100%" height="100%" > <s:Group contentBackgroundColor="#FFFFFF"> <s:layout> <s:VerticalLayout horizontalAlign="center" verticalAlign="middle"/> </s:layout> <s:Image id="image" width="100%"/> </s:Group> </s:Scroller> <!--画像読み込み時に表示するローダーアイコン--> <s:Group id="myPB" horizontalCenter="0" verticalCenter="0" removedEffect="Fade"> <s:layout> <s:HorizontalLayout verticalAlign="middle" horizontalAlign="left"/> </s:layout> <s:Group width="55" height="55" clipAndEnableScrolling="true"> <s:Image alpha="0.5" source="@Embed('assets/loader.png')" creationCompleteEffect="myRotate3D"/> </s:Group> <s:Label text="Image Loading..." color="0x333333" top="0" creationCompleteEffect="myFade"/> </s:Group> <!--お店タイトル--> <s:Group id="myTitleBox" width="100%" clipAndEnableScrolling="true" visible="false" showEffect="Fade"> <s:Rect alpha="0.9" height="40" width="100%"> <s:fill > <s:SolidColor color="0xffccff"/> </s:fill> </s:Rect> <s:Label id="myTitle" y="0" chromeColor="#563FFF" click="label1_clickHandler(event)" color="0xffffff" fontSize="18" top="12" text="{data.todouhuken+' '+data.category+' '+data.name}" textAlign="center" showEffect="myMove" visible="false" > <s:filters> <s:GlowFilter id="gf" blurX="4" blurY="4" strength="6" color="0xff40d4"/> </s:filters> </s:Label> </s:Group> <!--お店説明--> <s:Group id="myComment" visible="false" horizontalCenter="0" verticalCenter="30" width="90%" showEffect="{myShow}" hideEffect="Fade"> <s:layout> <s:VerticalLayout horizontalAlign="center" paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10"/> </s:layout> <s:Scroller> <s:Group minHeight="300" maxHeight="400" clipAndEnableScrolling="true" width="100%"> <s:TextArea lineHeight="24" width="100%" borderColor="0xffccff" color="#000000" alpha="0.9" borderVisible="false" editable="false" fontSize="18" horizontalCenter="0" text="{data.setumei}" selectable="false"/> </s:Group> </s:Scroller> <s:VGroup width="100%" paddingBottom="10" paddingTop="10" gap="20" horizontalAlign="center"> <s:Button width="100%" height="40" label="公式サイトへGO!" click="launchButton_clickHandler(event)" color="#FFFFFF" horizontalCenter="0"/> <s:Button id="saveBtn" width="100%" height="40" label="画像保存" click="saveButton_clickHandler(event)" color="#FFFFFF" cornerRadius="7" enabled="false" horizontalCenter="0"/> </s:VGroup> </s:Group> <!--説明呼び出しボタン--> <s:Button mouseDownEffect="Fade" id="commentBtn" right="20" top="60" height="54" label="お店説明" alpha="0.9" chromeColor="#FFFFFF" click="button1_clickHandler(event)" visible="false" showEffect="myShow" color="#008AC3" cornerRadius="30" fontSize="18"/> </s:View>
参考リンク
- Adobe Labs - Adobe AIR Launchpad
- AIR2.5のサンプルプログラムとソースを取得できます。
- Flex SDK 4.5 “Hero”を使って、お手軽Androidアプリ開発 | ClockMaker Blog
- AIR2.5のサンプルプログラムとソースがダウンロードできます。
- Mobile Application - Flex SDK - Adobe Open Source
- AIR2.5の説明
- View and ViewNavigator - Flex SDK - Adobe Open Source
- ViewNavigatorの説明。
- spark.effects.Animate - Adobe® Flex® 4.1 リファレンスガイド
- 今回から扱いが少し変わったアニメーションの説明
- mx.states.AddItems - Adobe® Flex® 4.1 リファレンスガイド
- stateの説明。Flex4からはstateが重要視されてます。
- Flex | Blog for Nayan
- viewStackの使い方の説明