flex 4 tabbar - disable tab - apache-flex

is there a common way to disable a tab of a spark tabbar component in flex 4? with the mx tabnavigator component you can just disable the content corresponding to the tab and the tab is also disabled then. but doing this with the spark tab bar component disables just the content not the tab.
here is my simple example:
<mx:TabNavigator x="122" y="155" width="200" height="200">
<s:NavigatorContent label="Tab 1" width="100%" height="100%">
<s:Label text="Label1"/>
</s:NavigatorContent>
<s:NavigatorContent label="Tab 2" width="100%" height="100%" enabled="false">
<s:Label text="Label2"/>
</s:NavigatorContent>
<s:NavigatorContent label="Tab 3" width="100%" height="100%">
</s:NavigatorContent>
</mx:TabNavigator>
<s:TabBar x="368.7" y="100.35" dataProvider="{viewstack1}" />
<mx:ViewStack x="364" y="133" id="viewstack1" width="200" height="200">
<s:NavigatorContent label="Tab 1" width="100%" height="100%">
<s:Label text="Label1"/>
</s:NavigatorContent>
<s:NavigatorContent label="Tab 2" width="100%" height="100%" enabled="false">
<s:Label text="Label2"/>
</s:NavigatorContent>
<s:NavigatorContent label="Tab 3" width="100%" height="100%">
<s:Label text="Label3" x="1" y="0"/>
</s:NavigatorContent>
</mx:ViewStack>
many thx,
florian

Addendum:
Literally two minutes after I got back to actually working, I found an "elegant" solution using a skin.
If you apply a custom skinClass to your tab bar you can bind the tab.enabled property just like you'd expect/want.
<fx:Script>
<![CDATA[
[Bindable] private var tab2IsReady:Boolean = false;
private function checkCriteria():void{
tab2IsReady = someOtherThing.isFinished;//Boolean
}
]]>
</fx:Script>
<s:TabBar id="theTabBar"
dataProvider="{viewStack}"
skinClass="skins.CustomTabBarSkin"/>
<mx:ViewStack id="viewStack">
<s:NavigatorContent label="Tab index 0">
<!-- Your first tab's content -->
</s:NavigatorContent>
<s:NavigatorContent label="Tab index 1" enabled="{tab2IsReady}">
<!-- Your second tab's content -->
</s:NavigatorContent>
</mx:ViewStack>
When you type "skinClass" use the auto complete to generate (in FlashBuilder ~4.5+???) the custom skin (named whatever you want).
The code will appear like below (I left out the Script tag).
<?xml version="1.0" encoding="utf-8"?>
<!-- skins/CustomTabBarSkin.mxml
...
Adobe's copyright & doc comments
...
-->
<s:Skin
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
alpha.disabled="0.5">
<fx:Metadata>
<![CDATA[
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("spark.components.TabBar")]
]]>
</fx:Metadata>
<!-- optional Script tag here -->
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
</s:states>
<!--- #copy spark.components.SkinnableDataContainer#dataGroup -->
<s:DataGroup id="dataGroup" width="100%" height="100%">
<s:layout>
<s:ButtonBarHorizontalLayout gap="-1"/>
</s:layout>
<s:itemRenderer>
<fx:Component>
<s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin" />
</fx:Component>
</s:itemRenderer>
</s:DataGroup>
</s:Skin>
<!-- End skins/CustomTabBarSkin.mxml -->
Change:
<fx:Component>
<s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin" />
</fx:Component>
To:
<fx:Component>
<s:ButtonBarButton skinClass="spark.skins.spark.TabBarButtonSkin"
enabled="{data.enabled}" />
</fx:Component>
Then any <s:NavigatorContent/> in the ViewStack with its enabled property set or bound will do exactly what you expect
(be enabled when true, & disabled when false).

One solution to try would be to use mx:VBox components instead of s:NavigatorContent.
From http://blog.flexexamples.com/2007/08/25/enabling-and-disabling-specific-tabs-in-a-tabbar-control/ :
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/08/25/enabling-and-disabling-specific-tabs-in-a-tabbar-control/ -->
<mx:Application name="TabBar_enabled_test"
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white">
<mx:ApplicationControlBar dock="true">
<mx:CheckBox id="tabBarEnabled"
label="TabBar.enabled"
selected="true"
width="25%" />
<mx:CheckBox id="tab1Enabled"
label="Tab1.enabled"
selected="true"
width="25%" />
<mx:CheckBox id="tab2Enabled"
label="Tab2.enabled"
selected="true"
width="25%" />
<mx:CheckBox id="tab3Enabled"
label="Tab3.enabled"
selected="true"
width="25%" />
</mx:ApplicationControlBar>
<mx:VBox verticalGap="0">
<mx:TabBar id="tabBar"
width="400"
dataProvider="{viewStack}"
enabled="{tabBarEnabled.selected}" />
<mx:ViewStack id="viewStack" width="400" height="100">
<mx:VBox id="tab1"
label="Tab1"
backgroundColor="haloGreen"
enabled="{tab1Enabled.selected}">
<mx:Label text="Label 1" />
</mx:VBox>
<mx:VBox id="tab2"
label="Tab2"
backgroundColor="haloBlue"
enabled="{tab2Enabled.selected}">
<mx:Label text="Label 2" />
</mx:VBox>
<mx:VBox id="tab3"
label="Tab3"
backgroundColor="haloOrange"
enabled="{tab3Enabled.selected}">
<mx:Label text="Label 3" />
</mx:VBox>
</mx:ViewStack>
</mx:VBox>
</mx:Application>

For those who want an working answer for Flex 4.5 (probably Flex 4 also). I finally figured out a solution. It feels like a hack to me, but Adobe's not answering the call and it's working for me. Here's a simplified example.
<!-- component that has the the TabBar in it... -->
<fx:Script>
<![CDATA[
//imports here
import mx.core.UIComponent;
//imports
private function setTabEnabled(index:int,enabled:Boolean):void{
var theTab:UIComponent = theTabBar.dataGroup.getElementAt(index) as UIComponent;
if(theTab){theTab.enabled = enabled;}
}
]]>
</fx:Script>
<s:TabBar id="theTabBar"
dataProvider="{viewStack}"/>
<mx:ViewStack id="viewStack">
<s:NavigatorContent label="0th Tab">
<!-- ...Content -->
</s:NavigatorContent>
<s:NavigatorContent label="1st Tab">
<!-- ...Content -->
</s:NavigatorContent>
<s:NavigatorContent label="2nd Tab">
<!-- ...Content -->
</s:NavigatorContent>
</mx:ViewStack>
<!-- rest of the component that has the the TabBar in it... -->
Then you just call setTabEnabled(theTabIndex,trueFalse) in an event handler related to whatever decides why the tab is, or isn't, enabled.
I should extend the TabBar to support this, but I've already spent enough time trying to figure it out.
Happy Coding =D

Related

How to enable vertical scroll in a flex mobile View?

At runtime when I click the Lire button then the TextArea field under it is populated from a sharedobject data and the display becomes bigger :
Here is code :
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark" title=""
creationComplete="creationCompleteHandler(event)" >
...
<s:VGroup width="100%" height="100%" paddingTop="5" verticalAlign="middle" horizontalAlign="center">
<s:TextInput id="chp1" width="50%"/>
<s:TextInput id="chp2" width="50%"/>
<s:Button label="Enregistrer" click="enregistrer(event)" />
<s:Label/>
<s:Button label="Lire" click="lire(event)" />
<s:TextArea id="area"/>
<s:Label/>
<s:HGroup>
<s:Button label="Envoyer" click="send(event)" />
<s:Button label="Retour" click="navigator.popView()" />
</s:HGroup>
<s:TextArea id="resultHTTP"/>
<s:TextInput id="h_url" text="{url}" visible="false"/>
</s:VGroup>
How to enable vertical scroll then to view others components at the bottom ?
wrap your VGroup with a scroller. something like this:
's:Scroller width="100%" height="100%"
s:VGroup width="100%" height="100%" paddingTop="5" verticalAlign="middle" horizontalAlign="center"'

BorderContainer with text is not showing buttonMode correctly

In my code, I have a list made up of items from a dataprovider. The itemRenderer for the list consists of a BorderContainer with text in it. I'm mimicking a row of buttons on a scrolling list. I'd like the cursor to change to the hand cursor as it passes over the "button", but the pointer only changes in the part of the BorderContainer that isn't covered by the text.
I've set the buttonMode to true for the list, the BorderContainer, and the text, so why isn't the cursor changing when passing over the text?
This is the list code
<s:List id="listProject" width="100%" height="100%" horizontalScrollPolicy="off" allowMultipleSelection="false"
click="listProject_clickHandler(event)" itemRenderer="ProjectRenderer"
dataProvider="{listProjects}" creationComplete="listProject_creationCompleteHandler(event)" buttonMode="true">
And this is the renderer
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true">
<!--<s:Label text="{data.header}"/>-->
<s:states>
<s:State name="normal"/>
<s:State name="hovered"/>
<s:State name="selected"/>
</s:states>
<!--<s:Image source.normal="{data.image1}" source.hovered="{data.image2}"/>-->
<s:BorderContainer width="200" height="50" backgroundColor="{data.color}"
borderColor.selected="#FFFFFF" borderVisible.normal="false"
borderVisible.selected="true" borderWeight.selected="4" borderStyle.selected="inset" buttonMode="true">
<s:layout>
<s:HorizontalLayout verticalAlign="middle" horizontalAlign="center"/>
</s:layout>
<mx:Text width="200" text="{data.header}" selectable="false"
color="#FFFFFF" fontSize="15" fontWeight="bold" leading="0" textAlign="center" buttonMode="true" useHandCursor="true"/>
</s:BorderContainer>
</s:ItemRenderer>
Just use a Spark Label instead of mx:Text and you'll be fine.
Also, there's some redundancy in your code. I took the liberty of trimming it down a little:
<s:BorderContainer width="200" height="50" backgroundColor="{data.color}"
borderColor.selected="#FFFFFF" borderVisible.normal="false"
borderVisible.selected="true" borderWeight.selected="4"
borderStyle.selected="inset" buttonMode="true">
<s:Label text="{data.label}" color="#FFFFFF" fontSize="15" fontWeight="bold"
horizontalCenter="0" verticalCenter="0"/>
</s:BorderContainer>
This will also fix that nasty jumpiness of the text when hovered or selected.
As soon as you do not need interaction with mx:Text, you can set mouseChildren property of its parent to false. It will fix the problem. Here is a short example:
<s:ItemRenderer>
<s:BorderContainer width="200" buttonMode="true" useHandCursor="true" mouseChildren="false">
<mx:Text text="No many text" selectable="false" />
</s:BorderContainer>
</s:ItemRenderer>

flex simple rollover problem

I have a panel2 inside panel1.
When I rollover panel1, I want panel2 to be visible and when mouseOut, panel2 to be invisible.
This is simple with mouseOcer and MouseOut events
Of course trouble is when I rollover panel2 (inside panel1): it starts blinking.
My question is: how to simply correct it ? (of course I would like buttons inside panel2 to be active as well)
regards
Why this code won't work for you?
<?xml version="1.0" encoding="utf-8"?>
<s:Application minHeight="600" minWidth="955" xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
[Bindable]
private var isOver:Boolean;
]]>
</fx:Script>
<s:Panel horizontalCenter="0" id="panel1" mouseOut="isOver = false" mouseOver="isOver = true" title="Panel1"
verticalCenter="0">
<s:Panel bottom="10" id="panel2" left="10" right="10" title="Panel2" top="10" visible="{isOver}">
<s:layout>
<s:VerticalLayout horizontalAlign="center" paddingBottom="10" paddingLeft="10" paddingRight="10"
paddingTop="10" verticalAlign="middle" />
</s:layout>
<s:Label id="actionResult" />
<s:HGroup>
<s:Button click="actionResult.text = 'Button 1 clicked'" label="Button1" />
<s:Button click="actionResult.text = 'Button 2 clicked'" label="Button2" />
</s:HGroup>
</s:Panel>
</s:Panel>
</s:Application>

"scrolling is allowed even after the scrollpolicies are off"

i made both the scrollpolicies (horizontal and vertical scrollpolicy) to "off", but if i scroll the mouse the content was scrolling.
how to avoid this behaviour?
the sample code is
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark" xmlns="*" creationComplete="init()">
<s:HGroup id="hgroup" chromeColor="110011">
<s:Scroller width="300" height="100" horizontalScrollPolicy="off" verticalScrollPolicy="off">
<s:Group >
<s:layout>
<s:VerticalLayout />
</s:layout>
<s:Button label="Button 1" />
<s:Button label="Button 2" />
<s:Button label="Button 3" />
<s:Button label="Button 4" />
<s:Button label="Button 5" />
<s:Button label="Button 6" />
<s:Button label="Button 7" />
</s:Group>
</s:Scroller>
</s:HGroup>
</s:Application>
if you just click the hgroup and scroll,then the contents are scrolling. now i want to aoid this behaviour.please verify and post your suggestions and comments.
please note that i haven't use any builder,i run the code in command prompt only.
please post your answers.
Check if there's some inline code which modified the scrollpolicy
Post your code, maybe it could be useful to look for the error
Yeah Buddy.....you kept off on scroll policies...then better take of the horizontal & vertical scroll policies and keep width="100%".....
<s:Scroller width="100%" height="100%">
orelse use
<s:Scroller horizontalScrollPolicy="auto" verticalScrollPolicy="auto">

Skinning Button Label in Flex 4

I am using a Skin for my buttons in Flex 4. The skinned buttons are displayed correctly.
Now I want the label of the buttons to respond as such:
Font Weight should be Bold when "RollOver" or "MouseOver" over the buttons.
I tried doing it in the mxml below by including the rollOver property to the Label on this button, but it doesnt seem to work.
Am I doing it at the right place, that is in the Skin mxml file? Or should I do it for each button in the Application itself?
Skin Code:
<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Metadata>
<![CDATA[
[HostComponent("spark.components.Button")]
]]>
</fx:Metadata>
<fx:Script>
<![CDATA[
protected function labelDisplay_rollOverHandler(event:MouseEvent):void
{
FontWeight.BOLD;
FontStyle.ITALIC;
}
]]>
</fx:Script>
<s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states>
<s:BitmapImage includeIn="up" source="{getStyle('upSkin')}" width="100%" height="100%"/>
<s:BitmapImage includeIn="over" source="{getStyle('overSkin')}" width="100%" height="100%"/>
<s:BitmapImage includeIn="down" source="{getStyle('downSkin')}" width="100%" height="100%"/>
<s:BitmapImage includeIn="disabled" source="{getStyle('disabledSkin')}" width="100%" height="100%"/>
<s:Label id="labelDisplay" textAlign="right" maxDisplayedLines="1" horizontalCenter="1"
verticalAlign="middle" verticalCenter="1" left="10" right="10" rollOver="labelDisplay_rollOverHandler(event)" />
</s:SparkSkin>
You can do this easily by changing the fontWeight style for the "over" state. You can do this in MXML by specifying the style followed by the state you want that style to be applied to, like so:
<s:Label id="labelDisplay" fontWeight.over="bold" textAlign="right" maxDisplayedLines="1" horizontalCenter="1"
verticalAlign="middle" verticalCenter="1" left="10" right="10" />
Hope that helps.

Resources