If you create a popup via:
PopUpManager.addPopUp( popup, this, false );
PopUpManager.bringToFront( popup );
It will create a popup and bring it on top of any other visual piece. I have one problem though. This 'popup' needs to stay up even when the user interacts with the background.
I would use modal, but I need the ability to interact with the back. Any way to tell the popup manager not to remove the popup when the user clicks off of it?
Thanks!
here's a helper class which would help you (tested only in Flex 4, but probably could be changed for Flex 3 too):
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.MouseEvent;
import mx.core.mx_internal;
import mx.managers.ISystemManager;
import mx.managers.systemClasses.ActiveWindowManager;
use namespace mx_internal;
public class PopupHelper
{
private var popup : DisplayObject;
private var systemManager : ISystemManager;
public function PopupHelper(popup : DisplayObject, systemManager : ISystemManager) : void
{
this.popup = popup;
this.systemManager = systemManager;
}
public function forceToFront() : void
{
systemManager.addEventListener(MouseEvent.MOUSE_DOWN, onSystemMouseDown);
popup.addEventListener(Event.REMOVED_FROM_STAGE, onPopupRemoved)
}
private function onSystemMouseDown(e : MouseEvent) : void
{
bringToFront(popup);
}
private function onPopupRemoved(e : Event) : void
{
popup.removeEventListener(Event.REMOVED, onPopupRemoved);
systemManager.removeEventListener(MouseEvent.MOUSE_DOWN, onSystemMouseDown);
}
private function bringToFront(popup : DisplayObject) : void
{
var windowManager : ActiveWindowManager = systemManager.getImplementation("mx.managers::IActiveWindowManager") as ActiveWindowManager;
var index : int = systemManager.getChildIndex(popup);
var newIndex : int = index;
var n : int = windowManager.forms.length;
for (var j : int = 0; j < n; j++)
{
var f : DisplayObject = windowManager.forms[j];
if (systemManager.contains(f))
if (systemManager.getChildIndex(f) > index)
newIndex = Math.max(systemManager.getChildIndex(f), newIndex);
}
if (newIndex > index)
{
systemManager.setChildIndex(popup, newIndex);
}
}
}
Here's a test example:
import helperClasses.PopupHelper;
import mx.managers.PopUpManager;
import spark.components.TitleWindow;
public function showPopup() : void
{
var popup1 : TitleWindow = new TitleWindow();
popup1.title = "Popup 1";
new PopupHelper(popup1, systemManager).forceToFront();
var popup2 : TitleWindow = new TitleWindow();
popup2.title = "Popup 2";
PopUpManager.addPopUp(popup1, this, false);
PopUpManager.addPopUp(popup2, this, false);
PopUpManager.bringToFront(popup1);
popup1.x = 20;
popup1.y = 20;
}
Related
I have the following code in the Game.as:
package
{
import flash.display.Bitmap;
import starling.display.Image;
import starling.display.Sprite;
import starling.events.Event;
import starling.textures.Texture;
import starling.utils.deg2rad;
public class Game extends Sprite
{
private const NUM_SAUSAGES: uint = 400;
private var sausagesVector: Vector.<Image> = new Vector.<Image>(NUM_SAUSAGES, true);
[Embed(source = "../media/textures/sausage.png")]
private static const Sausage: Class;
public function Game()
{
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded(e: Event): void
{
var sausageBitmap: Bitmap = new Sausage();
var texture: Texture = Texture.fromBitmap(sausageBitmap);
for (var i: int = 0; i < NUM_SAUSAGES; ++i)
{
var image: Image = new Image(texture);
image.alpha = Math.random();
image.x = Math.random() * stage.stageWidth;
image.y = Math.random() * stage.stageHeight;
image.rotation = deg2rad(Math.random() * 360);
addChild(image);
sausagesVector[i] = image;
}
}
}
}
But when I run the code it gives me the following error:
ReferenceError: Error #1065: Variable Game_Sausage is not defined.
What is the problem with the code because I have no idea?
I don't know the notation but I would hazard a guess that:
private static const Sausage: Class;
is never assigned, but defined as const. The [Embed] might not be finding the file?
a quick google found:
http://www.flexer.info/2009/05/01/getdefinitionbyname-error-variable-is-not-defined/
which might or might not be relevant
I have been digging for custom Flex preloaders and they all seem to rely on the same template:An SWC is created with Flash CS5 and then used by Flash Builder using the "preloader" application property.
I don't own Flash CS, and it feels that Flash builder should be able to do the trick.
I created a Library Project in Flash Builder with the following bare bones code:
package loader
{
import flash.display.DisplayObject;
import flash.events.Event;
import flash.utils.getTimer;
import mx.events.RSLEvent;
import mx.preloaders.DownloadProgressBar;
import mx.preloaders.SparkDownloadProgressBar;
public class Preloader extends SparkDownloadProgressBar
{
[Embed(source="loaderlogo.png")] public var logoClass:Class;
private var _displayStartCount:uint = 0;
private var _initProgressCount:uint = 0;
private var _downloadComplete:Boolean = false;
private var _showingDisplay:Boolean = false;
private var _startTime:int;
// private var preloaderDisplay:PreloaderDisplay;
private var rslBaseText:String = "loading: ";
public function Preloader()
{
super();
}
/**
* Event listener for the <code>FlexEvent.INIT_COMPLETE</code> event.
* NOTE: This event can be commented out to stop preloader from completing during testing
*/
override protected function initCompleteHandler(event:Event):void
{
dispatchEvent(new Event(Event.COMPLETE));
}
/**
* Creates the subcomponents of the display.
*/
override protected function createChildren():void
{
var img:DisplayObject = new logoClass();
img.x = Math.round( ( stageWidth - img.width) / 2);
img.y = Math.round( ( stageHeight - img.height) / 2);
addChild( img);
var dpb:DownloadProgressBar = new DownloadProgressBar();
dpb.x = img.x + 100;
dpb.y = img.x + 100;
dpb.width = 170;
dpb.height = 20;
addChild( dpb);
}
/**
* Event listener for the <code>RSLEvent.RSL_PROGRESS</code> event.
**/
override protected function rslProgressHandler(evt:RSLEvent):void {
if (evt.rslIndex && evt.rslTotal) {
//create text to track the RSLs being loaded
rslBaseText = "loading RSL " + evt.rslIndex + " of " + evt.rslTotal + ": ";
}
}
/**
* indicate download progress.
*/
override protected function setDownloadProgress(completed:Number, total:Number):void {
}
/**
* Updates the inner portion of the download progress bar to
* indicate initialization progress.
*/
override protected function setInitProgress(completed:Number, total:Number):void {
}
/**
* Event listener for the <code>FlexEvent.INIT_PROGRESS</code> event.
* This implementation updates the progress bar
* each time the event is dispatched.
*/
override protected function initProgressHandler(event:Event):void {
var elapsedTime:int = getTimer() - _startTime;
_initProgressCount++;
if (!_showingDisplay && showDisplayForInit(elapsedTime, _initProgressCount)) {
_displayStartCount = _initProgressCount;
show();
// If we are showing the progress for the first time here, we need to call setDownloadProgress() once to set the progress bar background.
setDownloadProgress(100, 100);
}
if (_showingDisplay) {
// if show() did not actually show because of SWFObject bug then we may need to set the download bar background here
if (!_downloadComplete) {
setDownloadProgress(100, 100);
}
setInitProgress(_initProgressCount, initProgressTotal);
}
}
private function show():void
{
// swfobject reports 0 sometimes at startup
// if we get zero, wait and try on next attempt
if (stageWidth == 0 && stageHeight == 0)
{
try
{
stageWidth = stage.stageWidth;
stageHeight = stage.stageHeight
}
catch (e:Error)
{
stageWidth = loaderInfo.width;
stageHeight = loaderInfo.height;
}
if (stageWidth == 0 && stageHeight == 0)
return;
}
_showingDisplay = true;
createChildren();
}
}
}
For short, it's loading a logo and a progress bar
It displays a preloader, but really late in the loading process. As if it was being loaded after Flex.
Do I need to compile this in CS5 to completely avoid use of MX/Spark?
You shouldn't use any components in preloader. Try to remove you imports (Ctrl+Shift+O):
import mx.controls.Image;
import spark.components.Label;
Use TextField and Loader instead if needed. I'm not sure about DownloadProgressBar component.
Also don't use create children in preloader. Here is one working sample:
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import mx.core.mx_internal;
import mx.preloaders.SparkDownloadProgressBar;
use namespace mx_internal;
public class Preloader extends SparkDownloadProgressBar {
private var preloaderLogo : MovieClip;
private var loadingText : TextField;
private var loadingProgress : TextField;
private var _initProgressCount : uint = 0;
private var textFormat : TextFormat = new TextFormat("Verdana", 16, 0x666666, true);
public function Preloader() {
super();
textFormat.align = "center";
}
override public function set preloader(value : Sprite) : void {
super.preloader = value;
if (!preloaderLogo) {
preloaderLogo = new Assets.PRELOADER_LOGO; // kakaranet logo
var startX : Number = Math.round((stageWidth - preloaderLogo.width) / 2);
var startY : Number = Math.round(stageHeight / 2 - preloaderLogo.height) - 100;
preloaderLogo.x = startX;
preloaderLogo.y = startY;
loadingText = new TextField();
loadingProgress = new TextField();
loadingText.width = stageWidth;//to allow center align
loadingProgress.width = stageWidth;
loadingText.text = "Loading...";
loadingText.y = preloaderLogo.y + preloaderLogo.height + 20;
loadingProgress.text = "0%";
loadingProgress.y = loadingText.y + loadingText.textHeight + 10;
addChild(preloaderLogo);
addChild(loadingText);
addChild(loadingProgress);
loadingText.setTextFormat(textFormat);
loadingProgress.setTextFormat(textFormat);
}
}
override protected function progressHandler(event : ProgressEvent) : void {
super.progressHandler(event);
if (loadingProgress) {
loadingProgress.text = Math.floor(event.bytesLoaded / event.bytesTotal * 100) + "%";
loadingProgress.setTextFormat(textFormat);
}
}
override protected function completeHandler(event : Event) : void {
loadingText.text = "Ready!";
loadingText.setTextFormat(textFormat);
preloaderLogo.stop();
}
override protected function initProgressHandler(event : Event) : void {
super.initProgressHandler(event);
//similar to super
_initProgressCount++;
if (loadingProgress) {
loadingProgress.text = "100% / " + Math.floor(_initProgressCount / initProgressTotal * 100) + "%";
loadingProgress.setTextFormat(textFormat);
}
}
}
}
i want a dropdownlist that is wide enough to accommodate the larger item in the dropdown in display area of the main control.(.i.e. dropdownlist with the functionality of MX Combobox)
please guide me on this .
This will adjust the width of the drop down to the width of the data.
I forget where the example is where i got the code from. The height can be set by rowCount I believe.
package valueObjects.comboBox{
import flash.events.Event;
import mx.controls.ComboBox;
import mx.core.ClassFactory;
import mx.core.IFactory;
import mx.events.FlexEvent;
public class ExtendedComboBox extends ComboBox{
private var _ddFactory:IFactory = new ClassFactory(ExtendedList);
public function ExtendedComboBox(){
super();
}
override public function get dropdownFactory():IFactory{
return _ddFactory;
}
override public function set dropdownFactory(factory:IFactory):void{
_ddFactory = factory;
}
public function adjustDropDownWidth(event:Event=null):void{
this.removeEventListener(FlexEvent.VALUE_COMMIT,adjustDropDownWidth);
if (this.dropdown == null){
callLater(adjustDropDownWidth);
}else{
var ddWidth:int = this.dropdown.measureWidthOfItems(-1,this.dataProvider.length);
if (this.dropdown.maxVerticalScrollPosition > 0){
ddWidth += ExtendedList(dropdown).getScrollbarWidth();
}
this.dropdownWidth = Math.max(ddWidth,this.width);
}
}
override protected function collectionChangeHandler(event:Event):void{
super.collectionChangeHandler(event);
this.addEventListener(FlexEvent.VALUE_COMMIT,adjustDropDownWidth);
}
}
}
package valueObjects.comboBox{
import mx.controls.List;
public class ExtendedList extends List{
public function ExtendedList(){
super();
}
public function getScrollbarWidth():int{
var scrollbarWidth:int = 0;
if (this.verticalScrollBar != null){
scrollbarWidth = this.verticalScrollBar.width;
}
return scrollbarWidth;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" mlns:comboBox="valueObjects.comboBox.*" >
<comboBox:ExtendedComboBox labelField="data.totext()" itemRenderer="mx.controls.Label" />
</mx:Canvas>
You should create custom DropDownList (extending original) and override dataProvider setter and measure() method. In dataProvider setter you should invoke invalidateSize() and in measure you should iterate your data provider and find the largest label (you can assign new text to the label and compare their width).
To increase the height of a combo box's drop-down list, use "rowCount" property. This is for Flex 3.6.0
Check out this example from Flex Examples. You just have to create a skin for the DropDownList and set the popUpWidthMatchesAnchorWidth="false" property.
it is achieved by following code :
public override function set dataProvider(value:IList):void
{
var length:Number = 0;
var array:Array = value.toArray();
super.dataProvider = value;
var labelName:String = this.labelField;
var typicalObject:Object =new Object();
for each(var obj:Object in array)
{
var temp:Number = obj[labelName] .length;
if( length < temp )
{
length = temp;
Alert.show(" length "+length.toString());
typicalObject = obj;
}
//length = length < Number(obj[labelName].length) ? Number(obj[labelName].length) : length
//Alert.show(obj[labelName].length);
this.typicalItem = typicalObject;
}
}
Sorry, better take off both the width and height from the field.
I had tired loading an image form a url below is my sample code , when tried to load a large image which is greater than 8191 pixel in width or height the Event.COMPLETE is not dispatched , i am aware of the flash player 10 BitmapData limit ,so cant we load an image greater than this 8191 pixel limit ?is there any workaround for this Or any other method you suggest in doing ?
private function loadImage(url:String):void
{
var request:URLRequest = new URLRequest(url);
var imageLoader:Loader = new Loader();
var context:LoaderContext;
context = new LoaderContext();
context.checkPolicyFile = true;
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, image_completeHandler);
imageLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
imageLoader.load(request,context);
}
private function image_completeHandler(event:Event):void
{
trace(" Image load Complete");
}
private function ioErrorHandler(event:IOErrorEvent):void
{
trace("ioErrorHandler: " + event);
}
I would recommend that you split up the images. If you need Flash to handle the images as one (moving, scaling) I would write a holder-class that adds the image pieces as children of the itself.
I added some code and a link to a test below. Look at the code in action here. (wait for the SWF to load).
//TestClass
package
{
import com.kazumakzak.display.TileImage;
import flash.display.Sprite;
import flash.events.Event;
public class TestBigImage extends Sprite
{
[Embed(source="assets/piece.png")]
private var imageClass : Class;
private var _image : TileImage;
private var _counter : Number = 0;
public function TestBigImage()
{
// create image with tile size 640x480
_image = new TileImage(640, 480);
// add tiles at positions
_image.addTile(new imageClass(), 1, 1);
_image.addTile(new imageClass(), 1, 2);
_image.addTile(new imageClass(), 2, 1);
_image.addTile(new imageClass(), 2, 2);
_image.addTile(new imageClass(), 3, 1);
_image.addTile(new imageClass(), 3, 2);
// add to display list
addChild(_image);
addEventListener(Event.ENTER_FRAME, render);
}
private function render(event : Event) : void
{
_counter += 0.05;
_image.x = -640 + Math.cos(_counter) * 640
}
}
}
//TileImage.as
package com.kazumakzak.display
{
import flash.display.Bitmap;
import flash.display.Sprite;
public class TileImage extends Sprite
{
private var _tileWidth : int;
private var _tileHeight : int;
public function TileImage(tileWidth : int, tileHeight : Number)
{
_tileWidth = tileWidth;
_tileHeight = tileHeight;
}
public function addTile(source : Bitmap, tileX : int, tileY : int) : void
{
source.x = (tileX-1) * _tileWidth;
source.y = (tileY-1) * _tileHeight;
addChild(source);
}
}
}
Has anyone successfully implemented a custom preloader in Flex 4? In my experience, when I specify a custom preloader using the preloader="com.foo.MyPreloader" in the Application tag, the preloader does not display until the SWF is completely downloaded, defeating the purpose of the preloader! Perhaps this is a bug in the still-beta Flex 4 framework?
I've been using this example in many Flex3 projects. It's still working with Flex4 sdk:
I can remember where I get it from. And you are right when you say it's important that this script is NOT referencing anything...
<s:Application tag ... preloader="com.YYY.XXX.shell.view.CustomPreloader"
CustomPreloader
package com.YYY.XXX.shell.view
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
import mx.events.FlexEvent;
import mx.preloaders.DownloadProgressBar;
public final class CustomPreloader
extends DownloadProgressBar
{
public var loader : LoadScreen;
private var _timer : Timer;
public function CustomPreloader()
{
super();
}
override public function initialize() : void
{
super.initialize();
this.loader = new LoadScreen();
this.addChild(this.loader);
this._timer = new Timer(1);
this._timer.addEventListener(TimerEvent.TIMER, handleTimerTick);
this._timer.start();
}
override public function set preloader(preloader : Sprite):void
{
preloader.addEventListener(ProgressEvent.PROGRESS, SWFDownLoadScreen);
preloader.addEventListener(Event.COMPLETE, SWFDownloadComplete);
preloader.addEventListener(FlexEvent.INIT_PROGRESS, FlexInitProgress);
preloader.addEventListener(FlexEvent.INIT_COMPLETE, FlexInitComplete);
}
private function SWFDownLoadScreen(event : ProgressEvent) : void
{
var prog : Number = event.bytesLoaded / event.bytesTotal * 100;
if (this.loader)
{
this.loader.progress = prog;
}
}
private function handleTimerTick(event : TimerEvent) : void
{
this.stage.addChild(this);
this.loader.x = (this.stageWidth - this.loader.width) / 2;
this.loader.y = (this.stageHeight - this.loader.height) / 2;
this.loader.refresh();
}
private function SWFDownloadComplete(event : Event) : void {}
private function FlexInitProgress(event : Event) : void {}
private function FlexInitComplete(event : Event) : void
{
this.loader.ready = true;
this._timer.stop();
this.dispatchEvent(new Event(Event.COMPLETE));
}
override protected function showDisplayForInit(elapsedTime:int, count:int):Boolean
{
return true;
}
override protected function showDisplayForDownloading(elapsedTime:int,
event:ProgressEvent):Boolean
{
return true;
}
}
}
LoadScreen
package com.YYY.XXX.shell.view
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.Sprite;
import flash.utils.ByteArray;
import mx.graphics.codec.PNGEncoder;
public class LoadScreen extends Loader {
//~ Settings ----------------------------------------------------------
private static var _BarWidth : int = 153; // Progress bar width
private static var _BarHeight : int = 12; // Progress bar height
private static var _LogoHeight : int = 153; // Logo picture height
private static var _LogoWidth : int = 68; // Logo picture width
private static var _Padding : int = 5; // Spacing between logo and progress bar
private static var _LeftMargin : int = 0; // Left Margin
private static var _RightMargin : int = 0; // Right Margin
private static var _TopMargin : int = 1; // Top Margin
private static var _BottomMargin : int = 1; // Bottom Margin
private static var _BarBackground : uint = 0xFFFFFF; // background of progress bar
private static var _BarOuterBorder : uint = 0x737373; // color of outer border
private static var _BarColor : uint = 0x6F9FD5; // color of prog bar
private static var _BarInnerColor : uint = 0xFFFFFF; // inner color of prog bar
//~ Instance Attributes -----------------------------------------------
[Embed(source="/asset/embed/img/XXX.gif")]
private var MyLogoClass: Class;
private var _logo : Bitmap;
private var _logoData : BitmapData;
private var isReady : Boolean = false;
public var progress : Number;
//~ Constructor -------------------------------------------------------
public function LoadScreen()
{
super();
this.progress = 0;
this._logo = new MyLogoClass as Bitmap;
}
//~ Methods -----------------------------------------------------------
public function refresh() : void
{
this._logoData = this.draw();
var encoder : PNGEncoder = new PNGEncoder();
var bytes : ByteArray = encoder.encode(this._logoData);
this.loadBytes(bytes);
}
override public function get width() : Number
{
return Math.max(_BarWidth, _LogoWidth) + _LeftMargin + _RightMargin;
}
override public function get height() : Number
{
return _LogoHeight + _BarHeight + _Padding + _TopMargin + _BottomMargin;
}
private function draw() : BitmapData
{
// create bitmap data to create the data
var data : BitmapData = new BitmapData(this.width, this.height, true, 0);
// draw the progress bar
var s : Sprite = new Sprite();
var g : Graphics = s.graphics;
// draw the bar background
g.beginFill(_BarBackground);
g.lineStyle(2, _BarOuterBorder, 1, true);
var px : int = (this.width - _BarWidth) / 2;
var py : int = _TopMargin + _LogoHeight + _Padding;
g.drawRoundRect(px, py, _BarWidth, _BarHeight, 2);
var containerWidth : Number = _BarWidth - 4;
var progWidth : Number = containerWidth * this.progress / 100;
g.beginFill(_BarColor);
g.lineStyle(1, _BarInnerColor, 1, true);
g.drawRect(px + 1, py + 1, progWidth, _BarHeight - 3);
data.draw(s);
// draw the logo
data.draw(this._logo.bitmapData, null, null, null, null, true);
return data;
}
public function set ready(value : Boolean) : void
{
this.isReady = value;
this.visible = !this.isReady;
}
public function get ready() : Boolean { return this.isReady; }
}
}
I feel dumb...I was referencing one of my main application classes from within the preloader, thus causing all of my classes to be compiled into the preloader, meaning it cannot display the preloader until everything is loaded.
For future reference: Double-check every reference in your preloader, make sure you use nothing more than what is absolutely necessary
There is a Flex 4 Custom Preloader code sample here http://www.leavethatthingalone.com/blog/index.cfm/2009/11/11/Flex4CustomPreloader