Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Adobe AIR Development

Reply
Developer
eugenevk
Posts: 167
Registered: ‎12-17-2010
My Device: Bold 9000
My Carrier: Vodafone
Accepted Solution

Application Menu on SWIPE_DOWN

I want to add an application menu that appears on swipe down. I have searched the forum and found the interesting and helpful example of LWalker (Creating a BlackBerry PlayBook tablet application menu using the BlackBerry Tablet OS SDK for Adobe ...). It works, as long as you don't have any other controls on the stage, at least that's my experience. When there are active controls, like buttons or input fields, you can swipe down the menu, but you can't make it disappear again.

I have an image as background covering the entire stage and I tried to assign the eventListener - to make the menu disappear again (according to the example of LWalker) - to this image, but the app doesn't respond to a click and my assumption is, that it is caused because of the active controls I put on top of the image.

Can anybody help?


Eugene

My PlayBook App: Checklists
Please use plain text.
Developer
pyth
Posts: 462
Registered: ‎01-19-2011
My Device: My Trusty Red Plane
My Carrier: Outer Space

Re: Application Menu on SWIPE_DOWN

having that tutorial is nice, but since i didn't even know about that, and my as3 skills got better, i made my own application menu this way:

 

follow the tutorial BUT with one additional thing: (i didn't read the tut completely, too much to read)

 

create the clickarea:smileyfrustrated:prite to fill the screen, and as soon as it is created, set it visible = false. don't add your eventlistener to your background, but to this clickarea

 

next:

the Tweener class can execute additional functions as soon as the tween ends. So when you show the menu, do this

 

			Tweener.addTween(this, {time:0.3, transition:"linear", y:0});
			_clickArea.visible = true;

 and on swipe out,/click out, do this:

			Tweener.addTween(this, {time:0.3, transition:"linear", y:-FIXHEIGHT, onComplete:
				function():void
				{
					_clickArea.visible = false;
				}			
			});

 

for testing, you can set the color of the clickarea to whatevere you like, opaquebackground = 0xff0000 or sth. when you get the drift, tset the alpha value of that clickarea to 0, so the user can't see it

-----------------------------------------------------------------------
I'm a bird from outer space. But I'm not flappy o.o
Please use plain text.
Developer
eugenevk
Posts: 167
Registered: ‎12-17-2010
My Device: Bold 9000
My Carrier: Vodafone

Re: Application Menu on SWIPE_DOWN

Thanks pyth. It's however not entirely clear to me (because of what's in the example of the 'tutorial' of LWalker): the MenuBar is in a separate class, so also the addTween is in that class. This means the MenuBar class is not aware of _clickArea, which I have defined in my main app, as well as a var of type MenuBar().

The code of the MenuBar() class:

package
{
	import caurina.transitions.Tweener;
	
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	import qnx.ui.buttons.LabelButton;
	
	public class MenuBar extends Sprite
	{
		
		// menu bar properties		
		public static const WIDTH:int = 1024;
		public static const HEIGHT:int = 80;
		public static const VISIBLE_Y:int = 0;
		public static const HIDDEN_Y:int = -HEIGHT;
		public static const SLIDE_TIME:Number = 0.5;
		
		// instance variable to track whether the menu bar is currently active
		private var _active:Boolean;
		
		// constructor
		public function MenuBar()
		{
			initializeUI();
		}
		
		// create the UI
		private function initializeUI():void
		{
			_active = false;
			
			// set default position (hidden)
			this.x = 0;
			this.y = HIDDEN_Y;

			// draw a slightly transparent, grey menu bar
			this.graphics.beginFill(0x222222,0.7);
			this.graphics.drawRect(0,0,WIDTH,HEIGHT);
			this.graphics.endFill();			
			
			// an example button to appear on the menu bar
			// currently, this button does nothing
			// to connect this button to an action, add an event handler
			// for example, egButton.addEventListener(MouseEvent.Click, myEventHandler)
			var egButton:LabelButton = new LabelButton();
			egButton.label = "Example button";
			egButton.height = 64;
			// set the button in 10 pixels from the left, and center it vertically in the menu bar
			egButton.x = 10;
			egButton.y = 6;
			this.addChild(egButton);
		}
		
		// allow other objects to determine whether the menu is visible
		public function isVisible():Boolean
		{
			return _active;
		}
		
		// allow other objects to display the menu bar
		public function show():void
		{
			_active = true;
			Tweener.addTween(this, {y:VISIBLE_Y, time:SLIDE_TIME, transition:"linear"});
			
		}
		
		// allow other objects to hide the menu bar
		public function hide():void
		{
			_active = false;
			Tweener.addTween(this, {y:HIDDEN_Y, time:SLIDE_TIME, transition:"linear"});
		}
		
		/* This handles events passed from the parent app. This way
		* you can "modalize" the menu bar by ignoring clicks outside the
		* bounds of the palette when it's active, or close it, or whatever.
		*/ 
		
		public function processEvent(event:MouseEvent):void
		{	
			// close if the click was below the menu		
			if(event.localY > HEIGHT)
			{
				hide();	
			}	
		}
	}
}

 

Eugene

My PlayBook App: Checklists
Please use plain text.
Developer
pyth
Posts: 462
Registered: ‎01-19-2011
My Device: My Trusty Red Plane
My Carrier: Outer Space

Re: Application Menu on SWIPE_DOWN

it's easier than you think it is, actually. first of all, you need to get the idea of the stage tree, which means, it doesn't matter if the clickarea is part of the stage or the menu, as long as it's on the correct z-position in the tree. that means, if you want to have the clickarea between your screen and the app menu, you can either add it on top of the screen OR below the app menu, as those two positions are completely different ones.

 

what i want to say is: add the clickarea to the app menu. here's the modified code: (didn't test yet

public class MenuBar extends Sprite
	{
		
		// menu bar properties		
		public static const WIDTH:int = 1024;
		public static const HEIGHT:int = 80;
		public static const VISIBLE_Y:int = 0;
		public static const HIDDEN_Y:int = -HEIGHT;
		public static const SLIDE_TIME:Number = 0.5;
		
		// instance variable to track whether the menu bar is currently active
		private var _active:Boolean;

//new areas 
private var top:Sprite;
private var clickarea:Sprite; 


		
		// constructor
		public function MenuBar()
		{
top = new Sprite;
addChild(top);

clickarea = new Sprite;
			clickarea .graphics.beginFill(0x222222,0.7);
			clickarea .graphics.drawRect(0,0,1024,1024);
			clickarea .graphics.endFill();	
addChildAt(clickArea, 0);

			initializeUI();
		}
		
		// create the UI
		private function initializeUI():void
		{
			_active = false;
			
			// set default position (hidden)
			top.x = 0;
			top.y = HIDDEN_Y;

			// draw a slightly transparent, grey menu bar
			top.graphics.beginFill(0x222222,0.7);
			top.graphics.drawRect(0,0,WIDTH,HEIGHT);
			top.graphics.endFill();			
			
			// an example button to appear on the menu bar
			// currently, this button does nothing
			// to connect this button to an action, add an event handler
			// for example, egButton.addEventListener(MouseEvent.Click, myEventHandler)
			var egButton:LabelButton = new LabelButton();
			egButton.label = "Example button";
			egButton.height = 64;
			// set the button in 10 pixels from the left, and center it vertically in the menu bar
			egButton.x = 10;
			egButton.y = 6;
			top.addChild(egButton);
		}
		
	}

 

)

 

 

and the rest as i said in my previous post

 

-----------------------------------------------------------------------
I'm a bird from outer space. But I'm not flappy o.o
Please use plain text.
Developer
eugenevk
Posts: 167
Registered: ‎12-17-2010
My Device: Bold 9000
My Carrier: Vodafone

Re: Application Menu on SWIPE_DOWN

Thanks pyth, but I'm afraid this doesn't work. The partly transparent clickarea is immediately displayed when the app is launched and all controls (lists, buttons, input field) are placed on top of the clickarea. The app also doesn't respond to the swipe down.

 

Eugene

My PlayBook App: Checklists
Please use plain text.
Developer
pyth
Posts: 462
Registered: ‎01-19-2011
My Device: My Trusty Red Plane
My Carrier: Outer Space

Re: Application Menu on SWIPE_DOWN

judging by your answer i guess you don't have much experience with as3, so i'll try to explain it again :/. i'm trying to explain it one by one, if you have a problem with one of the steps, just say so

 

1) you should have your program on your own already, let's call it MainScreen. MainScreen extends Sprite. this is your app, without the menubar, and it works as it is. also, all of your controls, which are not part of the menubar, are here

2) the menubar. you create a new instance of menubar as soon as your mainscreen has been initialized. that menubar is added on top of your MainScreen. The trick is, that (1) the actual visible part of the menubar is on top of the screen, and therefore not visible to the user, and (2), the clickarea is set to visible = false, so that you actuallly CANNOT see that area. anything that's not visible in flash can also not be clicked in any way. also, the alpha value of the clickarea is 0, so the user is unable to see that area in any case

3) the event listener for swiping is added to the stage of the MainScreen. when it is called, the tweening of the menubar INTO the screen starts

4) as soon as the tweening into the screen starts, set the clickarea of the menubar to true, so it reacts to clicks. since the clickarea should be as large as the screen, the user can only either click the clickarea or anything on the menubar. he CANNOT click what's underneath the clickarea

5) the eventlistener for tweening out should be to the clickarea as well. also, as soon as the menubar and the clickarea tween out again, set the clickarea.visible = false, so that the user can click your MainScreen again

 

and that's how the menubar works

-----------------------------------------------------------------------
I'm a bird from outer space. But I'm not flappy o.o
Please use plain text.
Developer
eugenevk
Posts: 167
Registered: ‎12-17-2010
My Device: Bold 9000
My Carrier: Vodafone

Re: Application Menu on SWIPE_DOWN

I am completely with you.

I have changed the MenuBar code to the following, which makes it (almost entirely) work:

 

package
{
	import caurina.transitions.Tweener;
	
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	import qnx.ui.buttons.LabelButton;
	
	public class MenuBar extends Sprite
	{
		
		// menu bar properties		
		public static const WIDTH:int = 1024;
		public static const HEIGHT:int = 80;
		public static const VISIBLE_Y:int = 0;
		public static const HIDDEN_Y:int = -HEIGHT;
		public static const SLIDE_TIME:Number = 0.5;
		
		// instance variable to track whether the menu bar is currently active
		private var _active:Boolean;
		private var _clickArea:Sprite = new Sprite();
		
		// constructor
		public function MenuBar()
		{
			initializeUI();
		}
		
		// create the UI
		private function initializeUI():void
		{
			_active = false;
			
			// set default position (hidden)
			with(this) {
				x = 0;
				y = HIDDEN_Y;
			}
			
			// set default position click area for hiding menu (hidden as well)
			with(_clickArea) {
				x = 0;
				y = -600;
			}

			// draw a slightly transparent, grey menu bar
			with(this) {
				graphics.beginFill(0x222222,0.7);
				graphics.drawRect(0,0,WIDTH,HEIGHT);
				graphics.endFill();
				addEventListener(MouseEvent.CLICK, onClick);
			}
			
			// draw the click area (for hiding the menu bar again)
			with(_clickArea) {
				graphics.beginFill(0x222222,0);
				graphics.drawRect(0,0,WIDTH, 600);
				graphics.endFill();
				addEventListener(MouseEvent.CLICK, onClick);
			}
			
			this.addChild(_clickArea);
			
			// an example button to appear on the menu bar
			// currently, this button does nothing
			// to connect this button to an action, add an event handler
			// for example, egButton.addEventListener(MouseEvent.Click, myEventHandler)
			var egButton:LabelButton = new LabelButton();
			egButton.label = "Example button";
			egButton.height = 64;
			// set the button in 10 pixels from the left, and center it vertically in the menu bar
			egButton.x = 10;
			egButton.y = 6;
			this.addChild(egButton);
		}
		
		// allow other objects to determine whether the menu is visible
		public function isVisible():Boolean
		{
			return _active;
		}
		
		// allow other objects to display the menu bar
		public function show():void
		{
			_active = true;
			Tweener.addTween(this, {y:VISIBLE_Y, time:SLIDE_TIME, transition:"linear"});
			Tweener.addTween(_clickArea, {y:VISIBLE_Y, time:0, transition:"linear"});			
		}
		
		// allow other objects to hide the menu bar
		public function hide():void
		{
			_active = false;
			Tweener.addTween(this, {y:HIDDEN_Y, time:SLIDE_TIME, transition:"linear"});
			Tweener.addTween(_clickArea, {y:-600, time:0, transition:"linear"});
		}
		
		/* This handles events passed from the parent app. This way
		* you can "modalize" the menu bar by ignoring clicks outside the
		* bounds of the palette when it's active, or close it, or whatever.
		*/ 
		
		public function processEvent(event:MouseEvent):void
		{	
			// close if the click was below the menu		
			if(event.localY > HEIGHT)
			{
				hide();	
			}	
		}
		
		public function onClick(event:MouseEvent):void
		{
			hide();
		}
	}
}

 The menu bar appears nicely and the click area as well (transparently). The thing is that the controls that I have on my stage (i.e. lists, buttons and a text input field) are still NOT covered by the click area. They are still on top of the click area, meaning that I can still click on them without the menu disappearing. If I click somewhere else on the screen, the menu bar nicely disappears.

 

The following code does - for some reason that I don't understand - not work (i.e. the click area doesn't appear; the issue with the controls is of course not be solved with this):

 

package
{
	import caurina.transitions.Tweener;
	
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	import qnx.ui.buttons.LabelButton;
	
	public class MenuBar extends Sprite
	{
		
		// menu bar properties		
		public static const WIDTH:int = 1024;
		public static const HEIGHT:int = 80;
		public static const VISIBLE_Y:int = 0;
		public static const HIDDEN_Y:int = -HEIGHT;
		public static const SLIDE_TIME:Number = 0.5;
		
		// instance variable to track whether the menu bar is currently active
		private var _active:Boolean;
		private var _clickArea:Sprite = new Sprite();
		
		// constructor
		public function MenuBar()
		{
			initializeUI();
		}
		
		// create the UI
		private function initializeUI():void
		{
			_active = false;
			
			// set default position (hidden)
			with(this) {
				x = 0;
				y = HIDDEN_Y;
			}
			
			// set default position click area for hiding menu (hidden as well)
			with(_clickArea) {
				x = 0;
				y = -600;
			}

			// draw a slightly transparent, grey menu bar
			with(this) {
				graphics.beginFill(0x222222,0.7);
				graphics.drawRect(0,0,WIDTH,HEIGHT);
				graphics.endFill();
				addEventListener(MouseEvent.CLICK, onClick);
			}
			
			// draw the click area (for hiding the menu bar again)
			with(_clickArea) {
				graphics.beginFill(0x222222,0.7);
				graphics.drawRect(0,0,WIDTH, 600);
				graphics.endFill();
				addEventListener(MouseEvent.CLICK, onClick);
				visible = false;
			}
			
			this.addChild(_clickArea);
			
			// an example button to appear on the menu bar
			// currently, this button does nothing
			// to connect this button to an action, add an event handler
			// for example, egButton.addEventListener(MouseEvent.Click, myEventHandler)
			var egButton:LabelButton = new LabelButton();
			egButton.label = "Example button";
			egButton.height = 64;
			// set the button in 10 pixels from the left, and center it vertically in the menu bar
			egButton.x = 10;
			egButton.y = 6;
			this.addChild(egButton);
		}
		
		// allow other objects to determine whether the menu is visible
		public function isVisible():Boolean
		{
			return _active;
		}
		
		// allow other objects to display the menu bar
		public function show():void
		{
			_active = true;
			Tweener.addTween(this, {y:VISIBLE_Y, time:SLIDE_TIME, transition:"linear"});
			_clickArea.visible = true;
		}
		
		// allow other objects to hide the menu bar
		public function hide():void
		{
			_active = false;
			Tweener.addTween(this, {y:HIDDEN_Y, time:SLIDE_TIME, transition:"linear"});
			_clickArea.visible = false;
		}
		
		/* This handles events passed from the parent app. This way
		* you can "modalize" the menu bar by ignoring clicks outside the
		* bounds of the palette when it's active, or close it, or whatever.
		*/ 
		
		public function processEvent(event:MouseEvent):void
		{	
			// close if the click was below the menu		
			if(event.localY > HEIGHT)
			{
				hide();	
			}	
		}
		
		public function onClick(event:MouseEvent):void
		{
			hide();
		}
	}
}

 

Eugene

My PlayBook App: Checklists
Please use plain text.
Developer
pyth
Posts: 462
Registered: ‎01-19-2011
My Device: My Trusty Red Plane
My Carrier: Outer Space

Re: Application Menu on SWIPE_DOWN

i actually don't have a lot of time, but i took the time to whip you up a quick example of what i meant (especially, when to set what to visible and/or alpha = 0)

 

here you go with the main class: it's a screen with a single button, no more. when you go into debug mode, you get trace-notifications saying 'BAM'. replace this later with your own class, except for the function initAppMenu

 

package 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import qnx.events.QNXApplicationEvent;
	import qnx.system.QNXApplication;
	import qnx.ui.buttons.LabelButton;
	
	// The following metadata specifies the size and properties of the canvas that
	// this application should occupy on the BlackBerry PlayBook screen.
	[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")]
	public class Test extends Sprite
	{	
		public function Test()
		{
			initMe();
			initAppMenu();
		}
		
		private function initMe():void
		{
			var lb:LabelButton = new LabelButton;
			lb.label = "Hit Me!!";
			lb.addEventListener(MouseEvent.CLICK,
				function(e:Event):void
				{
					trace("BAM!");
				}
			);
			lb.setPosition(500,300);
			addChild(lb);
		}
		
		private function initAppMenu():void
		{
			var am:AppMenu = new AppMenu;
			addChild(am);
			
			QNXApplication.qnxApplication.addEventListener(QNXApplicationEvent.SWIPE_DOWN, function(e:QNXApplicationEvent):void
			{	
				am.tweenIn();
			}
			);
		}
	}
}

 

and here's the app menu class, with the clickarea. the appmenu is independent from the rest of your app, therefore i don't even understand why you add your controls to the appmenu and not to the layer below. if you really want to add sth to the app menu, do it above that layer

 

package
{
	import caurina.transitions.Tweener;
	
	import flash.display.GradientType;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	
	public class AppMenu extends Sprite
	{	
		private const WIDTH:int = 1024;
		private const FIXHEIGHT:int = 100;
		private var _clickArea:Sprite;
		private var _settingBackground:Shape;
		
		private var matrix:Matrix = new Matrix();
		
		public function AppMenu()
		{
			super();
			
			_clickArea = new Sprite();
			_clickArea.graphics.beginFill(0xFFFFFF, 0);
			_clickArea.graphics.drawRect(0,0,WIDTH,WIDTH);
			_clickArea.graphics.endFill();
			addChild(_clickArea);
			
			_clickArea.addEventListener(MouseEvent.CLICK, tweenOut);
			_clickArea.visible = false;
			
			matrix.createGradientBox(WIDTH,FIXHEIGHT,90/180*Math.PI);
			
			_settingBackground = new Shape();
			_settingBackground.graphics.beginGradientFill(GradientType.LINEAR,[0x888888,0x666666, 0x444444],[1,1,1],[0,127,255],matrix);
			_settingBackground.graphics.lineStyle(1,0x888888);
			_settingBackground.graphics.drawRect(0,0,WIDTH,FIXHEIGHT);
			_settingBackground.graphics.endFill();
			
			addChild(_settingBackground);
			
			init();
		}
		
		private function init():void
		{
			y = -FIXHEIGHT;
		}
		
		public function tweenIn(e:MouseEvent = null):void
		{
			Tweener.addTween(this, {time:0.3, transition:"linear", y:0});
			_clickArea.visible = true;
		}
		
		public function tweenOut(e:MouseEvent = null):void
		{
			Tweener.addTween(this, {time:0.3, transition:"linear", y:-FIXHEIGHT, onComplete:
				function():void
				{
					_clickArea.visible = false;
				}			
			});
		}
	}
}

 when you swipe in the app menu, you can't click the button without removing the app menu first.

 

there's quite a bit hardcoded though, but that's quicker than thinking. therefore, the thinking part will be your task :smileyhappy:

 

-----------------------------------------------------------------------
I'm a bird from outer space. But I'm not flappy o.o
Please use plain text.
Developer
pyth
Posts: 462
Registered: ‎01-19-2011
My Device: My Trusty Red Plane
My Carrier: Outer Space

Re: Application Menu on SWIPE_DOWN

btw, there's also one other thing i know: if you're using scrollpanes, there's a bug in qnx taht those still scroll even though they are behind other objects (not wanted behaviour). in that case, you must set enabled = false for scrollpanes when they are covered by otehrs. i don't know about textareas etc though
-----------------------------------------------------------------------
I'm a bird from outer space. But I'm not flappy o.o
Please use plain text.
Developer
eugenevk
Posts: 167
Registered: ‎12-17-2010
My Device: Bold 9000
My Carrier: Vodafone

Re: Application Menu on SWIPE_DOWN

Thanks pyth! Appreciate your help. Got it working. You did things here and there a bit differently than in the example and yours works better. Indeed scrolling lists can still be scrolled, but that's to me a minor thing. At least now the other controls (the buttons and input fields) are now not enabled when the menu is pulled down (I actually didn't move them anywhere, so the fact that they could still be used when I used the menu of the other example shows the error was in the menu implementation, not in how I built up the stage).

Anyway, it works now, thanks again a lot!

Eugene

My PlayBook App: Checklists
Please use plain text.