Slides for my PhoneGap Presentation

I had the chance to present to the Seattle Web App Developers Group (formerly the Flex UG) and here are the slides from that presentation. Thanks a ton to everyone who came out. It was a lot of fun and it was exciting to see so many people interested in PhoneGap.

Recreating the Path Menu with Adobe Edge

I saw this blog post by Victor Coulon about redoing the Path menu in CSS3 and thought it was really slick. I’m not as up to speed on CSS3 as I need to be yet, but after taking a look at the post, I thought this was a perfect use case for animation in an application. It’s unintrusive, adds some overall polish, and generally improves the user interface. I thought Victor’s demo was awesome and since this use case is a good one for animation, I thought it would be an ideal experiment for Adobe Edge. (Final result is here)

The Animation

Building the animation itself was quite simple. I took Victor’s graphics, made them transparent PNGs, and imported them into Edge. At that point it was just a matter of lining everything up and using the timeline to tweak the animation. I didn’t sit down and do the math on the circle, so the elements aren’t aligned perfectly (apologies) but it’s basically just six elements that all pop in from behind the plus button. With Edge it was pretty easy to add the bounce effect. I just set the easing property to easeOutBack and that gave me the bounce.

The project loaded in Adobe Edge

Interaction

While the animation was easy, it took me a bit to get the interaction down correctly. Basically whenever the red button was clicked I wanted to play the timeline animation. When it was clicked again I wanted to reverse it. Luckily Edge has a decent API that makes working with the code it generates pretty straightforward. The biggest issue I ran into was that the playReverse() API can only be run on a symbol and I was having trouble figuring out how to get a symbol instance from within my click event. Running play() on the Composition (kind of the main Edge element, and the one Edge uses by default) runs off an entire set of other operations that made it tougher to do what I wanted.

So instead I used comp.getStage() to get an instance of the “stage” symbol where I could play and reverse the timeline at will. The result is pretty close to what Victor created and what the Path app uses. To do it all, I replaced the Adobe Edge DOM Ready Event Handler code in my project_name_edge.js file with the following:

/**
 * Adobe Edge DOM Ready Event Handler
 */
$(window).ready(function() {
     comp = new Edge.Composition(compId, {stage: "." + compId}, {});
        /**
 * Adobe Edge Timeline Launch
 */
     comp.ready(function() {
         var symb = comp.getStage();
 
         $('#stage_add_button').click(function(e){
               if(played)
               {
                    symb.playReverse();
                    played = false;
               } else {
                    symb.play();
                    played = true;
               }
 
         });
     });
});

Downsides

One downside is that once I make a change in Edge it overwrites all of the changes I’ve made. I’m not sure if there’s a safe place to make JavaScript edits like the one above but I’m going to check with the team. The other downside is that it’s all JavaScript, which makes it kind of heavy and you won’t get the hardware transforms that some browsers use for CSS3. I’m not much of a designer but after this little proof of concept I’m excited to see how Edge could potentially be used to add some fine-tuned interactions like the Path menu.

You can see a working demo here and the source for the project is up on GitHub.

Congratulations MAX Masters

My second year being involved in the planning of MAX was even more rewarding than the first. And the average scores for all of ours speakers were up over last year so it seems like the content is resonating with attendees and we continue to draw great speakers. Thanks to everyone who spoke at MAX this year for making it a huge success.

But we also like to call out the best of the best. This year it was really tough to be a MAX Master and so a huge congrats to the following speakers who made the cut.

  • Adam Lehman, Adobe Systems
  • Bryan O’Neil Hughes, Adobe Systems
  • Chris Converse, Codify Design
  • Chris Kitchener, Adobe Systems
  • Colin Smith, Adobe Systems
  • Dani Beaumont, Adobe Systems
  • Dave Helmly, Adobe Systems
  • David Nuescheler, Adobe Systems
  • Duane Nickull, Adobe Systems
  • Greg Rewis, Adobe Systems
  • Jack Davis, Wow, Inc.
  • James Williamson, Lynda.com
  • Jason Levine, Adobe Systems
  • Jim Babbage, Adobe Systems
  • Joe Rinehart, Booz Allen Hamilton
  • Marc Esher, Booz Allen Hamilton
  • Michael Chaize, Adobe Systems
  • Michael Labriola, Digital Primates
  • Michael Ninness, Lynda.com
  • Mordy Golding, Design Responsibly
  • Nicholas Zakas, NCZ Consulting
  • Patti Sokol, Adobe Systems
  • Paul Trani, Adobe Systems
  • Russell Brown, Adobe Systems

Adobe Financial Analyst Meeting Being Live Streamed

Quick heads up that Adobe is going to webcast the financial analyst meeting on November 9th starting at 10:00 AM EST. The press release mentions:

At the meeting, which is being held in New York City, Adobe’s management team will outline the company’s vision and business strategy.

I haven’t been to one of these, so I’m not sure what you should expect (plus it lasts 7 hours) but it should be a good chance to see what Adobe is thinking.

Flex Mobile European Tour 2011

Next week I’m going to be hitting the road with my colleague Mihai Corlan to spread the news about what Adobe has been up to the past few months. The primary reason for the trip is to show off the work the product teams have done with Flex on devices. Mihai and I are going to be doing some hands-on sessions showing just how easy it is to build great looking applications for iOS and Android. Bring your laptop, a copy of Flash Builder, and a device and we’ll walk you through all the steps you need to go through to start building and deploying mobile applications.

The other part of these events is providing some firsthand demos of some of the things we showed off at MAX. I think MAX was a major turning point for Adobe and Mihai and I will be showing off the touch tooling, talking about the creative cloud, and showing all of the things Adobe is up to in the world of HTML5. Plus we’ll give you some sneak peaks of the next generation of the Flash Platform. So there’s a ton of info and you’ll have the chance to ask questions firsthand. 2012 is going to be a great ride for the Adobe community so we want to make sure you have all the info you need to be successful.

Here are the cities we’re hitting:

Update: For those of you in the UK, there is an event on Monday, the 7th. I couldn’t make it out in time for that, but Mihai will be there covering everything.

November 9th

November 10th

November 11th

November 14th

November 15th

November 17th

November 19th

Can’t wait to see you and talk about application development and Adobe’s 2012.

Flash Player 11, AIR 3, and Flex/Flash Builder 4.6

Today is a pretty big day for Adobe developers. We’re officially announcing Flash Player 11, AIR 3, and Flex 4.6 and Flash Builder 4.6. The bits will be available in early October, but we’re announcing things today to help provide developers with information on what’s coming. I’ve been at Adobe for 4 years now and it’s been a very interesting 4 years as the landscape has evolved. It’s definitely been an up and down ride for Adobe developers, but the world has never been a better place for interactive developers, and these set of releases provide a ton of functionality aimed at helping Adobe developers create content in the most cutting edge places.

Gaming

We’ve been doing a lot of work to help enable console-esque games on top of the Flash Platform. Flash Player 11 includes Stage3D, which is going to open up a whole new world for game developers. Zombie Tycoon and Tanki are initial examples of what can be done and I can’t wait to see what comes of it. I’m reminded very much of the early days of Flash where a bunch of creative people were given a technology that was pretty open-ended and poked and prodded to create a bunch of very cool things. I think we’ll see that kind of revolution with Stage3D because of the ubiquity of Flash and the creativity of our developer community. Also in the gaming bucket is a framework we’re working on called Starling, which leverages Stage3D to create a super-fast way of doing parts of 2D games. It’s a great merger between the underlying technology/performance benefits of Stage3D and the kinds of things people want to do in 2D games. I think it’s also going to see some traction beyond games as agencies start to use it to enhance 2D content.

Mobile Applications

Flex and AIR have really found a great place in mobile applications. The performance enhancements in 2.7 made building native-experiences with AIR possible and we’ve seen some great examples of that in action including Machinarium and Caltrain Times. I’ve been impressed with performance on my 100 Days of Exercise application on iOS. I’m incredibly, incredibly excited by what this means for Flash. There’s a definite need to create mobile apps that can be deployed to multiple application stores. The Flash Platform provides a way to create great looking, high-design applications with near-native performance that can run on multiple devices. That’s a big deal.

And this release of AIR 3 goes where we haven’t gone before on the Flash Platform with native extensions. Now if there are features that aren’t included in AIR, like access to a credit card reader, you can build those extensions in native code and then link them to your AIR applications and leverage those libraries. It’s a great mix of native for specific use cases and AIR/Flash for fantastic user interfaces. It’s a big, big, big deal to be able to extend the platform and it’s a huge step.

I also think we have one of the best mobile-tool chains out there. Flash Builder 4.6 is going to help with creating those native extensions while also enabling the use of captive runtime in AIR so your applications don’t need to rely on the external AIR runtime on Android. Combine that with the enhancements that are coming in Flex 4.6 and it adds up to a world class mobile development platform that lets you reach more devices that matter. Flex 4.6 is especially exciting because of the new components that have been added. Flex and AIR are far and away the best toolset for interactive developers or any mobile developer who needs to create content for multiple devices. The apps you can build with Flex and AIR are going to stand out from the boring, standard apps that have started to litter app stores. Creativity will win the day and creativity is at the core of Flex/AIR.

Beyond

So this is a huge release, and I’m excited. But I’m also excited about the future of Adobe and how we are responding and will continue to respond to the evolving marketplace. As Danny Winokur, VP and GM of the Flash Platform, said recently:

“We’re not so concerned about what the right technology is for that as long as we’ll be able to deliver those experiences. We’re working with Microsoft and other members of the HTML community including Google, Apple, and others to enable rich experiences on HTML5.”

This is not a technology war. Adobe is about enabling developers to build the best possible experiences with the technology they want. We want to build tools and services that cater to that ethos. That takes the form of cutting-edge gaming features like Stage3D and world-class mobile app features with Flex, AIR and Flash Builder. But HTML5 is exciting for a lot of reasons, and Adobe will help developers there as well. If you’re an interactive developer, the future is very, very bright for you.

So you better get a good pair of sunglasses.

Success Window fix in Facebook ActionScript API

Facebook ActionScript APII just added a fix to an issue with the Facebook ActionScript API I ran into where after logging into Facebook on Android, the success event listener would never get called, the login window would never disappear, and you’d be left with a white StageWebView window with the word “Success” in it. It had something to do with a change in how AIR for Mobile handles StageWebView events.

I also noticed that when you would pass in a custom viewport for StageWebView in the initial window, the code would overwrite any settings and make it full screen. I didn’t think that was the expected behavior so I patched some code in FacebookMobile to make sure that if the login function has a viewPort specified, that one gets used instead of creating a new one.

I’m working on getting it added to the release SWC but I can’t tell exactly how the project has that process set up, so for now if you want the fix you’ll have to check out the source directly.

I’m spending some time with the Facebook API recently so if you have any issues, let me know.

AIR for Android Application – 100 Days of Exercise

100 Days of Exercise

100 Days of Exercise

Part of the evangelism team has been spending the past few weeks diving in and creating AIR mobile applications. We didn’t want them to look like just any other app so we hired the folks at The1stMovement and had them come up with some very cool designs across a few different application ideas. They gave us the PSD files and then we went to work developing them. It has been a great experience and I think it touches on something that AIR and Flex do really well; expressive, beautiful applications. This is an area where HTML/JS can’t quite cut it and that is pretty tough to do with native toolkits on iOS or Android. But it’s exactly the kind of thing that Flex and Flash excel at. Plus with AIR these apps can be taken and deployed to other platforms (you’ll see a version of all of these on the Apple App Store before too long). The apps themselves are awesome. Terry Ryan built a helpful item-finder called Finicky which incorporates a very cool grunge design. Renaun Erickson built the best looking Caltrain app on the market for finding train schedules and the closest stop to you based on GPS. Both are really spectacular.

Profile Screen

Profile Creation Screen

My contribution is 100 Days of Exercise, an app that will help track exercise progress over 100 days. Evidence has shown that if you do something 100 days in a row, it becomes a habit, and this app helps track that. It’s also supposed to help redefine what exercise means. For a lot of people, they think it means 3 hours at the gym, or an hour run, but it doesn’t have to. Just commit to something small for as long as you feel like you can do it. The goal is to get to the end of 100 days, not to throw yourself into a completely new lifestyle.

Wheel of Death

The Date Selector

One of the things I’m most proud of is the date picker. This is going to be an application for both Android and iOS and those platforms do date pickers very differently. Android has the buttons for up and down and iOS has the scroller. I wanted something that was very high design that would translate across both platforms. They came up with the “wheel of death” as a way to represent the month and date. So I took some of Evtim’s wheel layout code and created a custom Flex list layout that did what I wanted. It looks nice, is unique, performs well, and translates across any platform.

It’s been a fun project and I’m looking forward to adding a few things down the road. If you have any feedback, definitely drop me an email and let me know.

Skinning a Flex Mobile Button with Bitmaps

Flex Mobile Button Skin

Flex Mobile Button Skin

I’m working on a mobile app that requires a lot of skinning and since Flex 4 we’ve gotten a MUCH improved skinning model for Flex. Unfortunately, with Flex mobile, for performance reasons it’s a good idea to use ActionScript-only skins which means going back to the world of Flex 3 and diving into the component lifecycle a bit.

My colleague Terry Ryan has a good blog post that shows what he used to do skinning and I started off with that approach. But something didn’t seem quite right about skinning a button with a function associated with borders, so I tracked down the skinning master on the Flex team, Jason San Jose, and asked him the best way to do it. It turns out it’s really pretty simple to skin a button using Bitmap assets. If you look at the source code for ButtonSkin you’ll see that in the constructor, they associate FXG files (as classes) with specific button states.

upBorderSkin = spark.skins.mobile320.assets.Button_up;
downBorderSkin = spark.skins.mobile320.assets.Button_down;

In that constructor they also check for the DPI of the device and then load in the correct skin class according to that DPI. In general it’s going to be a good idea to check for different screen sizes and load in different assets accordingly, but for this example, I’ve just got one size that stretches reasonably well. The first step is to embed the assets and give them a variable name.

[Bindable]
[Embed(source="/assets/combobox_button_up.png")]
private var up:Class;
 
[Bindable]
[Embed(source="/assets/combobox_button_down.png")]
private var down:Class;

Then, in the constructor, simply set the upBorderSkin and downBorderSkin to those classes:

public function ComboBoxButtonSkin()
{
     super();
 
     upBorderSkin = up;
     downBorderSkin = down;
}

In this example I also wanted to create a graphic that would be overlaid on top of my skin. It’s a triangle graphic that will change depending on whether the app is on iOS or Android because of the different ways that those two platforms do ComboBoxes. On iOS you often have the app slide over to reveal the list (so the arrow would be pointing to the right) and on Android you often get a pop-up window with a list of choices (so the arrow would point down).

Adding Objects To Your Button Skin

To add something to your skin you need to go back and think about how Flex components work. You first want to make sure it’s added using the createChildren method. In this example I have already created the _triangle variable and instantiated it in the constructor.

override protected function createChildren():void
{
     super.createChildren();
     addChild(_triangle);
 
}

Then, once it’s added, you can start to modify it. In this example I wanted to make sure I could dynamically place the arrow depending on the height and width of my button. Luckily, the drawBackground method gives you an unscaledHeight and unscaledWidth, which you can use to calculate where the object should be placed. So all I had to do was tie into the drawing API, use those numbers, and voila, my skin now has the triangle.

override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
{
     var halfUnscaledHeight:int = Math.round(unscaledHeight/2);
 
     _triangle.graphics.beginFill(0xcee410);
     _triangle.graphics.moveTo(unscaledWidth-20,halfUnscaledHeight-5);
     _triangle.graphics.lineTo(unscaledWidth-10,halfUnscaledHeight);
     _triangle.graphics.lineTo(unscaledWidth-20,halfUnscaledHeight+5);
     _triangle.graphics.lineTo(unscaledWidth-20,halfUnscaledHeight-5);
     _triangle.graphics.endFill();
}

One of the benefits of this approach as opposed to just including the triangle in the skin is that the triangle kind of looked odd when it was stretched and morphed to different screen sizes. This way it’s independent of the bitmap skin and I can change the size according to the size of the underlying button.

Here’s what the finished button looks like and here’s the full code for you to grab.

Mobile Button Up State

Mobile Button Up State

Mobile Button Down Skin

Mobile Button Down Skin

    package skins
    {
    import flash.display.Sprite;
 
    import spark.skins.mobile.ButtonSkin;
 
    public class ComboBoxButtonSkin extends ButtonSkin
    {
    [Bindable]
    [Embed(source="/assets/combobox_button_up.png")]
    private var up:Class;
 
    [Bindable]
    [Embed(source="/assets/combobox_button_down.png")]
    private var down:Class;
 
    protected var _triangle:Sprite;
 
    public function ComboBoxButtonSkin()
    {
    super();
 
    upBorderSkin = up;
    downBorderSkin = down;
 
    _triangle = new Sprite();
    }
 
    override protected function createChildren():void
    {
    super.createChildren();
    addChild(_triangle);
 
    }
 
    override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
    {
    var halfUnscaledHeight:int = Math.round(unscaledHeight/2);
 
    _triangle.graphics.beginFill(0xcee410);
    _triangle.graphics.moveTo(unscaledWidth-20,halfUnscaledHeight-5);
    _triangle.graphics.lineTo(unscaledWidth-10,halfUnscaledHeight);
    _triangle.graphics.lineTo(unscaledWidth-20,halfUnscaledHeight+5);
    _triangle.graphics.lineTo(unscaledWidth-20,halfUnscaledHeight-5);
    _triangle.graphics.endFill();
    }
 
    }
    }