AS3 Flex Scroller - Hide when not scrolling - actionscript-3

I'm trying to figure out how to make a Flex Scroller not be offset and to be hidden when the user is not scrolling. Basically, I'd like for the Scrollbar to appear and be overlapping the content when the user is scrolling and to then disappear or fade out when the user has stopped scrolling.
However, I've been unable to find any information online or any similar implementation on how to actually go about doing this. I'd appreciate it if someone could point me in the right direction.

Create a custom skinclass, inside that skin you add the following states:
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
<s:State name="inactive" />
</s:states>
Once that is done, you have two buttons: TRACK and THUMB. Add this:
<!--- The default skin class is VScrollBarTrackSkin.
#copy spark.components.supportClasses.TrackBase#track
#see spark.skins.spark.VScrollBarTrackSkin -->
<s:Button id="track" top="0" bottom="0" height="54"
focusEnabled="false"
skinClass="com.happymetrix.client.mobile.components.uiLegacy.scroller.dark.DarkVScrollerTrackSkin"/>
<!--- The default skin class is VScrollBarThumbSkin.
#copy spark.components.supportClasses.TrackBase#thumb
#see spark.skins.spark.VScrollBarThumbSkin -->
<s:Button id="thumb"
focusEnabled="false" visible.inactive="false"
skinClass="com.happymetrix.client.mobile.components.uiLegacy.scroller.dark.DarkVScrollerThumbSkin" />
visible.inactive = "false"; Just try to play a bit with the custom skinclasses.

Related

Flex id contentGroup query

iam learning Flex and practising skins. So, i just had one doubt:
I have written one custom skin named : ApplicationContainerSkin.mxml
<?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">
<s:states>
<s:State name="normal" />
<s:State name="disabled" />
</s:states>
<fx:Metadata>
[HostComponent("spark.components.Application")]
</fx:Metadata>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:Group horizontalCenter="0" verticalCenter="0">
<s:Rect left="0" right="0" top="0" bottom="0"
radiusX="10" radiusY="10">
<s:fill>
<s:SolidColor color="#CCCCCC" />
</s:fill>
</s:Rect>
<s:Group id="contentGroup"
left="30" right="30" top="30" bottom="30">
</s:Group>
</s:Group>
</s:SparkSkin>
My Doubt:
When I removed s:Group id="contentGroup" , iam unable to see any content inside my application, so why is this 'contentGroup' id necessary?
where this id predefinedly specified.? sorry if its a noob query, but iam eager to knew it.I even tried to check the source code, but I didnt found it, Could anyone tell me where it specified and how does my content render only after using this contentGroup id...? ( I mean, how it internally works? )
Awaiting your responses!
Skinnable Spark components specify "skin parts," identified by the id.
The Application component, which you are skinning, defines 2 skin parts - contentGroup and controlBarGroup, as you can see in the documentation here: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/components/Application.html#SkinPartSummary
The Application class uses the contentGroup skin part (if it has been added in the skin) to lay out the content. Skin parts can either be required or not. The contentGroup part is not required, and therefore when you left it out, the content just did not display.

Flex: Content not Rendering Correctly After Transitioned State Change

I have a component with 2 states and I have added transitions for switching between the states, where 2 Move affects are applied to 2 different objects. This all works fine, however, after the transition from the first state to the second has completed the second state doesn not render correctly. It contains a TextInput control which is not visible, and a Button with a custom skin that is only sometimes visible and vanishes if you click on it. I have tried called invalidateDisplayList() and validateNow() after loading the second state but that has done nothing. I also have a VBox with a cornerRadius property set, strangely this does not seem to apply anymore and the corners are square, where they displayed correctly before I added the transition in. Does anyone have any ideas?
Thank you!
Here is the code for my states and their transitions:
<!-- different states of this component -->
<mx:states>
<s:State name="useForFree"
enterState="renderState()"/>
<s:State name="enterLicence"
enterState="renderState()"/>
</mx:states>
<!-- transitions between different states -->
<mx:transitions>
<!-- transition from useForFree to enterLicence state -->
<s:Transition id="toEnterLicence"
fromState="useForFree"
toState="enterLicence">
<s:Parallel id="p1"
targets="{[freeBtn, _enterLicenceMask]}">
<s:Move yFrom="250"
yTo="0"
duration="500"
targets="{[freeBtn]}"/>
<s:Move yFrom="289"
yTo="39"
duration="500"
targets="{[_enterLicenceMask]}"/>
</s:Parallel>
</s:Transition>
<!-- transition from enterLicence to useForFree state -->
<s:Transition id="toUseForFree"
fromState="enterLicence"
toState="useForFree">
<s:Parallel id="p2"
targets="{[enterLicenceBtn, _useForFreeMask]}">
<s:Move yFrom="0"
yTo="240"
duration="500"
targets="{[enterLicenceBtn]}"/>
<s:Move yFrom="-250"
yTo="0"
duration="500"
targets="{[_useForFreeMask]}"/>
</s:Parallel>
</s:Transition>
</mx:transitions>
and here is the code for my layout:
<mx:Canvas id="freeStateCanvas"
width="100%">
<mx:VBox width="100%"
horizontalAlign="center"
top="0"
mask="{_useForFreeMask}">
<mx:VBox id="freeBox"
includeIn="useForFree">
<s:Label text="some text"/>
<s:Spacer height="20"/>
<s:Image source="image path"/>
<s:Spacer height="20"/>
<mx:Button id="connectBtn"/>
<s:Spacer height="10"/>
<mx:HBox >
<s:Label text="some text"/>/>
</mx:HBox>
</mx:VBox>
<s:Label text="some text"
includeIn="useForFree"/>
</mx:VBox>
<mx:Button id="enterLicenceBtn"
includeIn="useForFree"/>
</mx:Canvas>
<!-- enter licence state -->
<mx:Canvas id="enterLicenceStateCanvas"
width="100%">
<mx:VBox id="enterLicenceBox"
mask="{_enterLicenceMask}"
includeIn="enterLicence">
<s:Label text="some text"/>
<s:Spacer height="20"/>
<s:TextInput id="licenceInput"
width="200"
height="30"/>
<s:Spacer height="20"/>
<mx:Button id="registerBtn"/>
<s:Spacer height="10"/>
<mx:HBox>
<s:Label text="some text"/>
<s:Label text="some more text"/>
</mx:HBox>
</mx:VBox>
<mx:Button id="freeBtn"
includeIn="enterLicence"/>
</mx:Canvas>
where the variables being set as masks are UIComponent instances where I have used their graphics property to draw a rectangle.
Okay, so I found what the problem was, but thanks for trying to help shaunhusain.
In my code you can see I have 2 VBox containers called "freeBox" and "enterLicenceBox" and these actually had a white background and rounded corners, and a DropShadowFilter applied to them (I removed these properties when putting up the code as I felt they were irrelevant, that was a mistake).
This DropShadowFilter was the cause of all my problems and on removing it, the transitions worked fine and all content was rendered correctly. I assume this is just a strange Flex bug, and I didn't find a workaround, I just used images as the box backgrounds for a quick fix.

anchor flex component at the bottom of the screen in normal mode and full screen mode

i am a beginner in action script / flex framework and i am facing a problem :
i would like to have like a menu bar always anchor the bottom of the screen in normal and full screen mode ...
i try to set my component with bottom = "1" (so it should alway be at 1 pixel from the bottom of the stage ... But .. NO :)
here my flex xlm :
<mx:Canvas>
<mx:UIComponent id="isoHostContainer" x="0" y="0" />
<mx:HBox id="_menu_hbox" bottom="1" backgroundColor="0Xff0000" borderStyle="solid" borderVisible="true" >
<mx:Button label="Zoom +" click="button1_zoom_increase_clickHandler(event)" labelPlacement="bottom" />
<mx:Button label="Solid Red" click="{box1.fill = new SolidColorFill(0xFF2222, 1);}" labelPlacement="bottom"/>
<mx:Button label="Transparent" click="{box1.fill = new SolidColorFill(0xFF2222, 0.2);}" labelPlacement="bottom" />
<mx:Button label="Fullscreen toogle" click="button_fullscreen_clickHandler(event)"/>
<mx:Button label="Zoom -" click="button2_zoom_decrease_clickHandler(event)" labelPlacement="bottom"/>
</mx:HBox>
</mx:Canvas>
if you have the answer it will be great!
Thank you!
I think the problem is your menu is anchored 1-pixel from the bottom of your Canvas, which is retaining the same height..width after you go to full screen.
Try setting your Canvas height=100%.
<mx:Canvas height="100%">
<!-- more code below -->
This will force the layout engine to resize the canvas when when the application is redrawn full-screen, and in turn, your menu should remain 1-pixel from the bottom.
Caveat: If your Canvas is nested in another fixed-width container, its parent will also need to dynamically resize for this to work.

Horizontal Layout: mx vs spark - Resizing children

In Flex 3, I used to be able to take 2 panels, lay them out with 100% width settings in an HBox. If I changed the width property of the first panel to something smaller, let's say 20%, the second would automatically update and fill in the space that used to be taken up by the first as the first resized down.
I notice in spark, this doesn't happen. I have an app with a HorizontalLayout, and a resizable panel control on the left and a panel on the right that has width="100%." When I resize my left-side panel down, the right side panel doesn't do anything. So I end up with a clean resizable panel, a bunch of wasted space, and my right-side panel just sitting there.
What I expect is that since the right-side panel has a width="100%" then if the panel to its left is resized, then there would be a corresponding growth in the right-side panel to fill in.
I've tried to manually trigger validation on properties and size without effect. I'm wondering what changed in the HorizontalLayout that no longer allows this technique to work. I would also like to know what solutions are available?
Here's some chomp chomp:
<mx:Application>
<mx:Script>
<![CDATA[
protected function resizeClick(event:MouseEvent):void
{
pnl1.percentWidth = 10; // When this would execute, pnl2 would automatically
// fill in the space previously held by pnl1.
}
]]>
</mx:Script>
<mx:HBox width="100%" height="100%">
<mx:Panel id="pnl1" width="40%" height="100%"> // Uses 40%
<mx:Button id="resizeButton" click="resizeClick(event)"/>
</mx:Panel>
<mx:Panel id="pnl2" width="100%" height="100%"/> // Fills in the rest of the available space
</mx:HBox>
</mx:Application>
Flex 4.5 doesn't automatically update the size of pnl2 when the size of pnl1 changes. I would think that since a HorizontalLayout is being used, that both children would update when the width of one of them was changed. But that just doesn't seem to be the case. I know I can create two states to accomplish this, but I was thinking that I shouldn't have to for something so trivial.
This sample works fine and illustrates correct changes of sizes:
<?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">
<s:VGroup height="100%" width="100%">
<s:HSlider change="firstPanel.percentWidth = event.currentTarget.value" maximum="100" minimum="0"
value="{firstPanel.percentWidth}" />
<s:HGroup height="100%" width="100%">
<s:Panel height="100%" id="firstPanel" minWidth="0" width="40%" />
<s:Panel height="100%" width="100%" />
</s:HGroup>
</s:VGroup>
</s:Application>
So this is how I eventually solved this problem. I should have been a little more specific in my post to explain that Panel 1 is actually a "collapsible" panel that modifies its own size whenever its header button is clicked. The example above does work, but since there is no numeric control on the view to "tell" the panel.percentWidth property how much to change, I set my collapsible panel up to dispatch custom events that are handled by the wrapper. The custom events basically indicate what is happening to the collapsible panel. From there, I can handle the events separately and then control the size of Panel 2.
The solution is actually rather simple and I was hoping for something a little more "behind the scenes" but this worked fine.
<s:Application initialize="initApp(event)">
<fx:Script>
<![CDATA[
protected function initApp(event:FlexEvent):void
{
this.addEventListener("PanelCollapse", panelHandler);
this.addEventListener("PanelNormal", panelHandler);
}
protected function panelHandler(event:Event):void
{
switch(event.type)
{
case "PanelCollapse":
pnl2.percentWidth = 100;
break;
case "PanelNormal":
pnl2.percentWidth = 60;
break;
}
}
]]>
</fx:Script>
<comp:CollapsiblePanel id="pnl1" width="40%" height="100%">
</mx:Panel>
<s:Panel id="pnl2" width="100%" height="100%"/> // Fills in the rest of the available space
</s:Application>

swap graphic objects inside a spark ItemRenderer

I'm writing a s:ItemRenderer to render some simple graphical components in my app. Each element can have multiple shapes that can be selected by the user, i.e. a certain element can be a square, or a circle, or a star, or whatever else.
The simplest way I could think for doing this was to include all possible shapes in a s:Group and then manage their visible tag depending on what shape the user has selected. Is there a better way to do that?
Also, if I encapsulate the group in a separate MXML component, how do I propagate the state of the itemRenderer (say "hovered") down to the MXML component that manages the shapes?
thank you!
f
Edited: here's a code snippet to better explain the situation. Let's say you want to display three types of objects alternatively - the IR below with an AS snippet that turns visible to false for 2 out of the 3 objects definitely does the trick, but seems so ugly to me. In the mean time I found setCurrentState(stateName:String, playTransition:Boolean=true) to propagate the state down, so that's solved.
<s:ItemRenderer>
<s:states>
<s:State name="normal" />
<s:State name="hovered" />
</s:states>
<s:Group width="100%">
<s:Rect width="20" height="10" radiusX="3" radiusY="3">
<s:stroke>
<s:SolidColorStroke color="Black" weight="1" pixelHinting="true"/>
</s:stroke>
<s:fill>
<s:SolidColor color="red" />
</s:fill>
</s:Rect>
<s:Rect id="square" width="10" height="10" radiusX="3" radiusY="3">
<s:stroke>
<s:SolidColorStroke color="Black" weight="1" pixelHinting="true"/>
</s:stroke>
<s:fill>
<s:SolidColor color="green"/>
</s:fill>
</s:Rect>
<s:Ellipse id="circle" visible="true" width="10" height="10">
<s:stroke>
<s:SolidColorStroke color="Black" pixelHinting="true" weight="1"/>
</s:stroke>
<s:fill>
<s:SolidColor color.normal="yellow" color.hovered="0xCEDBEF"/>
</s:fill>
</s:Ellipse>
</s:Group>
The simplest way I could think for
doing this was to include all possible
shapes in a s:Group and then manage
their visible tag depending on what
shape the user has selected. Is there
a better way to do that?
Yes. Item renderers need to be made as light weight as possible. Using the includeInLayout would be a bit better since it will only add what you need to the display list.
Also, if I encapsulate the group in a
separate MXML component, how do I
propagate the state of the
itemRenderer (say "hovered") down to
the MXML component that manages the
shapes?
I'm not quite sure I understand the question. Item renderer are data driven, so their instances have no reliable state. Renderer instances may display any given data item at any given time. Any information passed to an item renderer should be passed down through it's data item or you will run into syncing errors in your display.