0

I've created a simple Callout with a List in it. Like this:

<s:Callout xmlns:fx="http://ns.adobe.com/mxml/2009" 
       xmlns:s="library://ns.adobe.com/flex/spark" 
       xmlns:mx="library://ns.adobe.com/flex/mx" 
       autoLayout="true" >
<fx:Declarations>
    <!-- Platzieren Sie nichtvisuelle Elemente (z. B. Dienste, Wertobjekte) hier -->
</fx:Declarations>

<fx:Script>
    <![CDATA[
        import com.skill.flextensions.factories.StyledClassFactory;

        import mx.collections.IList;

        import spark.components.IconItemRenderer;
        import spark.components.List;
        import spark.events.IndexChangeEvent;
        import spark.layouts.HorizontalAlign;
        import spark.layouts.VerticalLayout;

        private var _list:List; 
        //
        // PUBLIC PROPERTIES
        //
        private var _dataProvider:IList;
        private var _dataProviderChanged:Boolean = false;
        public function get dataProvider():IList
        {
            return _dataProvider;
        }

        public function set dataProvider(value:IList):void
        {
            _dataProvider = value;
            _dataProviderChanged = true;
            this.invalidateProperties();
        }

        private var _itemRenderer:IFactory;
        private var _itemRendererChanged:Boolean = false;
        public function get itemRenderer():IFactory
        {
            return _itemRenderer;
        }
        public function set itemRenderer(value:IFactory):void
        {
            _itemRenderer = value;
            _itemRendererChanged = true;
            this.invalidateProperties();
        }
        //          
        // @ SUPER
        //
        override protected function commitProperties():void
        {
            super.commitProperties();

            if(_dataProviderChanged)
            {
                _dataProviderChanged = false;
                _list.dataProvider = _dataProvider;
                // TODO
                // we have to remeasure, after dataprovider updated
                // unfortunately, this doesn't work:
                /*
                _list.invalidateSize();
                _list.invalidateDisplayList();
                _list.validateNow();
                invalidateSize();
                invalidateDisplayList();
                validateNow();
                */
                // so we will have to find a workaround for this situation.
            }

            if(_itemRendererChanged)
            {
                _itemRendererChanged= false;
                _list.itemRenderer = getItemRenderer();
            }
        }

        override protected function createChildren():void
        {
            _list = new List;
            _list.top = _list.bottom = 0;                   
            _list.itemRenderer = getItemRenderer();
            _list.addEventListener( IndexChangeEvent.CHANGE , onChange , false , 0 , true );

            var l:VerticalLayout = new VerticalLayout;
            l.gap = 0;
            l.requestedMinRowCount = 0;
            l.horizontalAlign = HorizontalAlign.CONTENT_JUSTIFY;
            _list.layout = l;

            this.addElement( _list );
        }
        //
        // @ LIST
        //
        protected function onChange(e:IndexChangeEvent):void
        {
            var obj:Object = _list.selectedItem;
            this.removeAllElements();
            _list = null;
            this.close(true , obj);
        }

        private function getItemRenderer():IFactory
        {
            if( ! _itemRenderer )
            {
                var fac:StyledClassFactory = new StyledClassFactory( IconItemRenderer );

                var props:Object = new Object;
                props.messageField = "message";
                props.labelField = "";
                props.styleName = "itemName";
                props.iconField = "icon";

                var styles:Object = new Object;
                styles.messageStyleName = "itemHeadline";

                fac.properties = props;
                fac.styles = styles;

                return fac;
            }
            return _itemRenderer;
        }

    ]]>
</fx:Script>

The problem here is, that my Callout does not measure correctly. When the dataProvider is added to the List, it always resizes the List to the first item. When some user-interaction happens with the List, it suddenly resizes correctly (adjusting to the largest item).

Unfortunaltely, the CallOut-Position does not change, leading to a misplaced Callout, sometimes it's even half off screen.

So I want to make sure, List has the right size, before I open the Callout.

How can I do this? Many thx for your input.

zero323
  • 322,348
  • 103
  • 959
  • 935
T. Richter
  • 369
  • 1
  • 13
  • I Bet implementing a measure() method on your custom component will solve this issue. – JeffryHouser Jul 22 '13 at 00:33
  • @Reboog711 Yes, I will most probably do this. But right now I don't find the time. I will post the completed code as soon it's done. Many thx. – T. Richter Jul 23 '13 at 09:59

1 Answers1

0

I had the same problem. I'm sure there's a more elegant way to do it but this was my solution.

  1. Listen for Callout FlexEvent.CREATION_COMPLETE:

    <s:Callout xmlns:fx="http://ns.adobe.com/mxml/2009" 
       xmlns:s="library://ns.adobe.com/flex/spark" 
       xmlns:mx="library://ns.adobe.com/flex/mx" 
       autoLayout="true"
       creationComplete="init()">
    
  2. Force the callout to redo its layout/sizing:

    function init():void
    {
        validateNow();
        updatePopUpPosition();
    }
    

In my app, i handle list data population slightly differently than you, so you may need to call init() after setting data instead.

  • I tried, but this doesn't work in my case :( Problem must be somewhere in the List or in it's layout. I temporarily ended up with binding your init to `ResizeEvent.Resize` which at least repositions the popup back on the after List resizes on any user interaction. But the List shouldn't resize in the first place, but get the right dimensions from the beginning. So your answer is about half correct ;-) BTW: If I remove my 'custom' layout, the List doesn't resize, but isn't big enough to display data as well. – T. Richter Jul 21 '13 at 23:02
  • Strange, the @Lee Burrows tag is not working for me right now, I hope you get this anyway. thx again – T. Richter Jul 21 '13 at 23:08
  • you could also try justify for the list layout horizontalAlign - i found content justify to be troublesome –  Jul 22 '13 at 02:11
  • The List will not be shown in the right width then. I already tried. I think I will do as Reboog711 suggests, implementing a measure(). But for the moment I stick to the workaround you suggested. Many thx. – T. Richter Jul 23 '13 at 10:04