Posts tagged with: actionscript

Mobile Scrolling Components

One of the issues you can run into with AIR Mobile Development is scrolling data.  If you use a Spark List (s:List) the component has built-in scrolling.  In fact, you can even have other components around the list that do not scroll and the list that does scroll.  However, a list is not optimal for editing data.  You need a form to do that.  A form, whether it is a Spark Form or a collection of s:HGroup components with labels, does not scroll.  However, if you embed the form components inside a Spark Scroller the  form will scroll without a problem.

I have put together a sample application that demonstrates a form that has no scrolling, scrolling, and a view with a scrollable list. Below is a screenshot of each of the three lists with some sample code.

This is an example of the form that is unable to scroll. Doesn't mean much until you see the next form which is the same but is scrolled part of the way down.

</p>
<p><s:VGroup width="100%" height="100%"<br />
paddingBottom="10" paddingLeft="10"<br />
paddingRight="10" paddingTop="10"><br />
<s:TextArea text="Below is a form but this is not in a scroller so it will not scroll."<br />
editable="false" borderVisible="false" width="100%"/><br />
<s:HGroup width="100%"><br />
<s:Label width="150" text="First Name"/><br />
<s:TextInput width="100%"/><br />
</s:HGroup><br />
<s:HGroup width="100%"><br />
<s:Label width="150" text="Last Name"/><br />
<s:TextInput width="100%"/><br />
</s:HGroup><br />
<s:HGroup width="100%"><br />
<s:Label width="150" text="Street Address"/><br />
<s:TextInput width="100%"/><br />
</s:HGroup><br />
<s:HGroup width="100%"><br />
<s:Label width="150" text="City"/><br />
<s:TextInput width="100%"/><br />
</s:HGroup><br />
......<br />
<s:HGroup width="100%"><br />
<s:Label width="150" text="Work Phone"/><br />
<s:TextInput width="100%"/><br />
</s:HGroup><br />
</s:VGroup></p>
<p>

This is the exact same form as the No Scroll option. However, as you can see it is partially scrolled through the form. This is because the form is embedded in the s:Scroller component.

</p>
<p><s:Scroller width="100%" height="100%"><br />
<s:VGroup width="100%" height="100%"<br />
paddingBottom="10" paddingLeft="10"<br />
paddingRight="10" paddingTop="10"><br />
<s:TextArea text="Below is a form that inside a s:Scroller component and should scroll without a problem."<br />
editable="false" borderVisible="false" width="100%"/><br />
<s:HGroup width="100%"><br />
<s:Label width="150" text="First Name"/><br />
<s:TextInput width="100%"/><br />
</s:HGroup><br />
<s:HGroup width="100%"><br />
<s:Label width="150" text="Last Name"/><br />
<s:TextInput width="100%"/><br />
</s:HGroup><br />
<s:HGroup width="100%"><br />
<s:Label width="150" text="Street Address"/><br />
<s:TextInput width="100%"/><br />
</s:HGroup><br />
<s:HGroup width="100%"><br />
<s:Label width="150" text="City"/><br />
<s:TextInput width="100%"/><br />
</s:HGroup><br />
....</p>
<p><s:HGroup width="100%"><br />
<s:Label width="150" text="Work Phone"/><br />
<s:TextInput width="100%"/><br />
</s:HGroup><br />
</s:VGroup><br />
</s:Scroller></p>
<p>

This is a simple form with a label and a s:List component. The List component has built in scrolling functionality.

</p>
<p><s:VGroup width="100%" height="100%"<br />
paddingBottom="10" paddingLeft="10"<br />
paddingRight="10" paddingTop="10"><br />
<s:TextArea text="Below is a list which are always able to scroll.  Unfortunately a list is not usable for editable forms."<br />
editable="false" borderVisible="false" width="100%"/><br />
<s:List width="100%" height="100%" dataProvider="{bindableData}" labelFunction="list_labelFunction"/><br />
</s:VGroup></p>
<p>

So that is a quick explanation of scrolling within a View for AIR Mobile.  This is all in response to a Cookbook Request.  The source code can be found here.


PHP and HTTPService Chat

So about 2 weeks ago I decided that I should look through requests in the Adobe Cookbooks and see if I can contribute.  I found a few that I may work on in the future but the first one I started with was a request for a chat program in AIR using PHP, MySQL, and HTTPService.  Really I have a pretty simple solution to this question.  I don’t know if this is exactly what the person was looking for but it works.

The short answer is to create a PHP web service that can store messages typed into the chat and return a list of chats after a specific time period.  Then setup a timer that polls the webservice every X number of minutes.

Below is the long answer with some sample code.

MySQL Database

Obviously you can store whatever you want in the database.  I chose to store very basic information including an id, username, timestamp, message, and IP address.

</p>
<p>CREATE TABLE IF NOT EXISTS `chatmessages` (<br />
`id` bigint(20) NOT NULL AUTO_INCREMENT,<br />
`username` varchar(255) NOT NULL,<br />
`received` bigint(20) NOT NULL,<br />
`message` longtext NOT NULL,<br />
`ipaddress` varchar(20) NOT NULL,<br />
PRIMARY KEY (`id`)<br />
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;</p>
<p>

PHP Webservice

I will include the complete PHP source in the final project as well but as I mentioned the webservice needs to insert a message and get a list of messages after a timestamp. Below is the SQL that I used based on the table above:

</p>
<p>$query = sprintf("INSERT INTO `chatmessages` (`username`, `received`, `message`, `ipaddress`) VALUES ('%s', %d, '%s', '%s')",<br />
mysql_real_escape_string($username),<br />
time(),<br />
mysql_real_escape_string($message),<br />
mysql_real_escape_string($_SERVER['REMOTE_ADDR'])<br />
);</p>
<p>
</p>
<p>$query = sprintf("SELECT * FROM chatmessages WHERE `received` >= %d",<br />
$timestamp<br />
);</p>
<p>

AIR Application

You will first need to setup an HTTPService to consume the PHP service.  If you are using Flex 4 you can place this in the <fx:Declarations> section of the file:

</p>
<p><fx:Declarations><br />
<s:HTTPService id="service"<br />
url="{serverUrl}"<br />
useProxy="false"<br />
method="POST"<br />
fault="service_faultHandler(event)"<br />
result="service_resultHandler(event)"/><br />
</fx:Declarations></p>
<p>

Then setup a timer that runs every 5 seconds or so.  When the timer completes you will call the webservice and download all of the messages since the last time you checked.  You also probably want to manually download the information anytime the client submits a message.

</p>
<p>private function startTimer(length:Number = 5000):void {<br />
pollTimer = new Timer(length, 1);<br />
pollTimer.addEventListener(TimerEvent.TIMER_COMPLETE, timerTick);<br />
pollTimer.start();<br />
}</p>
<p>private function timerTick(event:TimerEvent):void {<br />
getChatMessages(lastUpdated);<br />
updateTimestamp();<br />
}</p>
<p>private function getChatMessages(timestamp:Number = 0):void {<br />
service.send({method: OP_GET_CHATS, format: format, timestamp: timestamp});<br />
}</p>
<p>

To send a message you simply make a call to the web service:

</p>
<p>private function createChatMessage(message:String):void {<br />
service.send({method: OP_CREATE, format: format, username: username, message: message});<br />
}</p>
<p>

That’s it!

Conclusion

Other than handling the chat messages that are downloaded that is pretty much it.  This really is a simple solution and to be truly functional you would have to add more functionality into the application.  For example, you would want to make sure that no one else is logged in with a specific username.  You may also want to add in a table that keeps track of who is logged in and logged out.  That is slightly more difficult but essentially you would add in a logout button and then also add an event listener to detect when the app is closed.  You may also want to add in the functionality to have chat rooms.  All of these additions are simply extensions of this application.

The full source code for PHP, MySQL, and AIR are available at http://code.google.com/p/airchatexample/.

Finding a Better Solution

Polling just isn’t as desirable as you might think.  A better solution is to use RTMFP which allows you to create P2P connections.  For the short term you could create a chat application that uses the Adobe Cirrus service. There are a couple of good sample applications that use Cirrus:

I may, at some future point, do another example using Adobe Cirrus but I haven’t had time to do that yet.


What is PressAndTapGestureEvent?

So I have been looking at some of the gesture possibilities with Flex Hero and ran in to one call PressAndTapGesture.  Now I am not exactly sure what a press and tap is but it sounds like you press with one finger and tap with the other.  Or maybe it is press and hold and then release.  Well I wanted to figure it out to see if I could use it in a sample that I am working on so I built a simple example project.  Now the problem is that the emulator does not support gestures.  So I pushed it out to an Android Nexus One and am unable to get the event to fire.

So as I tweeted earlier DUMB QUESTION ALERT what is a press and tap gesture?  The description of it in the docs is this: “The PressAndTapGestureEvent class lets you handle press-and-tap gesture on touch-enabled devices. Objects that inherit properties from the InteractiveObject class capture the primary touch point (press) and a secondary point (tap) in the dispatched event object. The press-and-tap gesture is typically used to raise a context-sensitive popup menu.” To me that sounds like pressing down with one finger and tap with a second which I have tried and it does tend to bring up the default context menu which allows for copy and paste.  However, I cannot reproduce the event on the device.

I have uploaded a sample Flash Builder project.  If anyone else can figure out how to generate the Press and Tap event that would be great.  I added a button to manually dispatch the event and the event listener is working.  I apparently just don’t know how to do the right gesture.

Here is the sample Flash Builder project: http://www.day2daydevelopment.com/wp-content/uploads/2010/12/PressAndTap_Example.fxp


What object is at the top of the list?

I recently ran into a situation where I needed to determine which object was at the top of a spark list in a mobile application.  I couldn’t find any easy and obvious way to do this but digging around I eventually figured out how to do that.  Below is a demo video:

So this actually turns out to be fairly easy.  Start by creating a mobile application.  Although you could include PlayBook for the target OS its not necessary.  Once you are in the first view that is created create a spark list with some sample data:

</p>
<p><s:List id="mainList" width="100%" height="100%"><br />
<s:dataProvider><br />
<s:ArrayList><br />
<fx:String>List Item 1</fx:String><br />
<fx:String>List Item 2</fx:String><br />
<fx:String>List Item 3</fx:String><br />
<fx:String>List Item 4</fx:String><br />
<fx:String>List Item 5</fx:String><br />
<fx:String>List Item 6</fx:String><br />
<fx:String>List Item 7</fx:String><br />
<fx:String>List Item 8</fx:String><br />
<fx:String>List Item 9</fx:String><br />
<fx:String>List Item 10</fx:String><br />
<fx:String>List Item 11</fx:String><br />
<fx:String>List Item 12</fx:String><br />
<fx:String>List Item 13</fx:String><br />
<fx:String>List Item 14</fx:String><br />
<fx:String>List Item 15</fx:String><br />
<fx:String>List Item 16</fx:String><br />
<fx:String>List Item 17</fx:String><br />
<fx:String>List Item 18</fx:String><br />
<fx:String>List Item 19</fx:String><br />
<fx:String>List Item 20</fx:String><br />
<fx:String>List Item 21</fx:String><br />
<fx:String>List Item 22</fx:String><br />
<fx:String>List Item 23</fx:String><br />
<fx:String>List Item 24</fx:String><br />
<fx:String>List Item 25</fx:String><br />
</s:ArrayList><br />
</s:dataProvider><br />
</s:List></p>
<p>

Obviously this is just a dummy list and in the real world it will contain complex objects rather than strings.  You should be able to add an event listener on the list for the change event but there is a bug with that event.  As a result, you need to add an event listener on the verticalScrollBar of the list.

</p>
<p>mainList.scroller.verticalScrollBar.viewport.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, vScrollBar_PropertyChange);</p>
<p>

Because this is a property change event you have to filter the event based on its type.  Then you can get the DataGroup from the list and determine the firstIndexInView from the DataGroup.  From there you can use the list’s dataProvider to get the object or in this case the String that is at the top of the list.

</p>
<p>private function vScrollBar_PropertyChange(event:PropertyChangeEvent):void {<br />
switch (event.property) {<br />
case "verticalScrollPosition":<br />
var dg:DataGroup = mainList.dataGroup;<br />
if (dg != null) {<br />
var index:int = (dg.layout as VerticalLayout).firstIndexInView<br />
var firstObject:Object = dg.dataProvider.getItemAt(index);<br />
currentTopLabel = firstObject.toString();<br />
}<br />
break;<br />
}<br />
}</p>
<p>

That is it.  You can now determine what object is at the top of a list.  Download the source code

Now that I have written this blog post does anyone have a recommendation for a WordPress plugin that does a better job formatting code snippets?


Android Mobile PopUp

In the Day2DayDevelopment library I have included the code for PopUpMessage.mxml which is a file mean to be used for mobile development.  An example of this component is available below:

This sample app demonstrates the popup component.  The popup component has 5 variables that can be set.  The first two title and message which server fairly obvious purposes.  The last one is callback which return the label of the button that was pressed.

The two variables that need explanation are the buttonLeftLabel and buttonRightLabel variables.  The primary reason these buttons need explanation is because that is how the component differentiates between a two-button label and a one-button label.  If the buttonRightLabel is null then the component assumes it should be a one-button label.

As soon as I test the app on an Android phone I will upload the apk file.  The code can be downloaded on my Google Code page.


Pages:12