feathersui / feathersui-starling

User interface components for Starling Framework and Adobe AIR
https://feathersui.com/learn/as3-starling/
Other
914 stars 386 forks source link

ItemRenderer: Unclear resize behavior between `HorizontalLayout` and `VerticalLayout` #1828

Closed 2jfw closed 1 month ago

2jfw commented 1 month ago

I have an issue with understanding the resize behaviour/layout within an ItemRenderer. The ItemRenderer (code below) contains two layout groups: _mainGroupH and _mainGroupV. _mainGroupV contains a label with wordWrap set to true.

When the parent list gets resized, the ItemRenderer should adjust it's size automatically. This only works for one scenario (1) as the following screenshots will show:

Scenario 1: _mainGroupV using HorizontalLayout:

Initial stage width: Horizontal1 Smaller stage width: Horizontal2

Scenario 2: Assigning the _mainGroupV a VerticalLayout with the same properties will result in this: Vertical1

Resizing the stage will not have the label and ItemRenderer adapt to the size as it does in scenario 1 and I don't understand why.

Here is the code for both ItemRenderers:

Diff:

Scenario 1:

_mainGroupV                           = new LayoutGroup();
var verticalLayout : HorizontalLayout = new HorizontalLayout();

Scenario 2:

_mainGroupV                         = new LayoutGroup();
var verticalLayout : VerticalLayout = new VerticalLayout();

Full:

Scenario 1 Working as expected (_mainGroupV having a HorizontalLayout whereas I would want to use a VerticalLayout):


package itemRenderers
{
    import feathers.controls.Label;
    import feathers.controls.LayoutGroup;
    import feathers.controls.renderers.LayoutGroupGroupedListItemRenderer;
    import feathers.layout.AnchorLayoutData;
    import feathers.layout.HorizontalAlign;
    import feathers.layout.HorizontalLayout;
    import feathers.layout.VerticalAlign;

    import starling.display.Quad;

    public class CustomGroupedListItemRenderer extends LayoutGroupGroupedListItemRenderer
    {

        private var _label : Label;
        private var _mainGroupH : LayoutGroup;
        private var _mainGroupV : LayoutGroup;

        private var _paddingTop : int    = 0;
        private var _paddingRight : int  = 0;
        private var _paddingBottom : int = 0;
        private var _paddingLeft : int   = 0;

        public function CustomGroupedListItemRenderer(paddingTop : int    = 20,
                                                      paddingRight : int  = 20,
                                                      paddingBottom : int = 20,
                                                      paddingLeft : int   = 20)
        {
            super();

            _paddingTop    = paddingTop;
            _paddingRight  = paddingRight;
            _paddingBottom = paddingBottom;
            _paddingLeft   = paddingLeft;
        }

        override protected function initialize() : void
        {
            var horizontalLayout : HorizontalLayout = new HorizontalLayout();
            horizontalLayout.horizontalAlign        = HorizontalAlign.JUSTIFY;
            horizontalLayout.verticalAlign          = VerticalAlign.JUSTIFY;
            horizontalLayout.paddingTop             = _paddingTop;
            horizontalLayout.paddingRight           = _paddingRight;
            horizontalLayout.paddingBottom          = _paddingBottom;
            horizontalLayout.paddingLeft            = _paddingLeft;

            layout = horizontalLayout;

            super.initialize();

            createLayout();
        }

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

            _label.text = "This ItemRenderer will behave differently when _mainGroupV's layout is 'HorizontalLayout' or 'VerticalLayout'";
        }

        private function createLayout() : void
        {
            _mainGroupH                             = new LayoutGroup();
            var horizontalLayout : HorizontalLayout = new HorizontalLayout();
            horizontalLayout.horizontalAlign        = HorizontalAlign.JUSTIFY;
            horizontalLayout.verticalAlign          = VerticalAlign.JUSTIFY;
            _mainGroupH.layout                      = horizontalLayout;
            _mainGroupH.backgroundSkin              = new Quad(10,
                                                               10,
                                                               0x444444);

            _mainGroupH.layoutData = new AnchorLayoutData();

            ////

            _mainGroupV                           = new LayoutGroup();
            var verticalLayout : HorizontalLayout = new HorizontalLayout();
            verticalLayout.horizontalAlign        = HorizontalAlign.JUSTIFY;
            verticalLayout.verticalAlign          = VerticalAlign.MIDDLE;
            _mainGroupV.layout                    = verticalLayout;
            _mainGroupH.addChild(_mainGroupV);

            _label          = new Label();
            _label.wordWrap = true;
            _mainGroupV.addChild(_label);

            addChild(_mainGroupH);
        }

        override protected function draw() : void
        {
            _label.width = width - _paddingLeft - _paddingRight; // just temp for dynamic resize
            super.draw();
        }
    }
}

Scenario 2 Not Working as expected (_mainGroupV having a VerticalLayout [only difference!]):

package itemRenderers
{
    import feathers.controls.Label;
    import feathers.controls.LayoutGroup;
    import feathers.controls.renderers.LayoutGroupGroupedListItemRenderer;
    import feathers.layout.AnchorLayoutData;
    import feathers.layout.HorizontalAlign;
    import feathers.layout.HorizontalLayout;
    import feathers.layout.VerticalAlign;
    import feathers.layout.VerticalLayout;

    import starling.display.Quad;

    public class CustomGroupedListItemRenderer extends LayoutGroupGroupedListItemRenderer
    {

        private var _label : Label;
        private var _mainGroupH : LayoutGroup;
        private var _mainGroupV : LayoutGroup;

        private var _paddingTop : int    = 0;
        private var _paddingRight : int  = 0;
        private var _paddingBottom : int = 0;
        private var _paddingLeft : int   = 0;

        public function CustomGroupedListItemRenderer(paddingTop : int    = 20,
                                                      paddingRight : int  = 20,
                                                      paddingBottom : int = 20,
                                                      paddingLeft : int   = 20)
        {
            super();

            _paddingTop    = paddingTop;
            _paddingRight  = paddingRight;
            _paddingBottom = paddingBottom;
            _paddingLeft   = paddingLeft;
        }

        override protected function initialize() : void
        {
            var horizontalLayout : HorizontalLayout = new HorizontalLayout();
            horizontalLayout.horizontalAlign        = HorizontalAlign.JUSTIFY;
            horizontalLayout.verticalAlign          = VerticalAlign.JUSTIFY;
            horizontalLayout.paddingTop             = _paddingTop;
            horizontalLayout.paddingRight           = _paddingRight;
            horizontalLayout.paddingBottom          = _paddingBottom;
            horizontalLayout.paddingLeft            = _paddingLeft;

            layout = horizontalLayout;

            super.initialize();

            createLayout();
        }

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

            _label.text = "This ItemRenderer will behave differently when _mainGroupV's layout is 'HorizontalLayout' or 'VerticalLayout'";
        }

        private function createLayout() : void
        {
            _mainGroupH                             = new LayoutGroup();
            var horizontalLayout : HorizontalLayout = new HorizontalLayout();
            horizontalLayout.horizontalAlign        = HorizontalAlign.JUSTIFY;
            horizontalLayout.verticalAlign          = VerticalAlign.JUSTIFY;
            _mainGroupH.layout                      = horizontalLayout;
            _mainGroupH.backgroundSkin              = new Quad(10,
                                                               10,
                                                               0x444444);

            _mainGroupH.layoutData = new AnchorLayoutData();

            ////

            _mainGroupV                         = new LayoutGroup();
            var verticalLayout : VerticalLayout = new VerticalLayout();
            verticalLayout.horizontalAlign      = HorizontalAlign.JUSTIFY;
            verticalLayout.verticalAlign        = VerticalAlign.MIDDLE;
            _mainGroupV.layout                  = verticalLayout;
            _mainGroupH.addChild(_mainGroupV);

            _label          = new Label();
            _label.wordWrap = true;
            _mainGroupV.addChild(_label);

            addChild(_mainGroupH);
        }

        override protected function draw() : void
        {
            _label.width = width - _paddingLeft - _paddingRight; // just temp for dynamic resize
            super.draw();
        }
    }
}

My question is, why does VerticalLayoutnot adapt to the size and flow out of bounds? horizontalAlign is set to HorizontalAlign.JUSTIFY in both scenarios.

joshtynjala commented 1 month ago

Try setting _mainGroupV.layoutData to a new HorizontalLayoutData with percentWidth set to 100.0.

2jfw commented 1 month ago

Unfortunately, this did not work.

Scenario 2 changed to :

            _mainGroupV                         = new LayoutGroup();
            var verticalLayout : VerticalLayout = new VerticalLayout();
            verticalLayout.horizontalAlign      = HorizontalAlign.JUSTIFY;
            verticalLayout.verticalAlign        = VerticalAlign.MIDDLE;
            _mainGroupV.layout                  = verticalLayout;
            _mainGroupV.layoutData              = new HorizontalLayoutData(100);
            _mainGroupH.addChild(_mainGroupV);

The label still goes out-of-bound / IR does not react to resizing.

joshtynjala commented 1 month ago

You probably need this too, actually:

_mainGroupH.layoutData              = new HorizontalLayoutData(100);

Be sure to remove this, since it could cause conflicts (and doesn't do anything anyway):

_mainGroupH.layoutData = new AnchorLayoutData();
2jfw commented 1 month ago
_mainGroupH.layoutData              = new HorizontalLayoutData(100);

This is working and I see how layoutData can affect the entire layouting process. This will likely bring in much more light to other previous "issues" I had in the past!

Thanks Josh, much appreciated (also again for your immediate response) ! 🍻

joshtynjala commented 1 month ago

You're welcome!