Adding icons to a Flex TabNavigator control

I was trying to figure out how to add icons to a TabNavigator control today and ended up making this. The trick is that you actually add the icon on the TabNavigator control’s child containers and not on the TabNavigator itself. The example also has three tabs which each look at a different filtered view of an XML document (filtered using E4X).

Full code after the jump.

View MXML

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white">

    <mx:XML id="model">
        <records>
            <record uuid="1" status="check" name="User 1" data="Data 1" />
            <record uuid="2" status="warning" name="User 2" data="Data 2" />
            <record uuid="3" status="warning" name="User 3" data="Data 3" />
            <record uuid="4" status="critical" name="User 4" data="Data 4" />
            <record uuid="5" status="check" name="User 5" data="Data 5" />
            <record uuid="6" status="check" name="User 6" data="Data 6" />
            <record uuid="7" status="warning" name="User 7" data="Data 7" />
            <record uuid="8" status="critical" name="User 8" data="Data 8" />
        </records>
    </mx:XML>

    <mx:Script>
        <![CDATA[
            [Bindable]
            [Embed(source="assets/bulletCheck.png")]
            private var BulletCheck:Class;

            [Bindable]
            [Embed(source="assets/bulletWarning.png")]
            private var BulletWarning:Class;

            [Bindable]
            [Embed(source="assets/bulletCritical.png")]
            private var BulletCritical:Class;

            private const CHECK:String = "check";
            private const WARNING:String = "warning";
            private const CRITICAL:String = "critical";
        ]]>
    </mx:Script>

    <mx:TabNavigator width="400" height="200">
        <mx:VBox label="Check" icon="{BulletCheck}">
            <mx:DataGrid id="gridCheck"
                    width="100%"
                    height="100%">
                <mx:columns>
                    <mx:DataGridColumn dataField="@name" />
                    <mx:DataGridColumn dataField="@data" />
                </mx:columns>
                <mx:dataProvider>
                    {model.record.(@status == CHECK)}
                </mx:dataProvider>
            </mx:DataGrid>
        </mx:VBox>

        <mx:VBox label="Warnings" icon="{BulletWarning}">
            <mx:DataGrid id="gridWarning"
                    width="100%"
                    height="100%">
                <mx:columns>
                    <mx:DataGridColumn dataField="@name" />
                    <mx:DataGridColumn dataField="@data" />
                </mx:columns>
                <mx:dataProvider>
                    {model.record.(@status == WARNING)}
                </mx:dataProvider>
            </mx:DataGrid>
        </mx:VBox>

        <mx:VBox label="Errors" icon="{BulletCritical}">
            <mx:DataGrid id="gridCritical"
                    width="100%"
                    height="100%">
                <mx:columns>
                    <mx:DataGridColumn dataField="@name" />
                    <mx:DataGridColumn dataField="@data" />
                </mx:columns>
                <mx:dataProvider>
                    {model.record.(@status == CRITICAL)}
                </mx:dataProvider>
            </mx:DataGrid>
        </mx:VBox>
    </mx:TabNavigator>

</mx:Application>

View source is enabled in the following example.

19 thoughts on “Adding icons to a Flex TabNavigator control

  1. Very nice example – thanks for posting it. When I tried to download the source code I got a 404 error. I wanted to get the icons you used so I could run the example myself in FlexBuilder.

  2. Peterd,
    i need to put 10 labels in my tabNavigator and i need every names are visible!
    thanks
    Paulo

  3. Do you know how to move the icon’s to a stylesheet?

    I have the following, but it doesn’t appear to work (the background style comes through though.

    .greenTab {
    	icon:        Embed('/assets/green-dot.gif');
    	backgroundColor:	'#cccccc';
    }
    
    .redTab {
    	icon:        Embed('/assets/red-dot.gif');
    	backgroundColor:	'#cccccc';
    }
    

    -Sean

  4. Sean,

    I logged an enhancement request about making it easier to skin individual buttons on a ButtonBar control a while ago, http://bugs.adobe.com/jira/browse/SDK-17117.

    The same workarounds may apply to the TabBar/TabNavigator controls as well, although you may need to use the getTabAt() method, I believe.

    When I get some time, I’ll see if I can post the workarounds to SDK-17117 as full blog entries.

    Hope that helps,

    Peter

    1. Pan,

      I’m not sure if this is the best approach, but you could try and do something like this:

      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
       
          <mx:Script>
              <![CDATA[
                  import mx.controls.ButtonLabelPlacement;
                  import mx.controls.TabBar;
                  import mx.controls.tabBarClasses.Tab;
       
                  protected function init():void {
                      var tabBar:TabBar = tabNav.mx_internal::getTabBar();
                      var idx:uint;
                      var len:uint = tabBar.numChildren;
                      for (idx = 0; idx < len; idx++) {
                          Tab(tabBar.getChildAt(idx)).labelPlacement = ButtonLabelPlacement.LEFT;
                      }
                  }
              ]]>
          </mx:Script>
       
          <mx:TabNavigator id="tabNav" width="400" height="300"
                           horizontalCenter="0" verticalCenter="0"
                           creationComplete="init();">
              <mx:VBox label="Accept" icon="@Embed('accept.png')">
                  <!-- child tags -->
              </mx:VBox>
              <mx:VBox label="Add" icon="@Embed('add.png')">
                  <!-- child tags -->
              </mx:VBox>
              <mx:VBox label="Anchor">
                  <!-- child tags -->
              </mx:VBox>
          </mx:TabNavigator>
       
      </mx:Application>

      Peter

      1. private function placeLabel():void{
        setStyle and TextAlign should work …

        for (var i:int = 0; i < linkTab.numChildren; i++) {

        var tab:Tab = linkTab.getTabAt(i) as Tab;
        tab.setStyle("textAlign","left");

        }
        }

  5. I have been trying to animate those icons in the TabNavigator. Any idea on how to do that?
    Thanks

  6. I am trying to use icons loaded with my asset loading system (which is quite common-style), and I get a coercion error..

    Basically, my Assets singleton class returns a class reference to an asset which is stored inside an external swf.
    The assets are loaded, and I use the system everywhere in the project. for example

    Now for use as icon, this approach doesnt seem to work. I get

    Flex Error #1034: Type Coercion Failed: Cannot Convert TalentTabIconEconomy@6d40c41 to mx.core.IFlexDisplayObject

    Will try to find a solution and post it here.

  7. My example was supposed to be

    <Image source="{Assets.getAsset('TalentTabIconEconomy')}"/>

    and i can’t seem to find a solution yet :(

  8. Heh, totally forgot about this entry. Long time no see :-)

    Well, my Assets class is (overly) complicated and consists of several helper classes. It would be too much to post it here. Should somebody be interested, feel free to drop a mail at jovica.aleksic_at_loopmode.de.

    However, the TabNavigator-with-icons situation became obsolete, because due to further project-specific complications I decided not to use the Flex TabNavigator, but create a “fake” custom tabNavigator using the usual containers like Canvas, Hbox etc.

Comments are closed.