Description
I have been having what seemed like sporadic or inconsistent issues with FlexLayouts in my app, where text gets cut off on some flex children when the children have FlexLayout.Grow="1". I thought this was some sort of edge case with DPI and font size, but it actually seems to occur any time there are items with large differences in "main axis" size in a particular row.
The root of this problem seems to be that the flex layout code ignores the original measured size of all "growing" flex items when there is extra space to fill, and instead forces all "growing" items to have a size proportional to their Grow value. This means that if there are a number of items with Grow="1" in a row, and one of those items has a much larger "measured size" than the rest, then the "larger" item will be shrunk down and cause its child content to clip.
This does not match CSS flexbox behavior - in CSS, the "extra" space causes items to increase in size proportionally to their flex-grow value (as opposed to overriding their size, as MAUI does).
Take the following example:
- There is a horizontal-flowing flex container with 3 items in it, all with a grow factor of 1.
- The container has a width of 300 units.
- The first two items ("Item A" and "Item B") each have a measured width of 50 units. The third item ("Item C") has a measured width of 140 units. The total consumed size is 240, leaving 60 units of extra space.
In CSS, the 60 units of extra space will be added to each item, proportional to the grow factor. All three items in this case have the same grow factor, so the 60 units will be distributed as 20 units of extra size for each item. "Item A" and "Item B" now have a width of 70 units, and "Item C" has a width of 160 units. 70 + 70 + 160 = 300.
In MAUI, however, the flex layout engine will ignore the measured size of all of these items. It takes the 300 units of space that needs to be filled, divides it up proportionally amongst the items based on their grow factor, and that is the new size (regardless of how each item was measured). In this case, "Item A", "Item B", and "Item C" all have a size of 100 units. "Item C" is now 40 units smaller than its "measured size", causing its content to clip.
Example - Broken
I have created a reproduction example in MAUI, as well as an equivalent example in CSS. The following screenshot is on the main branch, with the broken behavior (MAUI on top, HTML/CSS on bottom). The example text was chosen specifically to be as close in length and punctuation to what is in my app (but without exposing the true text that my app is using). The source code of the HTML/CSS can be found here: https://gist.github.com/ArcanoxDragon/6ee10551f4f756a9e5bb89408ea9e5d0.
The fix
I was able to get MAUI to utilize the same growth behavior as CSS by commenting out lines 738-743 and line 787 of Flex.cs:
|
if (layout.flex_dim > 0 && layout.extra_flex_dim > 0) |
|
{ |
|
// If the container has a positive flexible space, let's add to it |
|
// the sizes of all flexible children. |
|
layout.flex_dim += layout.extra_flex_dim; |
|
} |
|
if (layout.flex_dim > 0) |
|
{ |
|
if (child.Grow != 0) |
|
{ |
|
child.Frame[layout.frame_size_i] = 0; // Ignore previous size when growing. |
|
flex_size = (layout.flex_dim / layout.flex_grows) * child.Grow; |
|
} |
|
} |
Example - Working
After commenting out the lines mentioned above, the behavior seems to match the HTML/CSS example:
I don't know the reasoning behind the code that I commented out above. It seems quite explicit in the fact that it ignores the measured item size, going by the comment on line 787, but this yields broken behavior (which also does not match CSS).
By removing the offending code, I actually believe that issues #22371 and #28165 (and perhaps others) would also be addressed, as those issues seem to fit the same criteria of "items with vastly different size exist in the same row".
Steps to Reproduce
I have created a reproduction branch on my fork of this repo (see below)
I placed the reproduction code in the Sandbox project. Simply check out the project, open/build/run, and resize the window to see some items become clipped as they start to wrap.
The issue occurs on at least Windows and Android (did not test others) - the Windows version obviously makes it easier to see the wrapping behavior compared to Android, since the window can be easily resized.
Link to public reproduction project repository
https://github.com/ArcanoxDragon/maui/tree/issue/flexlayout-repro
Version with bug
10.0.50
Is this a regression from previous behavior?
Not sure, did not test other versions
Last version that worked well
No response
Affected platforms
Android, Windows, I was not able test on other platforms
Affected platform versions
No response
Did you find any workaround?
I have not found a workaround, aside from commenting out the offending code in the MAUI project itself (obviously not feasible for standalone projects).
Relevant log output
Description
I have been having what seemed like sporadic or inconsistent issues with FlexLayouts in my app, where text gets cut off on some flex children when the children have
FlexLayout.Grow="1". I thought this was some sort of edge case with DPI and font size, but it actually seems to occur any time there are items with large differences in "main axis" size in a particular row.The root of this problem seems to be that the flex layout code ignores the original measured size of all "growing" flex items when there is extra space to fill, and instead forces all "growing" items to have a size proportional to their
Growvalue. This means that if there are a number of items withGrow="1"in a row, and one of those items has a much larger "measured size" than the rest, then the "larger" item will be shrunk down and cause its child content to clip.This does not match CSS flexbox behavior - in CSS, the "extra" space causes items to increase in size proportionally to their
flex-growvalue (as opposed to overriding their size, as MAUI does).Take the following example:
In CSS, the 60 units of extra space will be added to each item, proportional to the grow factor. All three items in this case have the same grow factor, so the 60 units will be distributed as 20 units of extra size for each item. "Item A" and "Item B" now have a width of 70 units, and "Item C" has a width of 160 units. 70 + 70 + 160 = 300.
In MAUI, however, the flex layout engine will ignore the measured size of all of these items. It takes the 300 units of space that needs to be filled, divides it up proportionally amongst the items based on their grow factor, and that is the new size (regardless of how each item was measured). In this case, "Item A", "Item B", and "Item C" all have a size of 100 units. "Item C" is now 40 units smaller than its "measured size", causing its content to clip.
Example - Broken
I have created a reproduction example in MAUI, as well as an equivalent example in CSS. The following screenshot is on the
mainbranch, with the broken behavior (MAUI on top, HTML/CSS on bottom). The example text was chosen specifically to be as close in length and punctuation to what is in my app (but without exposing the true text that my app is using). The source code of the HTML/CSS can be found here: https://gist.github.com/ArcanoxDragon/6ee10551f4f756a9e5bb89408ea9e5d0.The fix
I was able to get MAUI to utilize the same growth behavior as CSS by commenting out lines 738-743 and line 787 of
Flex.cs:maui/src/Core/src/Layouts/Flex.cs
Lines 738 to 743 in f6314b5
maui/src/Core/src/Layouts/Flex.cs
Lines 783 to 790 in f6314b5
Example - Working
After commenting out the lines mentioned above, the behavior seems to match the HTML/CSS example:
I don't know the reasoning behind the code that I commented out above. It seems quite explicit in the fact that it ignores the measured item size, going by the comment on line 787, but this yields broken behavior (which also does not match CSS).
By removing the offending code, I actually believe that issues #22371 and #28165 (and perhaps others) would also be addressed, as those issues seem to fit the same criteria of "items with vastly different size exist in the same row".
Steps to Reproduce
I have created a reproduction branch on my fork of this repo (see below)
I placed the reproduction code in the Sandbox project. Simply check out the project, open/build/run, and resize the window to see some items become clipped as they start to wrap.
The issue occurs on at least Windows and Android (did not test others) - the Windows version obviously makes it easier to see the wrapping behavior compared to Android, since the window can be easily resized.
Link to public reproduction project repository
https://github.com/ArcanoxDragon/maui/tree/issue/flexlayout-repro
Version with bug
10.0.50
Is this a regression from previous behavior?
Not sure, did not test other versions
Last version that worked well
No response
Affected platforms
Android, Windows, I was not able test on other platforms
Affected platform versions
No response
Did you find any workaround?
I have not found a workaround, aside from commenting out the offending code in the MAUI project itself (obviously not feasible for standalone projects).
Relevant log output