<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0"  xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
	<title>AsFusion</title>
	<link>https://www.asfusion.com/</link>
	<description>Application development for phones, tablets, and desktops.</description>
	<generator>Mango 2.1</generator>
	<atom:link href="https://www.asfusion.com/blog/index.rss" rel="self" type="application/rss+xml" />
	
		
      <item>
         <title>Design first, and the process behind </title>
         <description><p>Why is it important to dedicate enough time to design your app? let me show you how we did it for <a title="Conqu" href="http://conqu.com/">Conqu</a>, what worked, and what didn't work.</p>
<h4>Team size and roles</h4>
<p>I love small teams. Everybody is so much productive when the team is small. Before this project, I was in a much larger project and the change was like night and day. With a small team, where is no waste of time in long meetings, or trying to decide if feature A is better than feature B, or trying to explain to other people -that are not completely involved- what it is best or fits better in the project.</p>
<p>Being small is bliss, turn-arounds are quick, and in a very agile environment everybody knows what to do and we can move faster. Another thing is that you need a team that has balanced skills in UX and design, which are as important as development skills. We have three team members and each of us plays different roles.</p>
<p><strong>Mark:</strong> The designer and artist. He is in charge of doing everything related to colors and pixels. In addition, he is doing some wireframe prototyping and helping us with the video, text copy and html code.</p>
<p><strong>Laura:</strong> The server side development and the magic behind the ui. She is in charge of doing all ColdFusion and server side code. But because ColdFusion is so fast to write, she helps the Flex development, in special all the SQLite interaction. She also plays the role of product owner with myself.</p>
<p><strong>Myself:</strong> The Flex guy. I'm in charge of doing most of the custom components on Flex and make sure that the app is optimized for mobile.</p>
<h4>Tools</h4>
<p>We use an internal tool, similar to Basecamp to post all the TODO's, messages and all the design files that we share with the team. Skype and IM for communication and a webdav disk for sharing assets, minimum amount of email (we prefer to have those conversations in the internal tool) and Acrobat.com for sharing documents. And last but not least, Adobe tools for development and design.</p>
<h4>Time line</h4>
<p>The following is a time line until today. The project is still going on, so maybe I will do another post in the future to show the progress.</p>
<p><img src="/assets/content/images/design_first/timeline.jpg" alt="Timeline" width="600" height="308"></p>
<h4>Beginning &amp; Exploration (High detailed design vs wireframe prototype)</h4>
<p><strong>First month - Nov 1</strong></p>
<p>At this stage, only Mark worked in the project full time. In the first week, we shared ideas and made sure Mark understood what we had in mind, and what the idea behind the product was. We started with the tablet version mostly because we were exited about all the tablets (Playbook and Android) that were announced, and we didn't want to miss the boat again (we missed it for iPhone and iPad). But the true is that we are geeks and we love gadgets, so what better excuse to have a project where we would be using the latest and greatest gadget. Now that I'm looking back, maybe we should have done the Desktop version and then move to the tablets because there are many more people with desktops than tablets at this moment (I think that will soon change).</p>
<p>Once Mark understood what we wanted, he started working and by the end of the first week, he has his first mockup.</p>
<p><a href="/assets/content/images/design_first/flow_01.jpg" rel="lightbox"><img src="/assets/content/images/design_first/flow_01_small.jpg" alt="First design" width="600" height="352"></a></p>
<p>As you see in this design, he spent a good time in the details. He skipped the wireframe prototype and showed us a much more polished design. That is what we usually do for our clients to make them more excited and it usually works. But this time, we were the clients so we thought that maybe we didn't need that, but we were wrong. Having a more detailed design helped us visualize the final product much better, and I can tell you that one of the best experiences was when we loaded that image in a tablet for the first time. We were like children with a new toy, that image has imprinted the feeling of the experience of the app. If we had just a black and white wireframe the feeling would have been totally different.</p>
<p>He later did some wireframes for other parts of the application, but that process didn't last long as we learnt quickly that having a more detail design triggered more feedback in our brain. That contradicts with some of our processes that we do for clients. We usually spend a lot of time creating great Omnigraffle documents, but for this project, we had 90% of the ideas as detailed as final.</p>
<p>Keep in mind that that worked fine in this project but if you have a bigger team you should think about it. For bigger teams, specially when everybody wants to be the chef in the kitchen it's better to go with more iterations of wireframes until they have an agreement and then move to pixel detail. In addition, working on wireframes for the most part lets the client know that there is no actual work. Sometimes clients would see a prototype and think that we are almost done, and that is far from true.</p>
<p>It wasn't the case for us because the three of us have a good eye for design and UX and we can visualize quickly. We can do the wireframes over the phone in our heads and go directly to a detailed mockup. The other thing is that all of us in the team are picky, we want pixel-perfect design - all the time. Sometimes we would even agree on a wireframe, but once we had it in Photoshop (pixel-perfect), we would make a lot of adjustments. Don't get me wrong, wireframes are good but you need to do them quickly and move on because later you will change them anyway, just don't spend too much on them. That's why we ended up doing more and more final mockups and less wireframes.</p>
<p>The three weeks that followed were an exploration of design, where we played with different ideas until we nailed down what we wanted. Laura and I where playing the role of product owners and Mark was cranking all the designs and the only one really working.</p>
<p>Some of the ideas are shown in the following screen shoots, you can click to expand to full size.</p>
<p><a href="/assets/content/images/design_first/dark.png" rel="lightbox"><img src="/assets/content/images/design_first/dark_small.jpg" alt="Dark theme" width="600" height="352"></a></p>
<p><a href="/assets/content/images/design_first/green.jpg" rel="lightbox"><img src="/assets/content/images/design_first/green_small.jpg" alt="Green theme" width="600" height="352"></a></p>
<p><a href="/assets/content/images/design_first/wooden.jpg" rel="lightbox"><img src="/assets/content/images/design_first/wooden_small.jpg" alt="Wood theme" width="600" height="352"></a></p>
<p><a href="/assets/content/images/design_first/gray_dark.jpg" rel="lightbox"><img src="/assets/content/images/design_first/gray_dark_small.jpg" alt="Gray dark" width="600" height="352"></a></p>
<p><a href="/assets/content/images/design_first/gray_light.jpg" rel="lightbox"><img src="/assets/content/images/design_first/gray_light_small.jpg" alt="Gray light" width="600" height="352"></a></p>
<p><a href="/assets/content/images/design_first/edit.jpg" rel="lightbox"><img src="/assets/content/images/design_first/edit_small.jpg" alt="Edit" width="600" height="352"></a></p>
<p>From all those ideas (we have more, but I made a selection for this post) we picked what we thought worked best from each and made a final version. Mark was expecting us to choose the final one and move on. But we, the product owners, were having a hard time making the final selection, each of us were attached to different images. For example, Mark liked the black one but Laura didn't and they both liked the wood version but I didn't. We knew that we needed to get to one that all of us liked and also made sure that we had all the items in place before deciding on the final version. We knew that once we had a final version, we couldn't go back and made big changes because it would affect development badly. After a few more rounds of tweaking we got our final design. <a title="everything-you-know-about-design-is-wrong" href="/blog/entry/everything-you-know-about-design-is-wrong">You can read more about how we chose the final design in this post</a>.</p>
<p><a href="/assets/content/images/design_first/final.png" rel="lightbox"><img src="/assets/content/images/design_first/final_small.jpg" alt="Final Design" width="600" height="352"></a></p>
<h4>Development starts and design expands to other areas</h4>
<p><strong>Second Month Dec 1</strong></p>
<p>Once we were done with the design exploration, we started development. It was important that at this time we were very happy with the design that we had and we were not thinking about doing major changes in the design nor UX. Laura started working on the first screen but just part time for that month, while Mark continued working full time on the edit screen and the rest of the app. Having Mark shaping other parts of the app, helped us visualizing how the whole app would function. We then started to think about transitions and how all the different pieces would be glued together.</p>
<h4>Development now in full speed</h4>
<p><strong>Third Month Jan 1</strong></p>
<p>After a relaxing december, we started January at full speed, Laura and I were working on development while Mark was working on final screens of the tablet version. He finished the first iteration of the tablet version on Jan 20th. We later asked him to tweak things here and there but not big changes, mostly usability changes that we started noticing when we were using the app in a real device. We also asked him to add a settings screen that was not in the original design. Other than that, all the major things where done.</p>
<p>Working with all the screens ready was a pleasure. It meant non stop development not only because they were final, but also because we had all the assets ready on our webdav disk, with a picture per screen with the dimensions, fonts, drop shadow, etc that looked like this:</p>
<p><a href="/assets/content/images/design_first/dimensions.jpg" rel="lightbox"><img src="/assets/content/images/design_first/dimensions_small.jpg" alt="Dimensions" width="600" height="352"></a></p>
<p>And this is how the vertical version looks</p>
<p><a href="/assets/content/images/design_first/vertical.jpg" rel="lightbox"><img src="/assets/content/images/design_first/vertical_small.jpg" alt="Vertical version" width="300" height="512"></a></p>
<h4>Continue development for tablet, design for phone and desktop were starting to take shape</h4>
<p><strong>Fourth Month Feb 1</strong></p>
<p>Laura and I were working on the tablet and from time to time requesting small changes to Mark. Meanwhile, he started the phone version and he managed to do that plus the desktop version and the website. At this point he was multitasking with all the different things that we needed: the website for the launch, a logo, banners, tweaks on the tablet version plus the phone and desktop version. Having Mark available full time working on all this helped us move forward quickly because we always had a designer available for anything such as assets, usability issues fixes, testing and preparing the next round of development for desktop and phone.</p>
<p><a href="/assets/content/images/design_first/desktop.jpg" rel="lightbox"><img src="/assets/content/images/design_first/desktop_small.jpg" alt="Desktop version" width="600" height="373"></a></p>
<p><img src="/assets/content/images/design_first/phone.jpg" alt="Phone version" width="318" height="478"></p>
<h4>Android and Playbook launch</h4>
<p><strong>Fifth Month Mar 1</strong></p>
<p>We did a first launch with a Playbook version, but it was not ready for prime time. We knew it but we did it because nobody could use it anyway since the Playbook was not available at that moment. People were saying that RIM was taking a lot of time to approve the apps and we wanted to make sure that we had something on the Blackberry market as soon as possible.</p>
<p>Later on March 23rd, we launched the Android version for everybody to use. That was our first real milestone. A week later we updated the build for the playbook. So the whole month we worked on making an stable build with all the features that we wanted. Laura and Mark worked on submitting the apps to the different markets and preparing the images, logos, etc for each while Mark was also supporting us in the development.</p>
<p><a title="Android Market" href="https://market.android.com/details?id=air.com.conqu"><img src="/assets/content/images/design_first/android_small.jpg" alt="Android Market" width="400" height="170"></a></p>
<p><a title="App World" href="http://appworld.blackberry.com/webstore/content/31138"><img src="/assets/content/images/design_first/blackberry_small.jpg" alt="App world" width="402" height="279"></a></p>
<h4>Synchronization and Desktop version</h4>
<p><strong>Sixth Month April 1</strong></p>
<p>April is not done yet as I'm writing this post, but most of the moth was spent in the synchronization and task sharing. Laura is taking care of all the ColdFusion code while I'm doing the ui. I'm done with my part and about to start the desktop version, will see how that works.</p>
<h3>Interesting facts by numbers</h3>
<h4>Hours spent on the project</h4>
<p>We spend 1898 hours total until today and we are still going. From that, 49% went to design. That is huge for design if you compare to other projects. Sometimes projects don't even have 5% of the total amount. The thing is that if you want to have a nice interface with good UX, you need to realize that design also takes times. Multiple iterations of design is what makes an app truly shine. Maybe 49% is too much and by the end it will be less because design started first and will finish earlier. We already have a lot of things designed that we haven't event started to develop. But I think that a 20% for design is a good number.</p>
<p><img src="/assets/content/images/design_first/hours.png" alt="" width="400" height="288"></p>
<h4>Design breakdown</h4>
<p>We spend 49% of the hours in design, but what does it mean? where did we spend it the most? The following chart is not the hours on design, it is the actual number of files that we created. Some of them took longer to create than others and therefore this chart is not completely accurate, but it gives you a good idea on how much we spent on each part.</p>
<p><img src="/assets/content/images/design_first/design.png" alt="Design" width="400" height="320"></p>
<p>The most time was spent in the tablet because that's what we built first and it is at this moment 100% done. We expect to spend more time on other areas like desktop and phone but not as much as the tablet because we are reusing a lot of ideas.</p>
<h4>Pixel perfect vs Wireframe</h4>
<p>This is interesting: we spent very little in wireframe for this project, only 7%, of the design time. I mentioned before that we had our reasons and I feel that we made the right choice.</p>
<p><img src="/assets/content/images/design_first/pixel_wireframe.png" alt="Pixel vs wireframe" width="400" height="288"></p>
<h4>Sever side vs front end vs design</h4>
<p>The server side is really nothing: only 5% of the whole project, and we are estimating that it will remain at the same ratio. We think that we'll need to spend more on the server side when we'll need to scale to more than one server, but for now we are not worrying too much. Flex, on the other hand, is taking much longer.</p>
<p><img src="/assets/content/images/design_first/dev_design.png" alt="Dev vs design" width="400" height="288"></p>
<p>In this following chart we compare only development, between server side and UI development and the ratio is 10% vs 90%.</p>
<p><img src="/assets/content/images/design_first/server_ui.png" alt="Server vs UI" width="400" height="288"></p>
<h4>Flex break down</h4>
<p>I did not talk much about Flex in this post, but let me tell you that we were very picky here as we were with the design. We built a lot of custom components. Here is the break down on Flex built-in components that we used and custom components that we built.</p>
<p><img src="/assets/content/images/design_first/flex_custom.png" alt="Flex vs custom components" width="400" height="288"></p>
<h4>Conclusion</h4>
<p>We had the idea for Conqu for long time. We even started it 3 years ago but we didn't give it the attention that it deserved. This time we approached it differently. We gave it full attention and a team of 3 people, with the same importance as any other client. This is not a project that we are doing between late nights and weekends, this is a full time project, and I feel that we did it right this time. <a href="http://corlan.org/2011/03/25/conqu-one-of-the-coolest-android-apps-outhere/">A few other people</a> also think the <a href="http://www.willw.net/conqu-blackberry-playbook-task-manager-app/">same</a>.</p>
<blockquote>I love this app! I've been searching for a simple, yet robust project/task management system and am so thankful to have found Conqu! It works great with BB PlayBook. You don't have to be well-versed in GTD to use it. I recommend checking out the website to see the new features coming soon (synchronization...YAY!). I highly recommend this awesome app!</blockquote>
<p>The best part is that it is cool to work on our own ideas, not on client work. We can manage our time better, spending time were we feel that needs more work and moving quickly when we know what we want.</p>
<p>If you are thinking to start a new project I suggest that you do it, but don't do it half way, because your project will die in the middle. I also think it is better to delegate things that you are not capable of doing. For example, if you are a developer, try to hire a designer to help you. If you don't have the extra money, try to get a partner. If you need help with the server, you should hire someone to do that too. Of course you can do everything, but the quality of your product will be affected. Some are lucky and are both designer and devevelopers (devsigner), but they need more time to complete the whole thing so there is always a drawback.</p>
<p>And if you took the time to read it all please write a comment telling us what works for you. I'd love to know what things are working for others.</p>
<p><a class="button" href="http://twitter.com/nahuel_en"><span class="twitter">Follow me on twitter</span></a></p></description>
         <link>https://www.asfusion.com/blog/entry/design-first-and-the-process-behind</link>
         <guid>https://www.asfusion.com/blog/entry/design-first-and-the-process-behind</guid>
         <category>Conqu</category><category>Mobile</category>
         <pubDate>Thu, 26 Apr 2012 10:00:00 GMT</pubDate>
      </item>	
      <item>
         <title>OnePound Weight Tracking App</title>
         <description><p><a href="/projects/onepound/"><img src="/assets/content/projects/onepound/OnePound-640x200.png" alt="" width="640" height="200" /></a></p>
<p>It's possible that AsFusion was bitten by the app bug. Soon after releasing Conqu, we decided to create another app called <a href="/projects/onepound/">OnePound</a>. This app was smaller and less ambitious than Conqu so we were able to complete it in just a few weeks time.</p>
<p>OnePound is a weight tracking app for <a href="https://market.android.com/details?id=air.com.onepoundapp&amp;hl=en">Android</a> tablets, <a href="http://appworld.blackberry.com/webstore/content/67265?lang=en">BlackBerry PlayBook</a>, and the <a href="http://www.barnesandnoble.com/w/onepound-asfusion/1107828941?ean=2940043868107">Nook</a>. We decided to target these platforms specifically because we felt a decent app was not available in those markets.</p>
<p>When we set out to create OnePound, we wanted a design that was aesthetically pleasing to both men and woman, and easy to use. We didn't want to force a user to switch between data entry screens and graph screens. We didn't want users to have to change the orientation of their device to see different screens. As those types of interactions--although neat at first--get rather tiresome once you start using the app. Instead, we created OnePound to use a single screen where you can add new weights and see the chart updated instantly.</p>
<p>OnePound includes the most requested features for weight tracking apps: features like the ability to set a goal and track your progress along the way. It also calculates your BMI based on your height and weight automatically. You can also choose between US or metric units of measurement.</p>
<p>We are very excited about releasing another beautiful application into the market and look forward making more great apps just like OnePound.</p>
<p> </p></description>
         <link>https://www.asfusion.com/blog/entry/onepound-weight-tracking-app</link>
         <guid>https://www.asfusion.com/blog/entry/onepound-weight-tracking-app</guid>
         <category>Flex</category><category>Mobile</category>
         <pubDate>Fri, 27 Jan 2012 13:17:39 GMT</pubDate>
      </item>	
      <item>
         <title>Switcher mobile skin for a toggle button</title>
         <description><p>One of the components that is very common in a mobile app is the Switcher component. The on/off switch is usually available on IOS and Android devices.  This component is like a toggle button but with a skin that makes it look as a Switcher.</p>
<p><img src="/assets/content/images/switcher.png" alt="Switcher" width="129" height="64" /></p>
<h4>Application</h4>
<p>This is just a simple test and we have all the styles hardcoded on it.</p>
<code>
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark">
	<fx:Style>
		@namespace s "library://ns.adobe.com/flex/spark";
		s|ToggleButton
		{
			skin-class: ClassReference("skins.SwitcherSkin");
			background: Embed(source='/images/switcher_bg.png');
			thumb: Embed(source='/images/switcher_thumb.png'); 
		}
	</fx:Style>
	<s:ToggleButton  x="50" y="50" width="94" height="27"/>
</s:Application>
</code>
<p>I have a special skin, <strong>SwitcherSkin</strong>,  for the toggle button that transforms the normal toggle to a switcher.</p>
<h4>Skin</h4>
<p>We are extending from MobileSkin to make our skin lightweight for a mobile project. And we only have 2 elements on it: the background that has the on/off background and the thumb that moves to cover the on/off labels.</p>
<code>
package skins
{
	import caurina.transitions.Tweener;
	import flash.display.DisplayObject;
	import spark.skins.mobile.supportClasses.MobileSkin;
	public class SwitcherSkin extends MobileSkin
	{
		protected var background:DisplayObject;
		protected var thumb:DisplayObject;
		override protected function commitCurrentState():void
		{ 
			super.commitCurrentState();
			invalidateDisplayList();
		}
		override protected function createChildren():void
		{
			background = addElement( "background" );
			thumb = addElement( "thumb" );
		}
		protected function addElement( style:String ):DisplayObject
		{
			var elementAsset:Class = getStyle( style );
			var element:DisplayObject;
			if( elementAsset )
			{
				element = new elementAsset();
				addChild( element );
			}
			return element;
		}
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			if( currentState == "up" )
			{
				Tweener.removeTweens( thumb );
				Tweener.addTween( thumb, { time:0.4, x:0 } );
			}
			if( currentState == "upAndSelected" )
			{
				Tweener.removeTweens( thumb );
				Tweener.addTween( thumb, { time:0.4, x:unscaledWidth - thumb.width } );
			}
		}
	}
}
</code>
<p>To make it more interesting, I added a little tween using the Tweener library . I hope you like it. You can improve on it making the labels dynamic and the dimensions too.</p>
<p><a class="button" href="/assets/content//tutorialFiles/switcher.zip"><span class="download">The source is available for download.</span></a></p>
<p><a class="button" href="http://twitter.com/nahuel_en"><span class="twitter">Follow me on twitter</span></a></p>
</description>
         <link>https://www.asfusion.com/blog/entry/switcher-mobile-skin-for-a-toggle-button</link>
         <guid>https://www.asfusion.com/blog/entry/switcher-mobile-skin-for-a-toggle-button</guid>
         <category>Flex</category><category>Flex Components</category><category>Mobile</category>
         <pubDate>Wed, 18 May 2011 13:50:19 GMT</pubDate>
      </item>	
      <item>
         <title>Mobile ItemRenderer in ActionScript (Part 5)</title>
         <description><p>This is part 5 of my series on item renderers.  As you may know, the Mobile Flex Framework does not have a DataGrid, mostly because a DataGrid control uses a lot of real state and the phone has a small screen. But, we have tablets too and a Grid makes complete sense. However, the regular flex DataGrid will not work as it is too heavy for that. We also want gestures and bouncing like the mobile List has. So the workaround is to make an ItemRenderer that mimics a grid.</p>
<p><img src="/assets/content/images/renderers/tweet_grid_renderer.png" alt="Grid Renderer" width="482" height="350" /></p>
<p>For this example I'm reusing the code of the Application from the  previous Twitter example so I will not explain that. Also I'm reusing some of the pieces from the TweetRenderer but changing the layout a lot.</p>
<p>For reference, these are the previous posts: <a title="Part 1" href="/blog/entry/mobile-itemrenderer-in-actionscript-part-1">part 1</a>, <a title="Part 2" href="/blog/entry/mobile-itemrenderer-in-actionscript-part-2">part 2</a>, <a title="Part 3" href="/blog/entry/mobile-itemrenderer-in-actionscript-part-3">part 3</a> and <a title="Part 4" href="/blog/entry/mobile-itemrenderer-in-actionscript-part-4">part 4</a>.</p>
<h4>Styles</h4>
<p>The main difference from the previous example is that I don't have individual styles for each TextField. Instead, all the fields use the same one.
The new thing that I added is the vertical-grid-line-color property used to paint the vertical lines.
renderers|TweetGridRenderer</p>
<code>
renderers|TweetGridRenderer
{
	padding-left: 15;
	padding-right: 15;
	gap: 20;
	
	min-height: 50;
	vertical-grid-line-color:#aaaaaa;
	font-size: 15;
	color: #555555;
	font-family: _sans;
	separator: Embed(source='/styles/images/separator.png' );
	
	background: Embed(source='/styles/images/background_up.png', 
		scaleGridLeft=10, scaleGridTop=20, scaleGridRight=11, scaleGridBottom=21 );
}

renderers|TweetGridRenderer:selected
{
	background: Embed(source='/styles/images/background_down.png',
		scaleGridLeft=50, scaleGridTop=20, scaleGridRight=51, scaleGridBottom=21 );
}
</code>
<h4>TweetGridRenderer</h4>
<p>This class has some similar elements  to the TweetRenderer. The main differences are:</p>
<ul>
<li>I added a lineCanvas display object used to paint the vertical lines.</li>
<li>I use fix height instead of variable height. The height is set by reading the value from the CSS.</li>
<li>I use the same styles for all the fields. Note that we do that when we call TextUtil.createSimpleTextField and pass <strong>"this"</strong>.</li>
<li>I changed the layout off all the fields and removed the avatar image.</li>
</ul>
<code>
package renderers
{
	import flash.display.DisplayObject;
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.text.TextField;
	import utils.TextUtil;
	public class TweetGridRenderer extends BaseRenderer
	{
		protected var userField:TextField;
		protected var nameField:TextField;
		protected var contentField:TextField;
		protected var background:DisplayObject;
		protected var backgroundClass:Class;
		protected var separator:DisplayObject;
		protected var lineCanvas:Shape;
		protected var columnWidth:int
		protected var paddingLeft:int;
		protected var paddingRight:int;
		protected var paddingBottom:int;
		protected var paddingTop:int;
		protected var gap:int;
		
		//  Contructor
		public function TweetGridRenderer()
		{
			percentWidth = 100;
		}
		
		//  Override Protected Methods
		override protected function createChildren():void
		{
			readStyles();
			setBackground();
			var separatorAsset:Class = getStyle( "separator" );
			if( separatorAsset )
			{
				separator = new separatorAsset();
				addChild( separator );
			}
			userField  = TextUtil.createSimpleTextField( this );
			addChild( userField );
			nameField  = TextUtil.createSimpleTextField( this )
			addChild( nameField );
			contentField  = TextUtil.createSimpleTextField( this );
			addChild( contentField );
			lineCanvas = new Shape();
			addChild( lineCanvas );
			// if the data is not null, set the text
			if( data )
				setValues();
		}
		override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
		{
			var oldColumnWidth:int = columnWidth;
			columnWidth = Math.floor( unscaledWidth / 3 );
			if( columnWidth != oldColumnWidth )
				setValues();
			var textWidth:int = columnWidth - paddingLeft - paddingRight;
			background.width = unscaledWidth;
			background.height = unscaledHeight;
			var textY:int = ( unscaledHeight - userField.textHeight ) / 2;
			userField.x = paddingLeft;
			userField.y = textY;
			TextUtil.adjustTextSize( userField, textWidth );
			nameField.x = columnWidth + paddingLeft;
			nameField.y = textY;
			TextUtil.adjustTextSize( nameField, textWidth );
			contentField.x = columnWidth * 2 + paddingLeft;
			contentField.y = textY;
			TextUtil.adjustTextSize( contentField, textWidth );
			separator.width = unscaledWidth;
			separator.y = layoutHeight - separator.height;
			var g:Graphics = lineCanvas.graphics;
			g.clear();
			g.lineStyle( 1, getStyle( "verticalGridLineColor" ) );
			g.moveTo( columnWidth, 0 );
			g.lineTo( columnWidth, unscaledHeight );
			g.moveTo( columnWidth * 2, 0 );
			g.lineTo( columnWidth * 2, unscaledHeight );
		}
		override protected function measure():void
		{
			measuredHeight = getStyle( "minHeight" );
		}
		protected function setBackground():void
		{
			var backgroundAsset:Class = getStyle( "background" );
			if( backgroundAsset && backgroundClass != backgroundAsset )
			{
				if( background && contains( background ) )
					removeChild( background );	
				backgroundClass = backgroundAsset;
				background = new backgroundAsset();
				addChildAt( background, 0 );
				if( layoutHeight && layoutWidth )
				{
					background.width = layoutWidth;
					background.height = layoutHeight;
				}
			}
		}
		override protected function setValues():void
		{
			var arr:Array = String( data.author.name ).split("(");
			var user:String = String( data.author.name )
			userField.text = arr[0];
			nameField.text =  String( arr[ 1 ] ).replace( ")", "" );
			contentField.htmlText = data.content.value;
		}
		override protected function updateSkin():void
		{
			currentCSSState = ( selected ) ? "selected" : "up";
			setBackground();
		}
		protected function readStyles():void
		{
			paddingLeft = getStyle( "paddingLeft" );
			paddingRight = getStyle( "paddingRight" );
			gap = getStyle( "gap" );
		}
	}
}
</code>
<p>As you can see this renderer is very similar to the one on our previous example. By making just some adjustments we have a completely new layout. Hope you enjoyed this series on item Renderers.<p>
<p><a class="button" href="/assets/content//tutorialFiles/renderers/renderers_5.zip"><span class="download">The source is available for download.</span></a></p>
<p><a class="button" href="http://twitter.com/nahuel_en"><span class="twitter">Follow me on twitter</span></a></p></description>
         <link>https://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-5</link>
         <guid>https://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-5</guid>
         <category>Flex</category><category>Mobile</category>
         <pubDate>Wed, 18 May 2011 10:05:36 GMT</pubDate>
      </item>	
      <item>
         <title>Mobile ItemRenderer in ActionScript (Part 4)</title>
         <description><p>This is part 4 of my series on item renderers. This time we have a more real example that includes two states (selected and up) plus and avatar image and a bunch of text fields.</p>
<p>What I choose as the example is a TweetRenderer that shows the picture of the user, the user name and the content of the tweet.</p>
<p>For reference these are the previous posts: <a title="Part 1" href="http://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-1">part 1</a>, <a title="Part 2" href="http://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-2">part 2</a>, and <a title="Part 3" href="http://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-3">part 3</a>.</p>
<p><img src="/assets/content/images/renderers/tweet_renderer.png" alt="" width="460" height="242" /></p>
<p>To simplify the code, I call the twitter service with a hardcoded value "Adobe" to receive all the tweets that include that word. As you may notice, I'm not following the best practices with services and added them in the Application file.</p>
<code>
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
				xmlns:s="library://ns.adobe.com/flex/spark" 
				creationComplete="creationCompleteHandler()">
	
	<fx:Style source="styles/Main.css"/>
	
	<fx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;
			import mx.events.FlexEvent;
			[Bindable]
			private var ac:ArrayCollection = new ArrayCollection();
			private var searchURL:String = "http://search.twitter.com/search.atom?q=";
			protected function creationCompleteHandler():void
			{
				httpService.url = searchURL + "Adobe";
				httpService.send();
			}
		]]>
	</fx:Script>
	<fx:Declarations>
		<s:HTTPService  id="httpService" 
						result="ac = event.result.feed.entry as ArrayCollection" />
	</fx:Declarations>
	<s:List width="100%" height="100%"
			dataProvider="{ac}" 
			itemRenderer="renderers.TweetRenderer"/>
</s:Application>
</code>
<h4>Styles</h4>
<p>Now that we have more elements, our styles are growing a little bit.<br/>
We do not longer have the background-color property, because we are using images to paint the background instead. We have 2 images, one for the selected state and another for the rest (in this case we have only one, the up state). We use the pseudo selectors to target the different states but in both cases the name of the property is "background".</p>
<p>Other thing  that we have now is individual style classes for the different text fields of the renderer. We have one for the name, one for the username and another for the content.</p>
<code>
renderers|TweetRenderer
{
	padding-top: 15;
	padding-left: 10;
	padding-right: 10;
	padding-bottom: 15;
	horizontal-gap: 10;
	vertical-gap: 10;
	
	name-style: nameRendererStyle;
	user-style: userRendererStyle;
	content-style: contentRendererStyle;
	separator: Embed(source='/styles/images/separator.png' );
	
	background: Embed(source='/styles/images/background_up.png', 
		scaleGridLeft=10, scaleGridTop=20, scaleGridRight=11, scaleGridBottom=21 );
}

renderers|TweetRenderer:selected
{
	background: Embed(source='/styles/images/background_down.png',
		scaleGridLeft=50, scaleGridTop=20, scaleGridRight=51, scaleGridBottom=21 );
}
.userRendererStyle
{
	font-size: 20;
	color: #222222;
	font-family: _sans;
	font-weight: bold;
}
.nameRendererStyle
{
	font-size: 14;
	color: #999999;
	font-family: _sans;
}
.contentRendererStyle
{
	font-size: 15;
	color: #555555;
	font-family: _sans;
}
</code>
<h4>Renderer</h4>
<p>Because we want change the background when the user clicks in the item we need to implement the interface IItemRenderer, that allow the List to notify the renderers every time the selection changes.  The help us with that task we create another class, the BaseRenderer that takes cares of the implementation of that interface and the TweetRenderer extends from it.</p>
<code>
package renderers
{
	import core.StyleClient;
	import spark.components.IItemRenderer;
	public class BaseRenderer extends StyleClient implements IItemRenderer
	{
		//  Public Setters and Getters
		
		protected var _data:Object;
		public function set data( value:Object ):void
		{
			if( _data == value )
				return;
			
			_data = value;
			// if the elements has been created we set the values
			if( creationComplete )
				setValues();
		}
		public function get data( ):Object
		{
			return _data;
		}
		// selected-------------------------------------------------------------  
		protected var _selected:Boolean = false;
		public function get selected():Boolean
		{
			return _selected;
		}
		public function set selected(value:Boolean):void
		{
			if (value != _selected)
			{
				_selected = value;
				updateSkin();
			}
		}
		// dragging------------------------------------------------------------
		/** Property not used but it is required by the interface IItemRenderer  */
		protected var _dragging:Boolean;
		public function set dragging( value:Boolean ):void
		{
			_dragging = value;
		}
		public function get dragging():Boolean
		{
			return _dragging;
		}
		// showsCaret-------------------------------------------------------------
		/** Property not used but it is required by the interface IItemRenderer  */
		protected var _showsCaret:Boolean;
		public function set showsCaret( value:Boolean ):void
		{
			_showsCaret = value;
		}
		public function get showsCaret():Boolean
		{
			return _showsCaret;
		}
		// itemIndex--------------------------------------------------------------
		protected var _itemIndex:int;
		public function set itemIndex( value:int ):void
		{
			_itemIndex = value;
		}
		public function get itemIndex():int
		{
			return _itemIndex;
		}
		// itemIndex--------------------------------------------------------------
		protected var _label:String;
		public function get label():String
		{
			return _label;
		}
		public function set label(value:String):void
		{
			_label = value;
		}
		// --------------------------------------------------------------
		protected function updateSkin():void
		{
			// To be implemented in children
		}
		protected function setValues():void
		{
			// To be implemented in children
		}
	}
}
</code>
<p>I added 2 methods to this base class: <strong>setValues</strong> which is called every time that the data changes and <strong>updateSkin</strong> which is called every time that the selection changes. </p>
<p>In the method updateSkin that is implemented in the <strong>TweetRenderer</strong> we change the state of the skin. Changing the state gives us new values for our call to the getStyle method. For example, when we change to the "selected" state and we call getStyle( "background" ) we get the image that is defined inside the pseudo selector TweetRenderer:selected. When we are in the "up" state, we get the default value for the background property. All this CSS functionally is provided by extending StyleClient.</p>
<p>You can see that in the following code</p>
<code>
package renderers
{
	import flash.display.DisplayObject;
	import flash.text.TextField;
	import spark.primitives.BitmapImage;
	import spark.primitives.Graphic;
	import utils.TextUtil;
	public class TweetRenderer extends BaseRenderer
	{
		//  Protected properties		
		protected var userField:TextField;
		protected var nameField:TextField;
		protected var contentField:TextField;
		protected var avatar:BitmapImage;
		protected var avatarHolder:Graphic;
		protected var background:DisplayObject;
		protected var backgroundClass:Class;
		protected var separator:DisplayObject;
		protected var paddingLeft:int;
		protected var paddingRight:int;
		protected var paddingBottom:int;
		protected var paddingTop:int;
		protected var horizontalGap:int;
		protected var verticalGap:int;

		//  Contructor	
		public function TweetRenderer()
		{
			percentWidth = 100;
		}
		
		//  Override Protected Methods
		override protected function createChildren():void
		{
			readStyles();
			setBackground();
			var separatorAsset:Class = getStyle( "separator" );
			if( separatorAsset )
			{
				separator = new separatorAsset();
				addChild( separator );
			}
			userField  = TextUtil.createSimpleTextField( getStyle( "userStyle" ) );
			addChild( userField );
			nameField  = TextUtil.createSimpleTextField( getStyle( "nameStyle" ) )
			addChild( nameField );
			contentField  = TextUtil.createSimpleTextField( getStyle( "contentStyle" ) , false, "none" );
			contentField.wordWrap = true;
			contentField.multiline = true;
			addChild( contentField );
			avatarHolder = new Graphic();
			avatar = new BitmapImage();
			avatar.fillMode = "clip";
			avatarHolder.width = 48;
			avatarHolder.height = 48;
			avatarHolder.addElement( avatar );
			addChild( avatarHolder );
			// if the data is not null, set the text
			if( data )
				setValues();
		}
		
		protected function setBackground():void
		{
			var backgroundAsset:Class = getStyle( "background" );
			if( backgroundAsset && backgroundClass != backgroundAsset )
			{
				if( background && contains( background ) )
					removeChild( background );
				
				backgroundClass = backgroundAsset;
				background = new backgroundAsset();
				addChildAt( background, 0 );
				if( layoutHeight && layoutWidth )
				{
					background.width = layoutWidth;
					background.height = layoutHeight;
				}
			}
		}

		override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
		{
			avatarHolder.x = paddingLeft;
			avatarHolder.y = paddingTop;
			avatarHolder.setLayoutBoundsSize( avatarHolder.getPreferredBoundsWidth(), avatarHolder.getPreferredBoundsHeight() );		
			userField.x = avatarHolder.x + avatarHolder.width + horizontalGap;
			userField.y = paddingTop;
			nameField.x = userField.x + userField.textWidth + horizontalGap;
			nameField.y = paddingTop + ( userField.textHeight - nameField.textHeight ) / 2;
			contentField.x = avatarHolder.x + avatarHolder.width + horizontalGap;
			contentField.y = paddingTop + userField.textHeight + verticalGap;
			contentField.width = unscaledWidth - paddingLeft - paddingRight - avatarHolder.getLayoutBoundsWidth() - horizontalGap;
			layoutHeight = Math.max( contentField.y + paddingBottom + contentField.textHeight, avatarHolder.height + paddingBottom + paddingTop );
			background.width = unscaledWidth;
			background.height = layoutHeight;
			separator.width = unscaledWidth;
			separator.y = layoutHeight - separator.height;
		}
		
		override public function getLayoutBoundsHeight(postLayoutTransform:Boolean=true):Number
		{
			return layoutHeight;
		}
		override protected function setValues():void
		{
			var arr:Array = String( data.author.name ).split("(");
			var user:String = String( data.author.name )
			userField.text = arr[0];
			nameField.text =  String( arr[ 1 ] ).replace( ")", "" );
			contentField.htmlText = data.content.value;
			if( data.link.length > 1)
				avatar.source = data.link[ 1 ].href;
		}
		
		override protected function updateSkin():void
		{
			currentCSSState = ( selected ) ? "selected" : "up";
			setBackground();
		}
		
		protected function readStyles():void
		{
			paddingTop = getStyle( "paddingTop" );
			paddingLeft = getStyle( "paddingLeft" );
			paddingRight = getStyle( "paddingRight" );
			paddingBottom = getStyle( "paddingBottom" );
			horizontalGap = getStyle( "horizontalGap" );
		}
	}
}
</code>
<p>We also have now more children to create and layout. We have an image to load for the avatar,  the embedded images for the background and a bunch of text fields. For the text fields, we use the same TextUtil to help us on the task of reading the styles and setting the properties. You may notice that we have 3 different styles, one for each text field. The TextUtil can read the styles from a class or from the type selector or current object ("this"). In this case we use 3 different classes.</p>
<p>The other thing that I implemented in this renderer is the ability to have variable height. To make it work with the list I just override the method getLayoutBoundsHeight that returns the height of the renderer after the layout is done. The List will use that value to layout all the items one after the other even if the height is different for each renderer.</p>
<p><a class="button" href="/assets/content//tutorialFiles/renderers/renderers_4.zip"><span class="download">The source is available for download.</span></a></p>
<p><a class="button" href="http://twitter.com/nahuel_en"><span class="twitter">Follow me on twitter</span></a></p>
</description>
         <link>https://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-4</link>
         <guid>https://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-4</guid>
         <category>Flex</category><category>Mobile</category>
         <pubDate>Thu, 12 May 2011 09:57:51 GMT</pubDate>
      </item>	
      <item>
         <title>Mobile ItemRenderer in ActionScript (Part 3) </title>
         <description><p>This is Part 3 of the series "Mobile ItemRenderer in ActionScript". This time we are going to use a different option to add the drop shadows to the text. We will be using a filter instead of having an extra text field.</p>
<p><a title="Part 1" href="/blog/entry/mobile-itemrenderer-in-actionscript-part-1">Part 1</a> and <a title="Part 2" href="/blog/entry/mobile-itemrenderer-in-actionscript-part-2">Part 2</a> for reference.</p>
<h4>Drop shadow Filter vs a second TextField</h4>
<p>The second text field workaround is good and performs better, but sometimes the designer has a bigger and softer shadow that cannot be reproduced with this technique. In that case we need to use a filter or bring a whole image from an image editor like Photoshop. Having an image works only if your text is not dynamic but lists usually have dynamic data. In that case, we don't have another option than to use a filter. From my experience of running an app in different devices, I found that the filters do not perform that bad, specially in tablets which have good memory and processor. You should test and see it how performs for you and maybe you can optimize in another places instead.</p>
<h4>Styles</h4>
<code>
renderers|SpriteLabel
{
	font-size: 20;
	color: #ffffff;
	font-family: _sans;
	min-height: 50;
	padding-left: 10;
	text-drop-shadow: 1, 120, #000000, 1, 6, 6; /* distance, angle,color, alpha, blurX, blurY, strength, quality, inner, knockout, hideObject*/
	background-color: #787884;
}
</code>
<h4>SpriteLabel Renderer</h4>
<p>This class is simpler that the one that we used in our previous example  because now we don't need to deal with 2 text fields. One interesting thing that I added this time is  text truncation. Truncating the label is something useful that you will need in your renderers when they have long text.<br/>
The TextUtil class provides a handy method to truncate the TextFiled. I hardcoded the width to 180px so you can see how it gets truncated.</p>
<p><img src="/assets/content/images/renderers/third_renderer.png" alt="Renderers" width="377" height="249" /></p>
<code>
package renderers
{
	import core.StyleClient;
	import flash.text.Font;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import mx.core.IDataRenderer;
	import utils.TextUtil;
	
	public class SpriteLabel extends StyleClient implements IDataRenderer
	{
		protected var labelField:TextField;
		
		//  Public Setters and Getters
		protected var _data:Object;
		public function set data( value:Object ):void
		{
			if( _data == value )
				return;
			
			_data = value;
			// if the textfield has been created we set the text
			if( labelField )
			{
				labelField.text = Font( data ).fontName;
			}
		}
		public function get data( ):Object
		{
			return _data;
		}
		
		//  Contructor	
		public function SpriteLabel()
		{
			percentWidth = 100;
		}
		
		//  Override Protected Methods
		override protected function measure():void
		{
			measuredHeight = getStyle( "minHeight" );
		}
			
		override protected function createChildren():void
		{
			labelField  = TextUtil.createSimpleTextField( this )
			addChild( labelField );
			
			// if the data is not null, set the text
			if( data )
				labelField.text = Font( data ).fontName;
			
		}
	
		override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
		{
			// position the field 
			labelField.x = getStyle( "paddingLeft" );
			labelField.y = (unscaledHeight - labelField.textHeight ) / 2;
			TextUtil.adjustTextSize( labelField, 180 );
			
			// drawbackground Color
			graphics.clear();
			graphics.beginFill( getStyle( "backgroundColor" ) );
			graphics.drawRect( 0, 0, unscaledWidth, unscaledHeight );
			graphics.endFill();
			
			// draw a separator line between each item
			var lineY:int = unscaledHeight -1;
			graphics.lineStyle( 1 );
			graphics.moveTo( 0, lineY );
			graphics.lineTo( unscaledWidth, lineY );
		}
	}
}
</code>
<p>The TextUtil also takes care of the drop shadow because the values for the drop shadow are coming from the CSS and we are delegating that task to the TextUtil. The filter is added by TextUtil with the help of another class.</p>
<p>Here it is the snippet of the code on the TextUtil that does that. The rest of the class has no changes from our previous post.</p>
<code>
public static function createSimpleTextField(  client:Object, selectable:Boolean = false, autoSize:String = "left", includeAll:Boolean = false ):TextField
{
	var textField:TextField = new TextField();
	
	client = getStyleClient( client );
	var textFormat:TextFormat = readTextFormat( client, includeAll );
	textField.defaultTextFormat = textFormat;
	textField.selectable = selectable;
	
	var dropShadowStyle:* = client.getStyle( "textDropShadow" );
	
	if( autoSize != "" )
		textField.autoSize = autoSize;
	
	if( dropShadowStyle != undefined )
	{
		if( !( dropShadowStyle is Array ) )
			dropShadowStyle = [ dropShadowStyle ];
		var dropShadow:CSSDropShadowFilter = new CSSDropShadowFilter( dropShadowStyle );
		textField.filters = [ dropShadow.filter ];
	}
	return textField;
}
</code>
<code>
public static function adjustTextSize( textField:TextField, availableWidth:int ):Boolean
{
	var truncated:Boolean = false;
	if( availableWidth < textField.textWidth )
	{
		var origText:String = textField.text;
		var charWidth:int =  textField.textWidth / textField.length;
		var numChar:int = availableWidth / charWidth - 3;
		while( availableWidth < textField.textWidth )
		{
			textField.text = origText.substr( 0, numChar ) + "...";
			numChar--;
		}
		truncated = true;
	}
	return truncated;
}
</code>
<h4>CSSDropShadowFilter</h4>
<p>This class is in charge of creating a drop shadow filter from an Array. The array is coming directly from the CSS. It supports all the possible values that the drop shadow filter support. The only catch is that you need to pass all the parameters in the CSS in the same order of the constructor of the DropShadowFilter, which are: distance, angle,color, alpha, blurX, blurY, strength, quality, inner, knockout, and hideObject. <br/>You can pass one or as many as you want, you just need to keep the order.</p>
<code>
package filters
{
	import flash.filters.DropShadowFilter;
	public class CSSDropShadowFilter
	{
		public var filter:DropShadowFilter;
		protected var properties:Array = [ "distance", "angle","color", "alpha", "blurX", "blurY", "strength", "quality", "inner", "knockout", "hideObject" ];
		
		public var distance:Number = 4;
		public var angle:Number = 45;
		public var color:uint = 0;
		public var alpha:Number = 1;
		public var blurX:Number = 4;
		public var blurY:Number = 4;
		public var strength:Number = 1;
		public var quality:int = 1;
		public var inner:Boolean = false;
		public var knockout:Boolean = false;
		public var hideObject:Boolean = false;
			
		private var _values:Array;
		public function set values( value:Array ):void
		{
			var equal:Boolean = false;
			if( _values && _values.length == value.length)
			{
				// compare all values
				equal = true;
				for (var i:int = 0; i < value.length; i++) 
				{
					if( _values[ i ] != value[ i ] )
					{
						equal = false;
						break;
					}
				}
			}
			if( !equal )
			{
				for (var n:int = 0; n < value.length; n++) 
				{
					this[ properties[ n ] ] = value[ n ];
				}
				updateFilter();
			}
		}
		public function get values():Array
		{
			return _values;
		}
		public function CSSDropShadowFilter( values:Array )
		{
			this.values = values;
		}
		
		protected function updateFilter():void
		{
			filter  =  new DropShadowFilter( distance, angle, color, alpha, blurX, blurY, strength, quality, inner, knockout, hideObject );
		}
	}
}
</code>
<p>Continue reading <a title="Part 4" href="/blog/entry/mobile-itemrenderer-in-actionscript-part-4">Part 4 </a>of this series on Item Renderers</p>
<p><a class="button" href="/assets/content//tutorialFiles/renderers/renderers_3.zip"><span class="download">The source is available for download.</span></a></p>
<p><a class="button" href="http://twitter.com/nahuel_en"><span class="twitter">Follow me on twitter</span></a></p></description>
         <link>https://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-3</link>
         <guid>https://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-3</guid>
         <category>Flex</category><category>Mobile</category>
         <pubDate>Wed, 04 May 2011 11:14:32 GMT</pubDate>
      </item>	
      <item>
         <title>Mobile ItemRenderer in ActionScript (Part 2) </title>
         <description><p>This is Part 2 of my series "Mobile ItemRenderers in ActionScript". This time I will explore how to apply drop shadows using a second TextField.</p>
<p>You can find <a title="Part 1" href="/blog/entry/mobile-itemrenderer-in-actionscript-part-1">part 1 </a>here for reference</p>
<h4>Why do we use a second TextField?</h4>
<p>As many of you may know, it is not recommended to use filters like drop shadow, bevel, or others on a DisplayObject when you are developing for Mobile. This is mostly because the player needs to create an extra image for each object that has a filter and that can bring performance issues. So if we want a text field with some drop shadow, the workaround is to have a second text field under it and move it a pixel down to mimic the effect.</p>
<p><img src="/assets/content/images/renderers/second_renderer.png" alt="Renderer" width="378" height="349" /></p>
<h4>Styles</h4>
<p>I have a text-drop-shadow-color property to pass the color of the shadow to the renderer. We also have a background-color style to have some contrast and be able to see the shadow. The rest is very similar to our previous example.</p>
<code>
renderers|SpriteShadowLabel
{
	font-size: 20;
	color: #222222;
	font-family: _sans;
	font-weight: bold;
	min-height: 50;
	padding-left: 10;
	text-drop-shadow-color: #ffffff;
	background-color: #bbbbbb;
}
</code>
<h4>SpriteVisualElement vs UIComponent</h4>
<p>In the previous example, we were extending from UIComponent. This time we are getting rid of  UIComponent and using a more light weight component. The problem is that the List needs an IVisualElement and because of that, we are extending  from SpriteVisualElement (Note: you can implement the IVisualElement interface and not use the SpriteVisualElement at all).</p>
<p>The other problem that we have now is that the SpriteVisualElement is not as complete as the UIComponent. We are missing something that the UIComponent provided us: CSS support. To fix that I created a simple class called StyleClient that implements the  IStyleClient and allows the component to participate in the styling framework. In addition to that, this class includes the measure, createChildren and  updateDisplayList in a similar way as the UIComponet (but much simpler). With that we can change the inheritance from UIComponent to StyleClient. The swap between classes can be made because some of the methods of UIComponent are supported in the StyleClient.</p>
<p>One thing that's important to mention is that the StyleClient does not wait for the next frame to commit the properties or invalidate. If that is needed, it is not really hard to implement.
You can see the inheritance chain of our renderers in the picture  below.</p>
<p><img src="/assets/content/images/renderers/renderer_inheritance.png" alt="Inheritance" width="165" height="355" /></p>
<p>I'm not going to paste all the code of the StyleClient, because this class is basically the implementation of  the IStyleClient interface (with the exception of registerEffects that I didn't feel that I needed). I want to highlight a few things though: first, notice that the method setLayoutBoundsSize calls updateDisplayList internally because this is the method that the List will use to layout the renderers.</p>
<code>
override public function setLayoutBoundsSize(width:Number, height:Number, postLayoutTransform:Boolean = true):void
{
	if ( isNaN( width ) )
		width = getPreferredBoundsWidth( postLayoutTransform );
	
	if ( isNaN( height ) )
		height = getPreferredBoundsHeight( postLayoutTransform );
	
	layoutWidth = width;
	layoutHeight = height;
	updateDisplayList( width, height );
}
</code>
<p>Second, we call measure and createChildren once all the styles are ready in stylesInitialized, to make sure that all the assets that we need for the renderer that are coming from the CSS are available.</p>
<code>
public function stylesInitialized():void
{
	if( !creationComplete )
	{
		createChildren();
		creationComplete = true;
		measure()
	}	
}
</code>
<h4>SpriteShadowLabel Renderer</h4>
<p>Let's take a look at the Renderer now. I'm reusing some of the code from the previous example: the data setter, the measure method and the constructor are very similar. The difference is that the data setter calls setValues if the TextFields are already created.</p>
<p>The other 3 methods for this class are:
<ul>
<li><strong>createChildren</strong> where we create both TextFields and we delegate the task of creation and reading the styles to the TextUtil (more on that later).</li>
<li><strong>updateDisplayList</strong> we layout  both TextFields and draw the background and separator.</li>
<li><strong>setValues</strong> sets the data to both TextFields.</li></ul></p>
<code>
package renderers
{
	import core.StyleClient;
	import flash.text.Font;
	import flash.text.TextField;
	import mx.core.IDataRenderer;
	import utils.TextUtil;
	
	public class SpriteShadowLabel extends StyleClient implements IDataRenderer
	{
		//  Protected properties
		protected var labelField:TextField;
		protected var labelShadowField:TextField;
		
		//  Public Setters and Getters
		protected var _data:Object;
		public function set data( value:Object ):void
		{
			if( data == value )
				return;
			_data = value;
			// if the textfield has been created we set the text
			if( labelField )
				setValues();
		}
		public function get data( ):Object
		{
			return _data;
		}
		
		//  Contructor
		public function SpriteShadowLabel()
		{
			percentWidth = 100;
		}
		
		//  Override Protected Methods
		override protected function measure():void
		{
			measuredHeight = getStyle( "minHeight" );
		}
		//--------------------------------------------------------------------------
		override protected function createChildren():void
		{
			labelShadowField = TextUtil.createSimpleTextField( this )
			TextUtil.changeColor( labelShadowField, getStyle( "textDropShadowColor" ) );
			addChild( labelShadowField );
			
			labelField  = TextUtil.createSimpleTextField( this )
			addChild( labelField );		
			
			if( data )
				setValues();
		}
		//--------------------------------------------------------------------------
		override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
		{
			// position the field 
			labelField.x = getStyle( "paddingLeft" );
			labelField.y = (unscaledHeight - labelField.textHeight ) / 2;
			
			labelShadowField.x = labelField.x;
			labelShadowField.y = labelField.y + 1;
			
			// drawbackground Color
			graphics.clear();
			graphics.beginFill( getStyle( "backgroundColor" ) );
			graphics.drawRect( 0, 0, unscaledWidth, unscaledHeight );
			graphics.endFill();
			
			// draw a separator line between each item
			var lineY:int = unscaledHeight -1;
			graphics.lineStyle( 1 );
			graphics.moveTo( 0, lineY );
			graphics.lineTo( unscaledWidth, lineY );
		}
		
		protected function setValues():void
		{
			// if the data is not null, set the text
			var text:String = ( data ) ? Font( data ).fontName : "";
			labelField.text = text;
			labelShadowField.text = text;
		}
	}
}
</code>
<h4>TextUtil</h4>
<p>This helper class creates a TextField and sets all the styles (bold, italic, font family, etc) and  a couple of properties like autoSize and selectable in the new TextField  been created.  All the styles for the text fields are coming from CSS, from a class selector example: .myClass or from a type selector example: MyItemRender. </p>
<code>
package utils
{
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	import flash.utils.getQualifiedClassName;
	import mx.styles.CSSStyleDeclaration;
	import mx.styles.ISimpleStyleClient;
	import mx.styles.IStyleManager2;
	import mx.styles.StyleManager;

	public class TextUtil
	{
		public static function createSimpleTextField(  client:Object, selectable:Boolean = false, autoSize:String = "left", includeAll:Boolean = false ):TextField
		{
			var textField:TextField = new TextField();
			client = getStyleClient( client );
			var textFormat:TextFormat = readTextFormat( client, includeAll );
			textField.defaultTextFormat = textFormat;
			textField.selectable = selectable;
			if( autoSize != "" )
			{
				textField.autoSize = autoSize;
			}
			return textField;
		}
		
		public static function getStyleClient( client:Object ):Object
		{
			var styleClient:Object;
			if( client is ISimpleStyleClient )
			{
				styleClient = client;
			}
			else
			{
				var styleManager:IStyleManager2 = StyleManager.getStyleManager( null );
				var selector:String = ( client is String ) ? "." + String( client ) : getQualifiedClassName( client ).replace("::", ".");
				var styleDeclaration:CSSStyleDeclaration = styleManager.getStyleDeclaration( selector );
				styleClient = styleDeclaration;
			}
			return styleClient;
		}
		
		public static function readTextFormat( client:Object, includeAll:Boolean = false ):TextFormat
		{
			var textFormat:TextFormat = new TextFormat();
			var align:String = client.getStyle("textAlign");
			if (align == "start")
				align = TextFormatAlign.LEFT;
			if (align == "end")
				align = TextFormatAlign.RIGHT;
			textFormat.align = align;
			textFormat.bold = client.getStyle( "fontWeight" ) == "bold";
			textFormat.color = client.getStyle( "color" );
			textFormat.italic = client.getStyle("fontStyle") == "italic";
			textFormat.font = client.getStyle( "fontFamily" );
			textFormat.size = client.getStyle( "fontSize" );
			textFormat.leading = client.getStyle("leading");
			
			if( includeAll )
			{
				textFormat.blockIndent = client.getStyle("blockIndent");
				textFormat.bullet = client.getStyle("bullet");
				textFormat.indent = client.getStyle("textIndent");
				textFormat.leftMargin = client.getStyle( "leftMargin" );
				textFormat.letterSpacing = client.getStyle("letterSpacing");
				textFormat.rightMargin = client.getStyle( "rightMargin" );
				textFormat.underline = client.getStyle("textDecoration") == "underline";
				
				var kerning:* =  client.getStyle("kerning");
				if (kerning == "auto" || kerning == "on")
					kerning = true;
				else if (kerning == "default" || kerning == "off")
					kerning = false;
				textFormat.kerning = kerning;
			}
			return textFormat;
		}
		
		public static function changeColor( textField:TextField, color:uint ):void
		{
			if( textField.textColor != color )
				textField.textColor = color;
		}
	}
}
</code>
<p>Continue reading <a title="Part 3" href="/blog/entry/mobile-itemrenderer-in-actionscript-part-3">Part 3 </a>of this series on Item Renderers</p>
<p><a class="button" href="/assets/content//tutorialFiles/renderers/renderers_2.zip"><span class="download">The source is available for download.</span></a></p>
<p><a class="button" href="http://twitter.com/nahuel_en"><span class="twitter">Follow me on twitter</span></a></p>
</description>
         <link>https://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-2</link>
         <guid>https://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-2</guid>
         <category>Flex</category><category>Mobile</category>
         <pubDate>Mon, 02 May 2011 10:00:00 GMT</pubDate>
      </item>	
      <item>
         <title>Mobile ItemRenderer in ActionScript (Part 1)</title>
         <description><p>If you are starting to do mobile development and are used to create all your ItemRenderers in MXML, you may notice that the small devices like phones and tablets do not perform as well as the desktop does and you need to start looking closely to different ways to optimize you app.</p>
<p>One of the ways to optimize your mobile app is to create your ItemRenderers in ActionScript.<a title="Devnet article" href="http://www.adobe.com/devnet/flex/articles/mobile-development-flex-flashbuilder.html"> Narciso Jaramillo wrote a good article for Devnet</a> with  great tips for mobile development and one of the items was exactly that, to keep your ItemRenderers in pure ActionScript.</p>
<p>Narciso mentions the Flex Framework comes with two ItemRenderers one is LabelItemRenderer that extends UIComponent and the other is IconItemRenderer that extends LabelItemRenderer. Those classes are great, but sometimes you have a different use case that needs a different set of classes. So in my examples I will not use those renderers. Instead, I will extend from UIComponent directly or from SpriteVisualElement for an even more lightweight class than UIComponent.</p>
<p>For the purpose of this tutorial, I'm planning a series of posts explaining the basics and moving on to more difficult renderers.</p>
<h4>Basic Example</h4>
<p>Let's start with the most simple renderer, a TextField that displays some text. To make it simple, we will extend from UIComponent and implement the IDataRenderer interface required from the List.</p>
<p>But before talking about the renderer, let's talk about the other elements.</p>
<h4>Application</h4>
<p>You need to create a Mobile project.  In this example, I use the simplest of all root containers,  that is an Application, not the TabbedApplication nor ViewBasedApplication subclasses. I added a List that expands 100% as the only element.</p>
<p><code>
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark">
	
	<fx:Script>
		<![CDATA[
			import mx.collections.ArrayList;
			[Bindable]
			private var items:ArrayList = new ArrayList( Font.enumerateFonts( true ) );
		]]>
	</fx:Script>
	
	<fx:Style source="styles/Main.css"/>
	
	<s:List id="list" width="100%" 
			height="100%" 
			dataProvider="{ items }" 
			labelField="fontName" 
			itemRenderer="renderers.UILabel"/>
	
</s:Application>
</code></p>
<h4>Styles</h4>
<p>I added an external StyleSheet where I have all the styles for the ItemRenderer:</p>
<code>
@namespace s "library://ns.adobe.com/flex/spark";
@namespace renderers  "renderers.*";

renderers|UILabel
{
	fontSize: 20;
	color: #000000;
	font-family: "_sans";
	min-height: 50;
	padding-left: 10;
}
</code>
<h4>ItemRenderer</h4>
<p>I have a simple class extending UIComponet that gives me a few handy methods and the ability to participate in the CSS framework.</p>
<p>The 3 methods from UIComponent that we use are the following:
<ul>
<li><strong>measure</strong> where we read the min size of the renderer from the style sheet. That comes in handy because devices with different dpi resolutions need different sizes.</li>
<li><strong>createChildren</strong> where we create the TextField, set the styles and if there is the data already available, we set the text in the TextField  to be displayed.</li>
<li><strong>updateDisplayList</strong> where we layout the elements and we draw a line separator for each ItemRenderer.</li>
</ul></p>
<p>In additions to those methods, we have the data property, which is the implementation of the IDataRenderer interface. That interface is the contract with the List and it is the way that the data is pushed to the ItemRenderer. If the TextField exists at the moment when the data is set, we set the text on the TextField, otherwise, we save it for later.</p>
<code>
package renderers
{
	import flash.text.Font;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import mx.core.IDataRenderer;
	import mx.core.UIComponent;
	
	public class UILabel extends UIComponent implements IDataRenderer
	{
		//Protected properties
		protected var labelField:TextField;
		
		//  Public Setters and Getters
		protected var _data:Object;
		public function set data( value:Object ):void
		{
			_data = value;
			// if the textfield has been created we set the text
			if( labelField )
			{
				labelField.text = Font( data ).fontName;
			}
		}
		public function get data( ):Object
		{
			return _data;
		}
		
		//  Contructor
		public function UILabel()
		{
			percentWidth = 100;
		}
		
		//  Override Protected Methods
		override protected function measure():void
		{
			measuredHeight = measuredMinHeight = getStyle( "minHeight" );
		}
		//--------------------------------------------------------------------------
		override protected function createChildren():void
		{
			labelField  = new TextField();
			labelField.defaultTextFormat = new TextFormat( getStyle( "fontFamily" ), getStyle( "fontSize" ) );
			labelField.autoSize = "left";
			addChild( labelField );
			// if the data is not null we set the text
			if( data )
				labelField.text = Font( data ).fontName;
		}
		//--------------------------------------------------------------------------
		override protected function updateDisplayList( unscaledWidth:Number, unscaledHeight:Number ):void
		{
			// position the field 
			labelField.x = getStyle( "paddingLeft" );
			labelField.y = (unscaledHeight - labelField.textHeight ) / 2;
			// we draw a separator line between each item
			var lineY:int = unscaledHeight -1;
			graphics.clear();
			graphics.lineStyle( 1 );
			graphics.moveTo( 0, lineY );
			graphics.lineTo( unscaledWidth, lineY );
		}
	}
}
</code>
<p>As you can see writing an ItemRenderer in ActionScript is not as difficult as it sounds.<br/>
I'm planning to show other examples in the future with multiple elements, background, states, text manipulation, multiple columns and more.</p>
<p>Continue reading <a title="Part 2" href="/blog/entry/mobile-itemrenderer-in-actionscript-part-2">Part 2 </a>of this series on Item Renderers</p>
<p><a class="button" href="/assets/content//tutorialFiles/renderers/renderers_1.zip"><span class="download">The source is available for download.</span></a></p>
<p><a class="button" href="http://twitter.com/nahuel_en"><span class="twitter">Follow me on twitter</span></a></p></description>
         <link>https://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-1</link>
         <guid>https://www.asfusion.com/blog/entry/mobile-itemrenderer-in-actionscript-part-1</guid>
         <category>Flex</category><category>Mobile</category>
         <pubDate>Thu, 28 Apr 2011 10:00:00 GMT</pubDate>
      </item>	
      <item>
         <title>Everything you know about design is wrong...</title>
         <description><p>...when running your app on a small, high screen-density device.</p>
<p>As you may know, we are developing a <a href="http://conqu.com">GTD application that runs on the Blackberry Playbook and Android tablets</a> (others to come) called Conqu. When we started, back in November, we were making designs as normal with Photoshop at the right size, and what we liked the most when looking at the designs (even when made small to fit the size of the device) were usually not all that good on the device. Since we hadn't developed the app yet, we only had mockup images to see. So what we did was browse those images to see how the actual app would look like.</p>
<p>This is what we learned:</p>
<h3>You need more contrast than you think</h3>
<p>While looking at the designs on the desktop monitor, bold and contrasting designs looked kind of ugly. They looked overdone. Not so on the device. The more contrast the elements had, the better they looked, the easier was to find them, the more defined were the different parts of the application, such as menus or navigation bars. Clearly defined elements were much needed than on the desktop. People using your app may be waiting for the bus under the sun, the screen may have glare, or they may have it sitting on their desk flat, so the viewing angle might not be optimal. Design for not-optimal viewing conditions.</p>
<p>Compare these two selected item designs for the menu:</p>
<p><img src="/assets/content/images/everything_you_know/menu1.png" alt="" width="233" height="389" /></p>
<p>Very little contrast.</p>
<p><img src="/assets/content/images/everything_you_know/menu2.png" alt="" width="230" height="446" /></p>
<p>A lot of contrast. While the first one might work on the web or desktop, the second was better for a handheld device. This design also has larger font, making it easier to read.</p>
<h3>Subtleties get lost</h3>
<p>While designing, we liked subtle shadows, soft colors and small details. However, on the device, soft gradients, small changes in tone or color were almost completely lost. Thin lines almost disappeared and elements we not clearly defined when there was not enough contrast. What's interesting is that "enough contrast" is actually "a lot" of contrast in a regular design (see point number one). You need detail, otherwise the application will look flat and uninteresting, but don't rely on subtleties for important things. For example, if you want to mark an item in a list as selected, make sure there is enough difference in color or texture, and not just some subtle shadow or change in tone. You also have to think about how far from the device your user will be. For a phone, people tend to look closer to it, so you can get away with small fonts and small details, but with a tablet, they may have it in their lap on the couch, so their eyes might be not as close to the device, so you would need larger fonts, more contrast, etc. </p>
<p><img src="/assets/content/images/everything_you_know/lines1.png" alt="" width="776" height="112" /></p>
<p>Subtle lines. Overdue date is only shown with a nice glowy red box.</p>
<p><img src="/assets/content/images/everything_you_know/lines2.png" alt="" width="783" height="118" /></p>
<p>More contrasting lines. The overdue date is shown with a "pill" to make it clearer. The checkbox is also red, but it is not the sole indicator.</p>
<h3>The device has its own boundaries</h3>
<p>Unlike a big desktop monitor these devices have boundaries (physical boundaries, the bezel) that you immediately see. While desktop applications can be full screen, they are generally enclosed in a window chrome, which can be "floating" around among other applications and you may even see your desktop wallpaper as background. In a device, however, your app will be full screen and will interact with the bezel and the device boundaries. The edges are important and elements that fit directly on the edges looked better than those that have space around them close to the edge. So in my opinion, the first menu looked better than the second one, as it used the device itself as an edge. This worked better on a smaller device (Galaxy Tab), but it may not necessarily be better on a larger device such as the iPad or Motorola XOOM. In those bigger displays, you may need additional borders so that the app doesn't look like is falling out the edge. </p>
<p><img src="/assets/content/images/everything_you_know/boundaries2.png" alt="" width="247" height="601" /></p>
<p>This design had a big border around the menu.</p>
<p><img src="/assets/content/images/everything_you_know/boundaries1.png" alt="" width="238" height="602" /></p>
<p>This design is snapping to the border of the device, utilizing the bezel as the sourounding box. It felt better than the previous one.</p>
<p>Speaking about the XOOM, or rather about Honeycomb, you have to remember that Honeycomb tablets have three buttons on the lower left edge. Unfortunately, that was the same placement for our lower four menu items. The issue here is that we no longer had a smooth edge and extra controls were added to that edge.</p>
<p><img src="/assets/content/images/everything_you_know/honeycomb-screen.png" alt="" width="618" height="389" /></p>
<p>The arrow shows the stacked menus (ours and Honeycomb's at the bottom)</p>
<h3>Test and test some more</h3>
<p>Devices can differ in size and screen density, the operating system may add controls, or a status bar and you need to make sure the design will work on those environments. Make sure you always check your designs in at least a couple of devices. </p>
<p>So maybe not all you know is wrong. Just take into account those points above as a reference since design is so subjective anyway (not even our designer Mark completely agrees with everything I said).</p>
<p> </p></description>
         <link>https://www.asfusion.com/blog/entry/everything-you-know-about-design-is-wrong</link>
         <guid>https://www.asfusion.com/blog/entry/everything-you-know-about-design-is-wrong</guid>
         <category>Design</category><category>Mobile</category>
         <pubDate>Thu, 31 Mar 2011 20:37:38 GMT</pubDate>
      </item>	
      <item>
         <title>Conqu's quest for life</title>
         <description><p>The idea for <a href="http://conqu.com">Conqu</a> was hashed long before the Android or Blackberry tablets were even a rumor. However, the idea sat on the back burner for several years until finally the first production tablet devices were on demo at Adobe MAX in late 2010. At that point the hardware finally caught up to the requirements of such an app. It was time to un-shelf the idea and put forth the effort to create an exceptional app for the Blackberry Playbook.</p>

<p>ASFusion has a history of developing some really nice apps Adobe Flex and Air, so the fit seemed natural. In November we started creating wireframes and mockups for the Conqu interface, only we had a few challenges to overcome. First, documentation was scarce. Having never developed a tablet or a touch based app before, we had to do a lot of learning, and a lot of idea testing and iterations on mockups.</p>

<p>After a disappointing realization that the original application name &quot;Flow&quot; was already being used by another company building--ironically a similar application--the name was changed to Conqu as a reference to &quot;Conquer&quot; in the phrase &quot;Conquer your inbox&quot;.</p>

<h3>Unique Challenges</h3>

<p>On the development side, we had to overcome some unique programming challenges. For instance, buttons and graphics for most apps can be made flexible through the use of a technique called <a href="http://www.sephiroth.it/tutorials/flashPHP/scale9/">Scale Nine</a>. What Scale Nine does is slice a graphic into nine parts so they can be stretched across the middle areas to accommodate any content size. The challenge we faced is that our interface was far more complex having gradients, top lighting for realism, and a texture that is impossible to stretch.&nbsp;</p>

<p>This need to use textures in the interface meant that we had to come up with a new technique. This led us to develop a method for using a hybrid Scale Nine that allowed us the flexibility to tile the middle part of a graphic to make it accept the content as needed.</p>

<h3>The Result</h3>

<p>We feel pretty good about the upcoming release of Conqu on both the Playbook and the Android platform. We think that the public will appreciate the fine details in the design as well as the many powerful features that make up Conqu. Conqu a great demonstration of what ASFusion is capable of producing no mater what the challenges are.</p>
</description>
         <link>https://www.asfusion.com/blog/entry/conqu-quest-for-life</link>
         <guid>https://www.asfusion.com/blog/entry/conqu-quest-for-life</guid>
         <category>Conqu</category><category>Flex</category><category>Mobile</category><category>Software Engineering</category>
         <pubDate>Fri, 25 Mar 2011 09:16:01 GMT</pubDate>
      </item>	
      <item>
         <title>Developing for the Blackberry Playbook will Rock</title>
         <description><p>At MAX we were shown, in a glass case, the new <a href="http://us.blackberry.com/playbook-tablet/">Blackberry Playbook</a>. I am personally super excited to try it out and start developing for it. First, you build apps for it using Flash (pure ActionScript or MXML), second, their store will be free (at least for some introductory time) and third, the hardware specs makes it the best on the market (1 GB RAM and 1 GHz dual-core processor??). Interestingly, their first development platform for it is Flash, and they said that later they will allow you to use Java and C++, so you can imagine that at this moment, Flash is as good as native.</p>

<p>And there is more. If you develop an application before the Playbook&#39;s launch and it gets approved,<a href="http://devblog.blackberry.com/2010/10/blackberry-playbook-developer-promotion-information/"> you&#39;ll be able to get a free Playbook</a> from RIM. The launch date is not yet announced, but I would get started as quickly as I can.</p>

<p>There are weekly webcast series you can attend. Those are hosted by RIM and usually Renaun Erickson from Adobe also shows relevant ActionScript code. They are a good starting point. You can find the link to those, the Getting Started guide and the documentation at the <a href="http://us.blackberry.com/developers/tablet/devresources.jsp">BlackBerry Tablet OS Development Resources</a>.&nbsp;</p>

<p>What are you waiting for?</p>
</description>
         <link>https://www.asfusion.com/blog/entry/developing-for-the-blackberry-playbook-will-rock</link>
         <guid>https://www.asfusion.com/blog/entry/developing-for-the-blackberry-playbook-will-rock</guid>
         
         <pubDate>Tue, 23 Nov 2010 22:41:37 GMT</pubDate>
      </item>	
      <item>
         <title>Mark's Introduction</title>
         <description><p>Hello everyone, I wanted to introduce myself as the newest member to join the ranks of ASFusion. I was hired on November 1st as a designer and front end developer, and I am excited to work with a team of people that really understand how the web works, and has a good sense of how to make the impossible happen. </p>
<p>About me: my name is Mark Aplet. If your familiar with Mango Blog, then you may have already heard my name before--or perhaps my username (visual28)--I design and develop themes or "skins" for Mango Blog users to dress up their blogs. I have also developed a number of free plugins for mango blog that are available from my <a href="http://www.visual28.com/page/projects">personal website</a>. I have been fairly active in the Mango Blog community since I was introduced to it about two and a half years ago. So if you have a theming question, I am a pretty good person to ask.</p>
<p>I have been working in the design industry for about 10 years. Then specifically in web design for about 7 plus years. In that time I have taught myself html and css, and even a little ColdFusion. In fact my very first ColdFusion app was MyCFNuke (no longer available). The ColdFusion clone of PHPNuke. I don't conceder myself to be a ColdFusion programmer in the least. I know my way around CF, but feel more at home in HTML and CSS. Languages that I hope will be put to good use while employed here at ASFusion.</p>
<p>When I am not designing or developing websites, I enjoy getting out of the house with my <a href="http://www.flickr.com/photos/visual28/3877748131/in/set-72157622206682806/">wife</a> (BFF) and or family pet <a href="http://www.flickr.com/photos/visual28/2345605618/in/set-72157604159812262/">Henna</a>--a very energetic golden retriever--for a trip up to the mountains for some camping, fun in the snow, or an all out off-road adventure in a heavily modified 1942 <a href="http://www.youtube.com/watch?v=9gB7xJlYfkY">Jeep rockcrawler</a>.</p></description>
         <link>https://www.asfusion.com/blog/entry/mark-s-introduction</link>
         <guid>https://www.asfusion.com/blog/entry/mark-s-introduction</guid>
         <category>Miscellaneous</category>
         <pubDate>Tue, 09 Nov 2010 15:08:51 GMT</pubDate>
      </item>	
      <item>
         <title>Adobe Enterprise Café News</title>
         <description><p>A couple of weeks ago, Adobe launched an AIR application called Adobe Enterprise Cafe:</p>
<blockquote>The Adobe Enterprise Café AIR app helps you stay in touch with Adobe teams and the enterprise community, receive news, find information, and aggregate content related to the entire enterprise community knowledge base. This is great place for all partners to receive timely news and stayed informed.</blockquote>
<p>I am happy to say that we developed the news section of the application in Flex using the <a href="http://mate.asfusion.com">Mate Framework</a>, and its backend, which is powered by <a href="http://www.mangoblog.org">Mango Blog</a>. </p>
<p><img src="/assets/content/images/cafepreferences.png" alt="" width="575" height="206" /></p>
<h3>A couple of development details</h3>
<p>While developing it, we made sure that the skin was exactly the same as the original design, to the pixel detail, leaving very little of the default Flex skin. This required creating a couple of custom components, such as the scrolling list and news next/previous navigation. </p>
<p> <embed type="application/x-shockwave-flash" width="508" height="408" src="http://blip.tv/play/gp0UgeyQKAA%2Em4v" allowfullscreen="true" allowscriptaccess="always"></embed></p>
<p>The smooth scrolling list will always keep the currently selected item on view when switching items, so if you scroll and then move to the next or previous item, it will quickly scroll to that position. </p>
<p> <embed type="application/x-shockwave-flash" width="508" height="408" src="http://blip.tv/play/gp0UgeyiPAA%2Em4v" allowfullscreen="true" allowscriptaccess="always"></embed></p>
<h3>Backend</h3>
<p>The news are fed by a Mango Blog install. We developed a couple of plugins to rate the posts, move old posts to the archives, get Adobe.tv video URLs, get top posts, and more. Thumbnails, product (LiveCycle, Acrobat, ColdFusion, etc) and links are managed by custom fields, and all of the custom fields are shown in a user-friendly “custom panel”. All communication is done via Remoting.</p>
<p><img src="/assets/content/images/cafenews_custompanel.png" alt="" width="133" height="171" /></p>
<h3>Install the app</h3>
<p> <iframe width="224" height="200" frameborder=0 scrolling="no" src="http://cafe.host.adobe.com/download/"></iframe></p></description>
         <link>https://www.asfusion.com/blog/entry/adobe-enterprise-cafe-news</link>
         <guid>https://www.asfusion.com/blog/entry/adobe-enterprise-cafe-news</guid>
         <category>Flex</category><category>Mango</category><category>Mate</category>
         <pubDate>Fri, 09 Jul 2010 12:49:28 GMT</pubDate>
      </item>	
      <item>
         <title>Goodbye Irvine, Hello Los Angeles!</title>
         <description><p>2010 brought a lot of changes to us and a big move. In December last year, the lease for our old office expired and we thought that we could change the scenery too. So we decided to go back to Los Angeles, after several years living in the Orange County. </p>
<p>With this change, I also needed to resign my title as the Manager of the <a href="http://www.ocflex.org">OCFlex</a> user group. But I have become an Adobe Community Professional, so I will still be involved with the community. </p>
<p>These are some photos of our old office, which I really liked!</p>
<p> </p>
<p><img src="/assets/content//images/photos/IMG_1689.jpg" alt="" width="640" height="426" /></p>
<p><img src="/assets/content//images/photos/IMG_1687.jpg" alt="" width="640" height="426" /></p>
<p><img src="/assets/content//images/photos/IMG_1709.jpg" alt="" width="640" height="426" /></p>
<p>And some of our new office:</p>
<p><img src="/assets/content//images/photos/IMG_6010.jpg" alt="" width="640" height="426" /></p>
<p><img src="/assets/content//images/photos/IMG_6014.jpg" alt="" width="640" height="426" /></p>
<p><img src="/assets/content//images/photos/IMG_6065.jpg" alt="" width="640" height="426" /></p>
<p> </p></description>
         <link>https://www.asfusion.com/blog/entry/goodbye-irvine-hello-los-angeles</link>
         <guid>https://www.asfusion.com/blog/entry/goodbye-irvine-hello-los-angeles</guid>
         <category>Miscellaneous</category>
         <pubDate>Thu, 10 Jun 2010 12:43:39 GMT</pubDate>
      </item>	
      <item>
         <title>CF.Objective() Does All The Right Things</title>
         <description><p><img alt="" height="180" src="/assets/content//images/button_cfobjective.jpg" width="180" /></p>

<p>This year I was part of the advisory board for the RIA track of <a href="http://cfobjective.com/">CF.Objective()</a>. I was also invited to speak. For the record, I didn&rsquo;t submit or vote for my session. :) Even though it must have become a little difficult to manage all the people in the board (3 members per track), it allowed for democratic voting of topics and wider variety. It was pretty amazing to see how people&rsquo;s interests lined up.&nbsp;</p>

<p>Overall, they had a good mix of topics, mostly advanced, which is a very good thing. From my experience at 360|Flex, people love in-depth topics. I believe CF.Objective gets the brightest CF audience, so it does make sense to have mostly advanced topics.&nbsp;</p>

<p>Unfortunately, the Flex part of the RIA track had very little attendance. There were only 5 Flex-only topics, and they were placed on the last day, which is always hard. I don&rsquo;t think the RIA track did all that bad overall, as the JavaScript and AIR sessions had good attendance.&nbsp;</p>

<p>From the speaker perspective, I think CF.Objective is one of the best conferences. They pay for speakers hotel rooms and even for the shuttle from the airport. This is a small gesture that really relieves the speakers of the burden of finding the correct transportation. You just go to Super Shuttle&rsquo;s desk and ask for your ticket. Minutes later you are routed to the right hotel without having to even find the address.&nbsp;</p>

<p>The hotel is very good, and they even serve organic eggs for breakfast! It has a good bar where you can actually have conversations since it is not loud. The hotel is located in Downtown Minneapolis instead of some isolated location, so you can always walk to get &nbsp;anything you need or find good restaurants all around. The food they served at the conference was great, and they had fulfilling vegan options. Other conferences I&#39;ve been to, their version of a vegetarian option is - if they actually have one - 3 pieces of lettuce on a wrap.</p>

<p>During the Bird of a Feather sessions they had a Pecha Kucha, which was pretty fun and interesting. I have to say that I was pretty surprised by some of the speakers, particularly <a href="http://bennadel.com/">Ben Nadel</a> and <a href="http://twitter.com/anthony_id">Anthony Israel-Davis</a>. I wish I could find the videos people recorded.&nbsp;</p>

<p>Overall, it was a great conference and I was very happy to see a lot of friendly faces I only get to see once a year.&nbsp;</p>
</description>
         <link>https://www.asfusion.com/blog/entry/cf-objective-does-all-the-right-things</link>
         <guid>https://www.asfusion.com/blog/entry/cf-objective-does-all-the-right-things</guid>
         <category>ColdFusion</category><category>Events</category>
         <pubDate>Tue, 27 Apr 2010 21:34:41 GMT</pubDate>
      </item>
	
   </channel>
</rss>