Earlier this week I started work on a new NookColor app (already done and submitted). One of the minor design elements I wanted was a simple background using a graphic. I had assumed this would be a simple matter. It's already easy to set a background color. However this turned out to be slightly more complex than I imagined. What follows is an example of how it can be done. Credit for this goes to Jason San Jose and Holly Schinsky. Please note that part of this blog entry is my understanding of what's going on and there is a strong possibility I could be wrong. Any mistakes - blame me. If it's perfect - thank them. ;)
Let's start off with a super simple Flex Mobile application. I've got a view based application with one view. Here's the top level Application.
<?xml version="1.0" encoding="utf-8"?>
<s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" firstView="views.BGTestHomeView">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</s:ViewNavigatorApplication>
And here is my view:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:VGroup horizontalAlign="center" paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10" width="100%" height="100%" verticalAlign="middle">
<s:Label text="Mobile Apps Rule!" width="75%" fontSize="50" textAlign="center" />
</s:VGroup>
</s:View>
Which produces the lovely...
Now - if I want to add a background color, I can do so in two places - either the root app (ViewNavigatorApplication) or the view. Putting it in the root will only work for a brief second. You can see the background color for a second right before the view loads. So let's just put it in the view.
<s:VGroup horizontalAlign="center" paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10" width="100%" height="100%" verticalAlign="middle">
<s:Label text="Mobile Apps Rule!" width="75%" fontSize="50" color="white" textAlign="center" />
</s:VGroup> </s:View>
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView" backgroundColor="blue">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
Note the addition of "blue" to the View as well as the white color for the label. This creates this awesomely pretty view:
Ok. So when I first discovered this, I assumed that there was probably some other argument, like backgroundImage or some such, that would just as easy. Unfortunately that's not the case. Some Googling turned up a few blog posts talking about how to do it for Flex 4 apps in general. The recommendation was to create a skin for the application as a whole. You can do this in pure ActionScript or MXML. Here's my attempt with MXML.
<?xml version="1.0" encoding="utf-8"?>
<s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" firstView="views.BGTestHomeView" skinClass="skins.myAppSkin">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</s:ViewNavigatorApplication>
Note the change here - I've added skinClass. Let's look at that file.
<fx:Metadata>
<![CDATA[
[HostComponent("BGTest")]
]]>
</fx:Metadata> <s:states>
<s:State name="normal" />
<s:State name="disabled" />
</s:states> <s:BitmapImage width="100%" height="100%" source="@Embed('/images/grass.jpg')"/> <s:Group id="contentGroup" width="100%" height="100%" minWidth="0" minHeight="0" /> <s:ViewNavigator id="navigator" width="100%" height="100%" /> </s:Skin>
<?xml version="1.0" encoding="utf-8"?>
<s:Skin name="CustomApplicationSkin"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
>
At first I kind of thought of the skin file like a CSS sheet, where I'd specify just what I wanted to change. But - it's more like a "skeleton" or outline for your entire application. Notice I included the viewNavigator in there. And my content group. This is - from what I understand - the default way the mobile application would be laid out anyway. So my modification then was to simply include the image. End of story, right? Not exactly.
Turns out this "works", but the View ends up covering the background picture. This is where Jason's tip came in. If we go into our view and set the alpha of the background like so:
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView" backgroundAlpha="0">
We allow the content to show the background behind it. Here's the complete view. I added a black background to the label as well.
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView" backgroundAlpha="0">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:VGroup horizontalAlign="center" paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10" width="100%" height="100%" verticalAlign="middle">
<s:Label text="Mobile Apps Rule!" width="75%" fontSize="50" color="white" textAlign="center" backgroundColor="black" />
</s:VGroup>
</s:View>
And the result:
Awesome. I bet you didn't know I was such a good designer, did you? As I said, this solution may not be 100% accurate across all situations, and there may be other ways of doing this, but I hope this is helpful to others.
Archived Comments
This should be added to the Tour de Flex Mobile.
Contact them
That's Holly's app - linked to above. :)
Nice post, but this didnt work for me in Flash Builder 4.5 until I removed the height=100% from the ViewNavigator in the skinClass.
Works now, EXCEPT the content has a background colour showing (white by default) and thus obscuring the background image! Setting the backgroundAlpha to 0 on the View, no difference.
Any idea if there is a way round this?
thanks
Andy
Are you using 4.5.1? Maybe it was fixed there?
thanks Ray, good call, Im downloading the update now.
:-)
Hey Ray,
For what its worth, I am having a problem with the HostComponent bit. They dont make that clear what it should be set to. I had it as [HostComponent ("spark.components.TabbedViewNavigatorApplication")] because my app is a tabbed one, but it wasnt working.
Then, I created a sample app with just one View, and set the HostComponent to the name of the app... and it works. Dont know why it doesnt work with spark.components.View, but heh!
So now I need to figure out what to set the Host Component to for customising the background of my tabbed app. It really shouldnt be this difficult just to set a background image!!
hopefully someone out there has cracked this...
thanks,
Andy
Yeah I agree. Was real surprised this wasn't simpler.
hi, im new developing on flex and you post works perfect. But i have a problem when run it lost an Menu. I dont know what to do, if you can help me would appreciate you. Sorry for the bad use of English. This is my code for the menu:
<s:Button bottom="10" left="10" width="15%" height="15%" click="mx.core.FlexGlobals.topLevelApplication.viewMenuOpen=true" icon="@Embed('assets/search.png')" />
<s:viewMenuItems>
<s:ViewMenuItem label="por lista" icon="@Embed('assets/list.jpg')" click="navigator.pushView(listabusq)"/>
<s:ViewMenuItem label="Top down" icon="@Embed('assets/top.jpg')" click="navigator.pushView(btopdown)"/>
<s:ViewMenuItem label="Gps" icon="@Embed('assets/gps_icon.png')" click="whereimi(event)"/>
</s:viewMenuItems>
Sorry - I'm not really doing Flex much more. I'd suggest posting this to the Adobe Flex forums. (Or maybe someone on this thread will know.)
Thanks! It helped me a lot.
This solution was dead on. Thanks.
Hey Raymond, great post!
I've been trying to write the background skin in actionscript class (it's more lightweight for mobile app) with no success :( have you tried this before?
Sorry - I haven't used Flex in almost a year.
dear Fher, I am also facing the same problem. Now my menu do not appear. Did you figure it out?
Thank you! This really helped me!