Tuesday, January 24, 2012

Creating a Flex AIR Screenshot app: Part 3

Today we will start creating the interface for our screenshot program.

As I said earlier, I am making this project in FlashDevelop 4.0 and it is recommended but not required to use the same tools as I am to create the application.

If you're using FlashDevelop, the first thing you need to do is go to Project and create a new Project. There's a big list of different types of projects you can create, pick Flex 4 AIR. After picking a destination, the project file will be created there, along with additional directories - bat, bin, lib and src. The one and only source file for now is located in the src folder, and is called Main.mxml. You can rename it to whatever you want, as long as it has the little green arrow next to it (meaning its the main file for this project) it will be the one that's executed on compilation.

The file has some tags by default - WindowedApplication - the root tags, and Declarations tags. In the root WindowedApplication tags, let's set showStatusBar's value to false - this will disable the status bar in our application (we don't need it now).

<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                       xmlns:s="library://ns.adobe.com/flex/spark"
                       xmlns:mx="library://ns.adobe.com/flex/mx" showStatusBar="false">

Next, the declarations tags. This is where we can declare objects, arrays, XML, and so on. Let's create a new ArrayCollection object. This will be used to store data for the page headings.

Each page (or stage) in our application is going to have a heading, which will be written in large font, to help the user move around the application. The heading consists of 2 parts - the Step number, and the Description. For example, according to our scheme from the previous tutorial, the very first screen is Step one, and during step one, the user has to load a web page to take a screenshot from. So, the first item in the array collection will have its step value set to "Step one:" and description to"load a web page."

Why is it needed to store text values in an array like this? Because there are going to be multiple steps, aka multiple stages. These stages can be easily handled by a control called ViewStack, which, according to what value it is passed, displays different content - like frames in Flash. Corresponding to these content blocks (the tags are called NavigatorContent), we add headings for them using this array collection.

According to our plan from the previous tutorial, there are 5 stages in total - step one, 2 step twos (depending on what the user decided to do with the loaded page - crop it or take a screenshot), step three and final step, each stage having its own description. Here is the ArrayCollection object containing all the data:

<fx:Declarations>
<mx:ArrayCollection id="headerTitles">
<fx:Object step="Step one:" description="load a web page." />
<fx:Object step="Step two:" description="set your export preferences." />
<fx:Object step="Step two:" description="select the area you wish to crop." />
<fx:Object step="Step three:" description="set your export preferences for the cropped image." />
<fx:Object step="Final step:" description="please wait while your images are being expored." />
</mx:ArrayCollection>
</fx:Declarations>

After the Declarations tags, let's add a VGroup. Set its width and height to 100% (making it scale to the whole window even if it is resized) and gap to 0. It shall contain an HBox and a Box objects - the HBox will be used for the header, and the Box - for the content.

Set their sizes and other properties like this:

<s:VGroup width="100%" height="100%" gap="0">
<mx:HBox backgroundColor="#333333" height="46" width="100%" paddingTop="10" paddingLeft="10">

</mx:HBox>
<mx:Box backgroundColor="#666666" width="100%" height="100%" paddingTop="20" horizontalAlign="center">

</mx:Box>
</s:VGroup>

Firstly, let's take care of the Box container. It is going to have a ViewStack with an id of "stack", which will contain 5 navigator content objects. In this tutorial, we're only going to fill one of these navigator content containers, and even that will be temporary.

Each NavigatorContent has its own id. The ids I set are - loadpage, screenshotsettings, crop, cropsettings and export.

As I already said, we're only populating the loadpage container today. We're going to add another VGroup inside of it, set its width to 100% and align the center the content horizontally. The VGroup contains a label object, a text input, and a 3 buttons. You'll see what the buttons are in the code below (I set their labels accordingly to what they are supposed to do). One thing left to note is that the Label object has its styleName property set to "descriptionText". This is essentially a CSS class, which we will use for most of the text inside the content area.

Here's the ViewStack now:

<mx:ViewStack id="stack">
<s:NavigatorContent id="loadpage">
<s:VGroup width="100%" horizontalAlign="center">
<s:Label styleName="descriptionText">Enter the link to the page:</s:Label>
<s:HGroup>
<s:TextInput width="250" /><s:Button label="Browse local..."/>
</s:HGroup>
<s:HGroup>
<s:Button label="Take screenshot" />
<s:Button label="Crop specific area" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>

<s:NavigatorContent id="screenshotsettings">

</s:NavigatorContent>

<s:NavigatorContent id="crop">

</s:NavigatorContent>

<s:NavigatorContent id="cropsettings">

</s:NavigatorContent>

<s:NavigatorContent id="export">

</s:NavigatorContent>
</mx:ViewStack>

Next, the HBox container. Here we add 2 labels to create a heading. Set their ids to headStep and headDesc, so that we can later create CSS styles for them. The text values for each of them are taken from the array collection using the index of the view stack. This way the viewstack content and headings are synched!

<s:Label id="headStep" text="{headerTitles.getItemAt(stack.selectedIndex).step}" />
<s:Label id="headDesc" text="{headerTitles.getItemAt(stack.selectedIndex).description}" />

So the whole VGroup now looks like this:

<s:VGroup width="100%" height="100%" gap="0">
<mx:HBox backgroundColor="#333333" height="46" width="100%" paddingTop="10" paddingLeft="10">
<s:Label id="headStep" text="{headerTitles.getItemAt(stack.selectedIndex).step}" />
<s:Label id="headDesc" text="{headerTitles.getItemAt(stack.selectedIndex).description}" />
</mx:HBox>
<mx:Box backgroundColor="#666666" width="100%" height="100%" paddingTop="20" horizontalAlign="center">
<mx:ViewStack id="stack">
<s:NavigatorContent id="loadpage">
<s:VGroup width="100%" horizontalAlign="center">
<s:Label styleName="descriptionText">Enter the link to the page:</s:Label>
<s:HGroup>
<s:TextInput width="250" /><s:Button label="Browse local..."/>
</s:HGroup>
<s:HGroup>
<s:Button label="Take screenshot" />
<s:Button label="Crop specific area" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>

<s:NavigatorContent id="screenshotsettings">

</s:NavigatorContent>

<s:NavigatorContent id="crop">

</s:NavigatorContent>

<s:NavigatorContent id="cropsettings">

</s:NavigatorContent>

<s:NavigatorContent id="export">

</s:NavigatorContent>
</mx:ViewStack>
</mx:Box>
</s:VGroup>

One thing left to do today is create styles for what we already have. These might be temporary, but later we will be able to easily change the appearance of our program using CSS. Create new Style tags under Declarations and add this:

<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";

.descriptionText{
fontSize: 24;
color: #fff;
}

#headStep{
fontSize: 30;
fontWeight: bold;
color: #ffffbb;
}

#headDesc{
fontSize: 30;
color: #ffffff;
}
</fx:Style>

Full code:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                       xmlns:s="library://ns.adobe.com/flex/spark"
                       xmlns:mx="library://ns.adobe.com/flex/mx" showStatusBar="false">
   
   
<fx:Declarations>
<mx:ArrayCollection id="headerTitles">
<fx:Object step="Step one:" description="load a web page." />
<fx:Object step="Step two:" description="set your export preferences." />
<fx:Object step="Step two:" description="select the area you wish to crop." />
<fx:Object step="Step three:" description="set your export preferences for the cropped image." />
<fx:Object step="Final step:" description="please wait while your images are being expored." />
</mx:ArrayCollection>
</fx:Declarations>

<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";

.descriptionText{
fontSize: 24;
color: #fff;
}

#headStep{
fontSize: 30;
fontWeight: bold;
color: #ffffbb;
}

#headDesc{
fontSize: 30;
color: #ffffff;
}
</fx:Style>
   
<s:VGroup width="100%" height="100%" gap="0">
<mx:HBox backgroundColor="#333333" height="46" width="100%" paddingTop="10" paddingLeft="10">
<s:Label id="headStep" text="{headerTitles.getItemAt(stack.selectedIndex).step}" />
<s:Label id="headDesc" text="{headerTitles.getItemAt(stack.selectedIndex).description}" />
</mx:HBox>
<mx:Box backgroundColor="#666666" width="100%" height="100%" paddingTop="20" horizontalAlign="center">
<mx:ViewStack id="stack">
<s:NavigatorContent id="loadpage">
<s:VGroup width="100%" horizontalAlign="center">
<s:Label styleName="descriptionText">Enter the link to the page:</s:Label>
<s:HGroup>
<s:TextInput width="250" /><s:Button label="Browse local..."/>
</s:HGroup>
<s:HGroup>
<s:Button label="Take screenshot" />
<s:Button label="Crop specific area" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>

<s:NavigatorContent id="screenshotsettings">

</s:NavigatorContent>

<s:NavigatorContent id="crop">

</s:NavigatorContent>

<s:NavigatorContent id="cropsettings">

</s:NavigatorContent>

<s:NavigatorContent id="export">

</s:NavigatorContent>
</mx:ViewStack>
</mx:Box>
</s:VGroup>

</s:WindowedApplication>

And that's all for this part!

Thanks for reading!

4 comments:

Anonymous said...

I am getting this error could you possibly guide me, whats wrong here?


Starting AIR Debug Launcher...
invalid application descriptor: Unknown namespace: http://ns.adobe.com/air/application/3.1
Press any key to continue . . .

Anonymous said...

For those who might stumble onto this error once again...

First navigate to the bin directory of your flex sdk, mine is
D:\flexsdk\4.5.1\bin

Find adl.exe - right click and select properties. Under details tab you will find the File version : 2.6.0.19120 - in my case

Now open the application.xml of the air project you are working, and update this line

with


And everything will fall in place.

Anonymous said...

Now open the application.xml of the air project you are working, and update this line
xmlns="http://ns.adobe.com/air/application/3.1"
with
xmlns="http://ns.adobe.com/air/application/2.6"

And everything will fall in place.

Kirill Poletaev said...

Yeah you can do that, or update your SDK to the newest version.

Post a Comment