Join James Talbot for an in-depth discussion in this video Controlling adaptable tablet layouts, part of Flex 4.6 and AIR 3.0 New Features for Mobile Apps.
- View Offline
The screen size of a tablet device is much bigger than a smartphone screen; in fact, it's closer to a desktop screen than a smartphone. If we develop a mobile application utilizing the Flex framework and we want to run this application on both smartphones and tablets, it's a best practice to build our UI as what's called an adaptable UI. This will greatly increase the user experience. It will help with performance because we can write different code for smartphones and for tablets, really optimizing the capabilities of each device, and it will also increase the usability, because tablet users expect something very different than smartphone users. For example, usually I carry around a smartphone with my left hand and I interact with the fingers of my right hand. Based on the size and weight of a tablet device, I want to design the screen differently to accept interactions on the left and on the right portions of the screen, and I would want to design those interactions so I could use just my left and right thumbs to interact with our application, which would have very different code.
Now the whole purpose of the Flex framework is so we can utilize as much code as possible, but sometimes that's not always realistic. So let's explore how to build an adaptable UI so we can reuse as much code as possible. So here I am in Adobe Flash Builder 4.6 Premium, and the first step is to simply build a mobile application. So I am going to click on New, and I am going to choose Flex Mobile Project, and I am going to call this mobile project Adapt. And then I am going to click Next. And again, the view-based and tab-based applications are generally designed specifically for smartphones.
So we're just going to choose Blank, and then inside of the states we can call what we need to do, designed for each one of those particular devices. So here I am just going to uncheck BlackBerry Tablet OS, and I am going to target this for the Apple iOS platform, and I am going to target this not just for iPhones but also iPads, and the same thing with Google Android, the whole multitude of different Google Android devices, plus all of the different Google Android tablets, I am going to target my application for. I am going to also have the application automatically reorient.
So again, if the user is in landscape mode, it will automatically reorient the application to that mode or portrait mode, and I will also automatically scale the application for different screen densities, targeting 160 dots per inch. Again, all of this, there is much more detailed information in the original series on how to build mobile applications for Flex. This is just a new technique, an advanced technique, for existing Flex developers that we are covering here in this series. Okay, so I am going to click Next, and for the Application server type, I can just use None. We are not going to worry about application servers for now. And I will click Next again, and you'll see my Main application file.
It will automatically create and it's called Adapt.mxml. Go ahead and just click Finish, and it will build this main application file for you. Now the first step--of course, here is our application, very simple--is I am going to define different states for each one of my different devices. I might define a portrait phone state for when I have a smartphone and it's in portrait view. I might define a landscape tablet view for when I have an iPad or a Zoom or another type of tablet for when it's in landscape mode.
So let's define those different states, and then I can put the appropriate code for each tablet in those states. So the first thing I am going to do is just simply define a states block, and for those of you who are more visual, feel free to do this in Design mode instead of in Coding, but I think I want to show you here inside of code, because I think it's very valuable for you to actually see how this all works in terms of the code. So I am defining by states block. This could of course be done in Design mode. And then I'm going to just simply define the different states that I want to be able to track.
So I am going to just going to State like so. Let's call our first State portraitPhone just like so. And then let's create the stateGroups here. And I am just going to say stateGroups. We are going to define this as phone and as portrait, just like so, okay, and then close off your State tag. And let's do the same thing of course for our landscapePhone, just like so. And the stateGroups for this one, I'm going to say landscape, phone. You can see the order doesn't matter here as long as you're including both of them, so there I have that.
And then now let's define the states for our tablet. So I am going to say State and I am going to say name="portraitTablet" like so and then the stateGroups for this one is equal to portrait, tablet like so. And then I am going to define yet another State and you say name="landscapeTablet" just like so, and then I'm going to say stateGroups="landscape,tablet" just like so.
Make sure you close off each one of your State blocks and then make sure of course yours States block up here is also closed. I'll add in some spacing, so I can set that up. So now I have defined each one of these different states inside of my application that I can utilize. Now, what we are going to do is we are going to write some code that will reference each one of those states at the appropriate time. So I want this to happen as soon as the application is actually loaded on the device. So what happens is the application is loaded on the device and then the application is resized to fit into that device.
Now that's actually captured in an event here on our application tag called resize. So I can just simply say resize, just right here. You'll see that there is an event here, part of UI component, and I can say resize. I can click on it, and then I can have Flash Builder here automatically generate me the resize handler to save on typing. So again, if that didn't appear for you and you're right there, you can also just press Ctrl+Space on your keyboard and you should get this Generate Resize Handler. If you click on this, this will generate you the application_resizeHandler, just like so. And again, you could also just manually type this in.
You would have to add in the import and do everything else. This is just a quick timesaver to avoid a lot of typing. We could have just manually typed that in, and this would be called once the application is loaded on the device and resized for the screen size of that device. So this is very useful for us because we can develop a couple of different variables here. So let's create a new variable here right at top, and let's call this public var, and let's say isTablet. And let's make this a Boolean, which is just simply a true or false, so we want to know if we are on a tablet or not.
So there I have my public var isTablet, just like so, and inside of our application_resizeHandler, let's take this variable that we created called isTablet and let's figure out if we are on a tablet or smartphone. So the easiest way to do that is just simply by testing the height and the width of the screen. Tablets, as I said before, have a much bigger screen than smartphones. So here I'll just say isTablet will take the height here, so I will say height > 960, okay.
We will add in the pipe pipe, and I will say width > 960 as well. That's it. So now if the height is greater than 960, the width is greater than 960, it will return this to be true, and now I can of course test on that. Let's do the same thing for whether or not our variable is in portrait. So here I am going to say var isPortrait, just like so, and we will also create a Boolean here. So now I'll say isPortrait.
And an easy way to tell if it's a portrait is to simply--if the height is greater than the width. That means you're in portrait mode. So here I will just say height > width and again if the height is greater than the width, then this will return to be true. Very straightforward. So now, based on this information that we have, whether or not we are on a tablet and whether or not we are in portrait mode, we can simply just test and pull in the appropriate state that we created down here. Based on the actual names, we can pull that in and have it display that state for the appropriate device.
Very, very powerful and as you can see here, very, very easy. And we can utilize all the rest of our code base here, call other functions and do all of that, but really build out the UI so that it increases the usability, our users are happy, and we can really build an efficient application. So let's do it here. I am going to just simply say currentState, which again you can learn all about how to switch between states and what states are. You can learn all about that in the basic Flex course here. Again, I'm assuming you guys know Flex, so here I am going to say currentState is equal to, and what I will add in here is I will just simply reference the variable that I created, so I will say isPortrait. That's going to of course be true or false. So I am going to say isPortrait, and then I am going to reference portrait, string literal there, and I am going to say colon, "landscape" as you see there. It's either going to be portrait or landscape.
And then I am going to do a concatenation here, and I will do the exact same thing, but I will test on the variable here called isTablet. So here I will say isTablet, and I'll say, "Tablets," colon, "Phone" just like so. And now I will just say is it a tablet or is it is a phone, and again we will be able to switch out. And again, portraitPhone, landscapePhone, portraitTablet, landscapeTablet. It should pull out the appropriate state based on what device it is actually on, called right when the application starts.
So let's just test that. So I am just going to add in a trace statement, and I am going to say trace currentState, just, like so. And this should, if we do it right, pull back whether we are on a phone, whether we are on a tablet, and whether we're in portrait mode, or whether we're in landscape mode. So go ahead and save this, so click on Save. You should see that it compiles with no problems. If it does not compile, just go up. It should tell you any errors, and go up and debug your code. You probably made just a quick syntax error. And now let's debug this so that our trace statement appears.
So over here, let's set up a new debug configuration, and let's set this up for a mobile application. So here I am going to highlight Mobile Application. I will creating new debug configuration. And let's use good old Apple iOS. And now I am going to say On desktop, and let's see what happens if we test this on an actual Apple iPad. So here I'm going to say On desktop, Apple iPad. I am going to simply click Debug, and if we did is right, you should see that down here the trace statement says portraitTablet.
So again, by default it shows us an Apple iPad in portrait mode, and it's a tablet. So that seemed to work, but let's make sure that we do this correctly. So let's go back here. I'm going to go back to my Debug Configurations, and instead of testing this on an Apple iPad, let's test this on an Apple iPhone 4. Click Apply, click Debug, and now if we did this right, you should see that are trace statement now says portraitPhone as opposed to portraitTablet.
So that's very, very powerful, and that gives us a way to take our mobile Flex application and dynamically adapt it to the screen size of a device.
- Controlling adaptable tablet layouts
- Controlling view hierarchy
- Using 16-bit and 32-bit render modes
- Using the Date Picker, Scroller, and List components
- Adding a splash screen to a mobile app
- Using native extensions for iOS and Android
- Testing with FlexUnit on Wi-Fi
- Packaging the application for release