0
votes

I have an IDropInListItemRenderer that is being used inside a List. The height of the row depends on both the data and it's position in the List's view.

How do I remeasure as soon as the row index changes?

updateDisplayList doesn't get called every time, and also by that point it's too late because the List has already measured it.

edit

The effect I'm trying to achieve is similar to iOS where the header for a section sticks to the top iOS UITableView with sections

Here is the basic renderer that doesn't measure correctly:

import mx.controls.Label;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;
import mx.controls.listClasses.IListItemRenderer;
import mx.core.UIComponent;
import mx.events.FlexEvent;

public class MyRowRenderer extends UIComponent implements IListItemRenderer, IDropInListItemRenderer {
    private static const HEADER_HEIGHT:int = 20;
    private static const LABEL_HEIGHT:int = 20;

    private var _data:Object;
    private var _label:Label;
    private var _header:Label;
    private var _listData:BaseListData;

    public function MyRowRenderer() {
        super();
    }

    [Bindable("dataChange")]
    public function get data():Object {
        return _data;
    }

    public function set data(value:Object):void {
        this._data = value;
        invalidateProperties();
        dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
    }

    [Bindable("dataChange")]
    public function get listData():BaseListData {
        return _listData;
    }

    public function set listData(value:BaseListData):void {
        _listData = value;
    }

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

        _header = new Label();
        addChild(_header);

        _label = new Label();
        addChild(_label);
    }

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

        if (_label == null || _header == null) {
            return;
        }

        var h:Number = LABEL_HEIGHT;

        if (_listData.rowIndex == 0) {
            h += HEADER_HEIGHT;
        }

        explicitHeight = measuredHeight = height = h;
    }

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

        _label.text = _data.label;
        _header.text = _data.header;
    }

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

        _header.visible = _header.includeInLayout = (_listData.rowIndex == 0);

        if (_header.visible) {
            _header.move(0, 0);
            _header.setActualSize(unscaledWidth, HEADER_HEIGHT);

            _label.move(0, HEADER_HEIGHT);
            _label.setActualSize(unscaledWidth, LABEL_HEIGHT);
        } else {
            _label.move(0, 0);
            _label.setActualSize(unscaledWidth, LABEL_HEIGHT);
        }
    }
}

}

1
Can you provide working code? why don't try with inline itemRenderer any specific reason there? - Raja Jaganathan

1 Answers

0
votes

I ended up creating a subclass of List and overriding the shiftRow function to dispatch a custom RowIndexChangeEvent. In the row renderer's set listData it adds an event listener to the owner for the RowIndexChangeEvent and invalidates it's properties, size and displaylist.