Home > Thoughts > Flex SDK easy Background-Position

Flex SDK easy Background-Position

August 21st, 2008

One feature that current FLEX SDK skin lacks is the CSS background-position (it centers the image no metter what), here is a quick way to fix this.

CSS:

Box{
   border-skin:ClassReference('ro.huddle.skins.hallo.HalloBorderWithImagePositioning');
   background-image:Embed('/assets/browser_footer.jpg');
   background-position:left,bottom;
}

the HalloBorderWithImagePositioning class:

package ro.huddle.skins.hallo
{
	import flash.display.DisplayObject;
	import flash.display.Shape;

	import mx.core.EdgeMetrics;
	import mx.core.IChildList;
	import mx.core.IContainer;
	import mx.core.IRawChildrenContainer;
	import mx.skins.halo.HaloBorder;

	public class HalloBorderWithImagePositioning extends HaloBorder
	{

		 override public function layoutBackgroundImage():void{
		 	super.layoutBackgroundImage();
		 	if(!hasBackgroundImage) return;

		 	var style:Object = getStyle("backgroundPosition");
		 	// the default alignment is center center
		 	if(!(style is Array) || (style[0]=='center' && style[1]=='center')) return;
		 	var posHorizontal:String = style[0];
		 	var posVertical:String = style[1];

		 	var p:DisplayObject = parent;
		 	var bm:EdgeMetrics = p is IContainer ?
                             IContainer(p).viewMetrics :
                             borderMetrics;
			var childrenList:IChildList = parent is IRawChildrenContainer ?
                                         IRawChildrenContainer(parent).rawChildren :
                                         IChildList(parent);		 	

		 	var backgroundImage:DisplayObject = childrenList.getChildAt(1);

            // default position is center center, or middle,middle
			var bgX:int = backgroundImage.x;
			var bgY:int = backgroundImage.y;

			if(posHorizontal == 'left') bgX = bm.left;
			if(posHorizontal == 'right') bgX = p.width-bm.right-backgroundImage.width;

			if(posVertical == 'top') bgY = bm.top;
			if(posVertical == 'bottom') bgY = p.height-bm.bottom-backgroundImage.height;

		 	backgroundImage.x = bgX;
        	backgroundImage.y = bgY;

        	const backgroundMask:Shape = Shape(backgroundImage.mask);
        	backgroundMask.x = bgX;
        	backgroundMask.y = bgY;
		 }  

	}
}

Because of the RectangularBorder having most of it’s properties private instead of protected, some hacks need to be applied, like getting image from the childsList instead of getting it from the parent by name.

Anyway hope this helps somebody else, it did help me a couple of times.

Radu Cocieru Thoughts , , ,

  1. DilutedImage
    July 31st, 2009 at 01:58 | #1

    This works great. Nice work!

  2. February 15th, 2010 at 12:12 | #2

    Hi Radu,

    Thanks for the tutorial, but I don’t think it works quite right with right-aligned backgrounds. I am trying to a meter that shows an image to the right and to the left. If I show a border I can see that the image is growing to the left as expected, but the background doesn’t appear in the correct place. I know this was an old post, perhaps you have updated the code since then? If not i’ll try to figure out where it is going wrong.

    All the best,
    Ash

  3. February 15th, 2010 at 12:18 | #3

    Did you set the width to 100% .. and all of parent containers have a a fixed or % width ? If you don’t set the width on a container it tries to measure it and sizes the containers to a minimum width that accommodates the image.
    If this doesn’t work I would suggest http://www.degrafa.org if you can use 3rd party libraries.

  1. No trackbacks yet.