I'm returning to a component I was trying to write earlier, that would scale
and center a single child (or ideally children), such that the contents fit
within the bounds of the container, and aspect ratio is preserved. The
solution at the end of this post  does the scaling of one child fine
(including aspect ratio) but I haven't figured out how to incorporate the
centering. Just setting horizontalCenter on the content holder didn't work,
and nor did my efforts to add a move() call as shown in the code below:

A couple of notes.
- If the measure() implementations returned content dimensions rather than
0, I got scroll bars and 1400 was passed into updateDisplayList().
- allowInvalidateSize is because otherwise setting scale triggers
re-measuring.

Any advice about the centering would be much appreciated. Here's the code:

Test case:

<mx:Canvas width="90%" height="90%" horizontalCenter="0" verticalCenter="0"
borderStyle="solid" >
    <comp:ScaledContent  width="100%" height="100%" borderStyle="solid" >
        <mx:Button label="Big" width="1400" height="1400"
cornerRadius="50"/>
     </comp:ScaledContent>
</mx:Canvas>

ScaledContent.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"; xmlns:comp="comp.*"
    horizontalScrollPolicy="off" verticalScrollPolicy="off"
    >

    <mx:Metadata>
        [DefaultProperty("contents")]
    </mx:Metadata>

    <mx:Script>
        <![CDATA[
            import mx.core.UIComponent;

            private var _contents:UIComponent;
            private var _contentsChanged:Boolean = false;

            public function set contents(value:UIComponent):void {
                _contents = value;
                _contentsChanged = true;
                this.invalidateProperties();
            }

            override protected function commitProperties():void {
                super.commitProperties();

                if (_contentsChanged) {
                    contentHolder.content = _contents;
                    _contentsChanged = false;
                }
             }


            override protected function measure():void {
                super.measure();
                minWidth = measuredWidth = 0; //
_contents.getExplicitOrMeasuredWidth();
                minHeight = measuredHeight = 0; //
_contents.getExplicitOrMeasuredHeight();
            }

            override protected function
updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void {
                super.updateDisplayList(unscaledWidth, unscaledHeight);
                contentHolder.scaleContentToFit(unscaledWidth,
unscaledHeight);
                contentHolder.setActualSize(unscaledWidth, unscaledHeight);
            }
        ]]>
    </mx:Script>

    <comp:ScaledContentHolder id="contentHolder" >
    </comp:ScaledContentHolder>

</mx:Canvas>

ScaledContentHolder.as

    public class ScaledContentHolder extends UIComponent
    {
        public function ScaledContentHolder()
        {
        }

        private var _allowInvalidateSize:Boolean = true;
        private var _content:UIComponent;
        private var _contentChanged:Boolean = false;

        override protected function measure():void
        {
            super.measure();
            minWidth = measuredWidth = 0; //
_content.getExplicitOrMeasuredWidth();
            minHeight = measuredHeight = 0;
//_content.getExplicitOrMeasuredHeight();
        }

        public function set content(value:UIComponent):void {
            _content = value;
            _contentChanged = true;
            this.invalidateProperties();
        }

         override protected function commitProperties():void {
             super.commitProperties();
             if (_contentChanged) {
                 this.removeAllChildren();
                 this.addChild(_content);
                 _contentChanged = false;
             }
         }


      private function removeAllChildren():void
      {
          while (numChildren> 0)
          {
              removeChildAt(0);
          }
      }


        override public function invalidateSize():void
        {
            if (_allowInvalidateSize)
                super.invalidateSize();
        }

        public function scaleContentToFit(unscaledWidth:Number,
unscaledHeight:Number):void {
            var contentWidth:Number = _content.getExplicitOrMeasuredWidth();
            var contentHeight:Number =
_content.getExplicitOrMeasuredHeight();

            var xScale:Number = (unscaledWidth / contentWidth);
            var yScale:Number = (unscaledHeight / contentHeight);
            var finalScale:Number = Math.min(xScale, yScale); // Preserve
aspect ratio

            _allowInvalidateSize = false;
            this.scaleX = finalScale;
            this.scaleY = finalScale;
             _allowInvalidateSize = true;

             var scaledContentWidth:Number = contentWidth * finalScale;
             var scaledContentHeight:Number = contentHeight * finalScale;

             _content.move(unscaledWidth/2 - scaledContentWidth/2 ,
unscaledHeight/2 - scaledContentHeight/2);

        }

        override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
        {
            super.updateDisplayList(unscaledWidth, unscaledHeight);
        }

Reply via email to