Draggable Drawer Adobe Flex Mobile - apache-flex

Could someone please assist me with a way to create a drag-able drawer that resides on the bottom of my mobile application? I am wanting to make it so there is a drag handle that is visible all the time (can be an image or whatever) and then allow you to slide the contents into view and slide them back out of view at the bottom of the screen. I am needing a direction to start in, I should be able to figure it out once I have that.

I originally had the sliding initiated on mouse down/move/up events, but have since changed it out for a tap affect (which also occurs when you slide up/down) on the handle image at the top of the dock, since I changed it this afternoon I haven't had a chance to clean it up yet but this is the start:
Drawer:
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" maxHeight="125" minHeight="30" height="30"
xmlns:s="library://ns.adobe.com/flex/spark">
<fx:Script>
<![CDATA[
private var dragging:Boolean = false;
protected function resize():void{
var h:int = this.height;
var i:int = 0;
if (h !== 125){
for(i=h;i<=125;i++){
this.height = i;
};
currentState='up';
return;
}else{
}
if(h >= 30){
for(i=h;i>=30;i--){
this.height = i;
};
currentState='down';
return;
}
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<s:states>
<s:State name="down"/>
<s:State name="up"/>
</s:states>
<s:Rect width="100%" height="100%" top="30">
<s:fill>
<s:SolidColor color="#333333"/>
</s:fill>
</s:Rect>
<s:Image scaleMode="zoom" source.down="#Embed('Images/down.png')" source.up="#Embed('Images/up.png')" mouseDown="resize()"/>
<s:HGroup width="100%" horizontalAlign="center" verticalAlign="bottom" top="30" gap="30">
<!--Buttons here-->
</s:HGroup>
</s:Group>

Related

How to make a component draggable from any part except a Scroller inside the component

I have and Flex component that inside has a profundidad component that has a Scroller on a DataGroup
The component can be draged fine, but when I try to drag the scroll bar is dragging the whole component instead of dragging the scroll bar itself
How can I make the component to be draggable from any other part besides the scroll bar and make the drag on the scroll bar to behave as expected (show more info above or below)
?
The code for the main component is
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:c="Components.ComponentsMulticuenta.*"
xmlns:c1="Components.*"
xmlns:Front="Components.Front.*"
mouseDown="initialPosition(event)" mouseUp="finalPosition(event)"
width="250" height.Start="94">
private var isDragging:Boolean ;
protected function initialPosition(event:MouseEvent):void
{
isDragging = false ;
if(event.localY <= 94)
{
this.startDrag();
isDragging = true ;
}
}
protected function finalPosition(event:MouseEvent):void
{
if(isDragging)
{
this.stopDrag();
isDragging = false ;
}
}
<s:states>
<s:State name="Start"/>
<s:State name="stateDown"/>
</s:states>
<s:BorderContainer borderStyle="solid"
top="0" width="100%" height="94" height.stateDown="210"
borderColor="#4F5548" horizontalCenter="0">
<mx:Canvas id="fondo" width="100%" height="100%">
<c:profundidad includeIn="stateDown" id="prof" left="0" right="0" top="90" arrProff="{MarketInfoArray}"/>
</mx:Canvas>
</s:BorderContainer>
</s:Group>
The code for the profundidad component is
<mx:Canvas xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="248" height="100%">
<s:BorderContainer width="100%" height="100%" >
<s:Scroller id="scroll" left="0" right="0" top="32" bottom="0" focusEnabled="false" hasFocusableChildren="true" >
<s:DataGroup left="0" right="0" top="0" bottom="0" dataProvider="{arrProff}"
itemRenderer="Components.ComponentsMulticuenta.DepthRender">
<s:layout>
<s:VerticalLayout gap="1"/>
</s:layout>
</s:DataGroup>
</s:Scroller>
</s:BorderContainer>
</mx:Canvas>
To avoid the drag from the "close" button and also from the scroll bar, which in flex has the id thumb (for SliderThumb)
This is what I did
protected function initialPosition(event:MouseEvent):void
{
isDragging = false ;
if( event.target.hasOwnProperty("id") && (event.target.id != "close") && (event.target.id != "thumb"))
{
this.startDrag();
isDragging = true ;
parentApplication.showNemo(this) ;
}
}

slightly weird question about ordering layers

I was wondering if there is a way to have an object A (e.g. a Rect) visually appear behind an object B (e.g. another Rect) but in front of it from a mouse rollover standpoint. In other words, if you move the mouse tip over the intersection of A and B, A rolls over instead of B.
If this doesn't exist out of the box I'm curious how you would implement something like this.
thank you
Maybe this sample suits your need?
<?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">
<fx:Script>
<![CDATA[
private function putBlueRectInFront():void
{
blueRect.depth = 1;
redRect.depth = 0;
}
private function putRedRectInFront():void
{
redRect.depth = 1;
blueRect.depth = 0;
}
protected function rectContainer_rollOutHandler(event:MouseEvent):void
{
rectContainer.removeEventListener(MouseEvent.MOUSE_MOVE, rectContainer_mouseMoveHandler);
putBlueRectInFront();
}
protected function rectContainer_rollOverHandler(event:MouseEvent):void
{
rectContainer.addEventListener(MouseEvent.MOUSE_MOVE, rectContainer_mouseMoveHandler);
}
private function rectContainer_mouseMoveHandler(event:MouseEvent):void
{
if (event.localX <= redRect.width && event.localY <= redRect.height)
putRedRectInFront();
else
putBlueRectInFront();
}
]]>
</fx:Script>
<s:BorderContainer height="400" horizontalCenter="0" id="rectContainer"
rollOut="rectContainer_rollOutHandler(event)" rollOver="rectContainer_rollOverHandler(event)" verticalCenter="0"
width="400">
<s:borderStroke>
<s:SolidColorStroke color="black" weight="1" />
</s:borderStroke>
<s:Rect height="250" id="redRect" left="0" top="0" width="250">
<s:fill>
<s:SolidColor color="red" />
</s:fill>
</s:Rect>
<s:Rect bottom="0" height="250" id="blueRect" right="0" width="250">
<s:fill>
<s:SolidColor color="blue" />
</s:fill>
</s:Rect>
</s:BorderContainer>
</s:Application>
I don't think this works intrinsically.
To make ObjectA appear behind ObjectB, you just have to add ObjectA to the container before ObjectB. Flex handles the "Z-Order" based on the order items were added to the container.
I'd implement the Z-Order change using using swapChildren and mouse events. Possibly mouseOver to move ObjectA on top and then mouseOut to move ObjectA to the back.
If you have a more complicated structure with more than two classes, you can use swapChildrenAt.

Flex first window width/bound gets ignored

I have a window in which I want to add/remove component and resize the window accordingly based on states. but for some reason it's ignoring the first resize.
here's a sample code
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="450"
minHeight="355"
currentState="{stateBox.selected ? 'one' : 'two'}"
currentStateChange="handleStateChange(event.oldState, event.newState)">
<fx:Script>
<![CDATA[
private function handleStateChange(oldState:String, newState:String):void
{
if (oldState == "two") {
width -= 341;
minWidth = 450;
} else {
width += 341;
minWidth = 791;
}
}
]]>
</fx:Script>
<s:states>
<s:State name="one" />
<s:State name="two" />
</s:states>
<s:Rect id="rect1" top="0" left="0" right="0" right.two="341" bottom="0" >
<s:fill>
<s:SolidColor color="0xDDDDDD" />
</s:fill>
</s:Rect>
<s:Rect id="rect2" top="0" bottom="0" width="341" right="0" includeIn="two" >
<s:fill>
<s:SolidColor color="0x000000" />
</s:fill>
</s:Rect>
<s:CheckBox id="stateBox" label="change state" />
</s:WindowedApplication>
Idea is that when the state change to 'two', I want to add rect2 to display and increase the minWidth and size of the window. And when the state change to 'one', i want to remove rect2 from display and resize the window. This seems to work except the window doesn't shrink on the very first time the state change from "two" to "one" but works as expected afterwards. I'm not sure why it's ignoring first time I reduce the width. I also tried changing nativeWindow.bounds directly but that didn't work either.
Originally I just tried setting minWidth based on state (minWidth.one="450 minWidth.two="791") but that caused window to grow on left and shrink on right which caused the window to move left whenever the state changed. so then I just moved the window to right whenever state changed but that caused some flicker that I didn't want.
does anyone have any idea why this might be happening? or a good solution for my problem?
Try flipping these lines around from:
width -= 341;
minWidth = 450;
to:
minWidth = 450;
width -= 341;
I think the problem is with the way that condition is setup in general.... I'm going to copy your code and modify it how I would go about doing this and repost as an edit, but you could try the above suggestion (I believe you may be setting the width lower than the minimum width then reducing the minWidth so the setting of the width in the first place would have been set to a width that isn't valid according to the current minWidth, think you may only see this the first time around due to timing with validation.
EDIT(ed twice, add locking the window size by setting min and max heights equal to the set height):
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minHeight="355"
maxHeight="355"
minWidth="450"
width.two="791"
width.one="450"
minWidth.one="450"
minWidth.two="791"
maxWidth.one="450"
maxWidth.two="791">
<fx:Script>
<![CDATA[
protected function stateBox_changeHandler(event:Event):void
{
// TODO Auto-generated method stub
currentState=stateBox.selected ? 'two' : 'one';
}
]]>
</fx:Script>
<s:states>
<s:State name="one"/>
<s:State name="two"/>
</s:states>
<s:HGroup width="100%"
height="100%"
gap="0">
<s:Rect width="450"
height="100%">
<s:fill>
<s:SolidColor color="0xff0000"/>
</s:fill>
</s:Rect>
<s:Rect width="341"
height="100%"
includeIn="two">
<s:fill>
<s:SolidColor color="0x000000"/>
</s:fill>
</s:Rect>
</s:HGroup>
<s:CheckBox id="stateBox"
label="change state"
change="stateBox_changeHandler(event)"/>
</s:WindowedApplication>
Does this achieve the desired behavior ^ (sorry I know I changed a lot of code but this is just how I would approach it, maybe this won't work because of other explicit sizing you need to set but seems to achieve the goal to me)

Wrong target when clicking on a <s:Group> with a Mask in Flex 4

I am having trouble handling a MouseEvent.MOUSE_DOWN on an component with a Image for a mask in Flex 4.
I have an application as follows:
<?xml version="1.0"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="init()"
>
<fx:Script>
<![CDATA[
import spark.core.MaskType;
public function init():void {
manager.addEventListener( MouseEvent.MOUSE_DOWN, handleMouseDown );
}
public function handleMouseDown(e:MouseEvent):void {
trace( e.target )
}
]]>
</fx:Script>
<s:Group id="manager" width="500" height="500">
<s:Group id="layer" mouseChildren="false" x="220">
<s:Group id="content" maskType="{MaskType.ALPHA}" cacheAsBitmap="true">
<s:Rect width="338" height="162">
<s:fill>
<s:SolidColor color="0xDDAAAA" />
</s:fill>
</s:Rect>
<s:mask>
<s:Group>
<mx:Image
source="http://www.wpclipart.com/signs_symbol/alphabets_numbers/3D_text_T.png"
cacheAsBitmap="true"
/>
</s:Group>
</s:mask>
</s:Group>
</s:Group>
</s:Group>
</s:Application>
If you run this, you will notice that if you click on the left side of the image (on the "3"), the trace correctly indicates that "layer" got clicked. However, if you click on the right side of the image (on the "D") you'll see that "manager" got clicked instead of "layer", which is wrong. If you click anywhere on the "layer" that is past 338px (the mask size), the mouse event does not seem to make it to the layer object.
If I remove the "x" offset on "layer", the whole layer works as expected, but as soon as I offset, anything past the width of the mask (338px) seems to not be captured properly, like if the mask wasn't offset. The strange thing is that if you click to the left of the image once it has been offset, you do get "manager", which means that the layer (and mask) did get moved.
Here's what I mean, with no offset, clicking on the green area returns "layer", clicking on the blue area returns "manager", which is the expected behaviour. See image
If I offset the layer by 220, the areas behave like this image
Sorry I can't embed the images here, but I don't have enough reputation :(
Figured it out.
Apparently the problem is that the Image that is used as the mask needs to be added to the display list before it gets set as the mask or this erratic behaviour happens. This is what the code looks like now and it's working:
<?xml version="1.0"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
creationComplete="init()"
>
<fx:Script>
<![CDATA[
import spark.core.MaskType;
public function init():void {
manager.addEventListener( MouseEvent.MOUSE_DOWN, handleMouseDown );
}
public function handleMouseDown(e:MouseEvent):void {
trace( e.target.id )
}
]]>
</fx:Script>
<s:Group id="manager" width="500" height="500">
<s:Group id="layer" mouseChildren="false" x="100" mouseEnabledWhereTransparent="false">
<s:Group id="content" mask="{maskImage}" maskType="{MaskType.ALPHA}" cacheAsBitmap="true">
<s:Rect width="338" height="162">
<s:fill>
<s:SolidColor color="0xDDAAAA" />
</s:fill>
</s:Rect>
</s:Group>
<mx:Image id="maskImage"
source="http://www.wpclipart.com/signs_symbol/alphabets_numbers/3D_text_T.png"
cacheAsBitmap="true"
/>
</s:Group>
</s:Group>
</s:Application>
Also of note is that the maskImage is a child of layer and not a child of content. Setting it as a child of the latter results in the same incorrect behaviour as before.

Frustrated Animation Issue

I have spent 2 hours on this simple state to state transition with simply resize and move animation.... I can get the element to move and fade...but there is no resize animation at all. The panel element stay the same width whole time. If I copy the code to a brand new test mxml file, it works, but not in my main application file...I was wondering if someone here can help me out. Thanks a lot.
//This is a custom component inside the main application...Not sure if it relates to my issue.....
<mx:Canvas xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" width="1000" height="600" xmlns:getcomplist="services.getcomplist.*" xmlns:components="components.*"
currentState="defaultState">
<fx:Script>
<![CDATA[
protected function compList_changeHandler(event:IndexChangeEvent):void
{
currentState="whenClick";
}
]]>
</fx:Script>
<mx:states>
<s:State name="defaultState"/>
<s:State name="whenClick" />
</mx:states>
<mx:transitions>
<s:Transition toState="whenClick">
<s:Parallel target="{animationIsAnnoying}">
<!--<s:Fade duration="1000"/>--> // Fade is working fine...
<s:Resize heightFrom="600" duration="5000" /> //resize is not working
<s:Move xFrom="500" duration="5000" /> //Move is working fine
</s:Parallel>
</s:Transition>
</mx:transitions>
<s:HGroup>
<s:List id="compList"
width="280"
height="500"
change="compList_changeHandler(event)">
</s:List>
<s:Panel id="animationIsAnnoying" height="150" includeIn="whenClick" /> //The panel I want to animated...
<components:compDisplayDetail includeIn="whenClick" id="compDisplay" width="600" height="500" userPic="{userPicResult.lastResult}" dataFromClick ="{compDetailinfoResult.lastResult}" />
</s:HGroup>
</mx:Canvas>
You must have a click event to command the resize component
im using here mx:Resize component
<mx:Resize id="resizeThis" target="{toolBoxContainer}"/>
<mx:VBox id="toolBoxContainer" height="200" width="300" >
<mx:Textid="txt" text="HELLO"/>
</mx:VBox>
<mx:Button id="menuImage"toolTip="Show/Hidden Menu" click="menuClickHandler(event)" toggle="true"/>
<mx:Script>
<![CDATA[
private var toggle:int =1;
private function menuClickHandler(e:MouseEvent):void {
if(toggle == 0 ) {
//MoveThis.end();
resizeThis.widthFrom = 0
resizeThis.widthTo = 46;
resizeThis.play();
}
if(toggle == 1) {
resizeThis.end();
resizeThis.widthFrom = 46
resizeThis.widthTo = 0;
resizeThis.play();
}
if(toggle == 0) toggle = 1;
else toggle = 0;
}
]]>
</mx:Script>
This thing has errors in imports or the likes.. but i assume you got my point..

Resources