davi_flutter icon indicating copy to clipboard operation
davi_flutter copied to clipboard

Stretchable column

Open ykrasik opened this issue 3 years ago • 15 comments

Hi,

Thanks for this project. I can't find any way of stretching only a single column to fill the available width while having other columns have a fixed width with custom cell renderers. I'm looking for the following behavior:

| <---- flex column that will fill in all available width ---> | fixed width column | fixed width column |

The idea is that the fixed width columns will not allow the width to go below their min width (or their intrinsic width) and the flex column use up the available width after the fixed width columns have taken theirs.

Things I've tried:

  • Setting a weight of 100 on the stretch column and a weight of 1 on the fixed columns, but then the fixed width columns aren't rendered at all.
  • Setting lower weights doesn't give the desired behavior either - For example, using weight 10 on the stretch column and 1 on the others gets them to render, but the columns that are supposed to be fixed width still expand and contract when the window is resized.
  • The width parameter of the columns seems to be ignored with columnsFit: true.
  • I also tried wrapping the columns in Widgets that apply constraints like ConstrainedBox or IntrinsicWidth, but there was no effect.

Specifically in my case I only need 1 flex column, but I suppose this can be generalized into the following: How to mix any number of flex columns (that behave according to the weight behavior) with fixed-width columns that do not flex?

ykrasik avatar Nov 28 '22 21:11 ykrasik

Hi @ykrasik! Sorry about the delay.

You cannot find it because it does not exist. :grimacing: :disappointed:

Currently, there are only columnsFit with weight or columns with width.

I understand that you would like weight without columnsFit. But I don't know how it would be to have flex and horizontal scroll at the same time. I would have to think. I don't even know if that exists :smile:

  • width would be the initial size?
  • flex stop growing when the sum of the widths is equal or greater than the available area?

I'll check the layout algorithm.

caduandrade avatar Nov 30 '22 23:11 caduandrade

This can also be achieved, I think, by adding a minWidth to columns. If each column has a minWidth and a low weight and the flex column(s) would have a higher weight and no minWidth, that would behave as expected, at least in this case. Just need to make the layout respect the minWidth of each column.

ykrasik avatar Dec 01 '22 19:12 ykrasik

Hi @caduandrade!

Hope I don't come off as rude, but I need this feature for what I'm working on and this ability would affect whether I can use this library or not.

Is this something you would consider implementing any time soon?

ykrasik avatar Dec 14 '22 19:12 ykrasik

Hi @ykrasik ! Sorry for the delay. I'm in a very busy week (after work my brain is off).

I'm still thinking about how it will behave with flex + window resize + manual column resize.

caduandrade avatar Dec 16 '22 12:12 caduandrade

@ykrasik , the simple case (N columns and a single flex) is easier to think of. Horizontal scrolling could appear if a minimum flex column width is less than the available space. But there are still other more complex cases.

Example: table with 3 flex columns and one of them is resized. When the window is resized, the rule for displaying the scroll will also depend on this delta of the new column size and not just on the minimum width.

caduandrade avatar Dec 16 '22 13:12 caduandrade

Hi @caduandrade - here are my observations. Currently, its already possible for a flex column to completely "push out" another flex column by having a much larger weight (for example, 200 vs 1), resulting in the 2nd flex column having 0 width (OK, I'm not actually sure its 0 width, but its not visible).

So maybe, as a suggestion - allow each column to declare a minimum width. When laying out the columns, each column takes up its minimum width first, and then the flex columns are given an opportunity to grow (sharing the remaining width according to their flex weight). If a flex column doesn't declare a minWidth and all the columns don't fit in the parent, the flex columns are shrunk, all the way to 0 if needed. If the columns still can't fit the width, horizontal scroll appears.

And manual column resize would act as... minWidth?

ykrasik avatar Dec 17 '22 21:12 ykrasik

@ykrasik

I'm thinking of keeping it simple by disabling sizing on columns with flex. I think it makes more sense because if it's flex, it should only grow when it can.

The width attribute could already be used to display or not the scroll. Its default value is 100.

I see minWidth as another feature that can limit resizing.

I'm also seeing how to rename weight to flex and reuse that same attribute but as nullable.

Perhaps it would be better to change the columnsFit parameter to a ColumnsBehavior enum with scrollable and fit values.

caduandrade avatar Dec 17 '22 22:12 caduandrade

Thanks for taking the time to work on this, I'll be happy to test it when it's ready. Will stay tuned for updates 🙂

ykrasik avatar Dec 18 '22 08:12 ykrasik

@ykrasik, mission accomplished.

Sorry for the delay. As I said, work was busy and unfortunately, I still don't use Flutter there. So there is not much free time for this open-source project. I hope that changes someday :pray: .

If you need anything else, let me know.

caduandrade avatar Dec 18 '22 21:12 caduandrade

Awesome, thanks for this! This is really not a big delay, quite quick in fact :) Will test!

ykrasik avatar Dec 19 '22 13:12 ykrasik

Hi @caduandrade!

It works, thanks! I played around with it a bit. However, first thing I noticed was that resizable columns behave a bit... unnaturally, when combined with a flex column: qfiler 2022-12-23 23-44-33 Its like the resize handle is on the wrong side - happy to hear your thoughts.

Also, I know I suggested using fixed widths for the non-flex columns, but when it was time to actually use it I found myself wanting the columns to just dynamically size themselves - a "fit" column. If the flex column takes up all available width, a "fit" column would take up the minimum width it can to accommodate its children. This is useful, for example, if a column is a "datetime" column whose format depends on the locale (and is in a row with a flex column). It would be useful to have it sized dynamically according to its content, instead of specifying its width manually to fit the maximum width date format.

ykrasik avatar Dec 23 '22 23:12 ykrasik

Hi @ykrasik!

Video

The width of a flexible column is used as its minimum width. The flex only applies to available space beyond the width used by all columns.

All columns have a default width of 100. In the video, it looks ugly but I believe it is expected. When decreasing column (col2), column (col1) will occupy the available space because it is flexible. When increasing column (col2), it will first decrease column (col1) which is flexible since column (col3) must already be at its minimum size.

Maybe you want to define the order of priority between the columns as well. With that, maybe col3 could decrease before col1. It's turning into a layout :smile: .

Sizing according to its content

It is something very difficult especially in Flutter and even more in this table because only the visible Widgets are in memory. Even if it does, this feature should be off by default. It would probably be too slow as well :disappointed: . For the same reason, the cell has a fixed height. It is one of the tips to improve performance.

Perhaps the best would be to define a technique that I've used a lot in Swing and JavaFx which is to define a prototype to represent the width. It would be more performant than comparing against all cell data. I would just have to think about how this would be possible in Flutter.

caduandrade avatar Dec 24 '22 01:12 caduandrade

Hi @caduandrade ,

Thanks for your reply. About the resizing - it feels unnatural because the resize handle is on the right, but the column grows in size to the left. I understand why this is happening, just as a user I would expect a resizable column to resize in the direction of the drag if it is possible, or just not resize at all if not possible. I think the solution that would make it feel natural is to have 2 resize zones for each column, on both sides, and only allow resizing in a direction if there is available width in that direction. Actually, maybe 2 resize zones aren't needed as col1's right resize zone is col2's left resize zone, just adjust the behavior because we're not trying to set the size of col1, we're trying to set the size of col2 and have col1 adjust. In the example above, dragging the right handle to the right would do nothing and dragging the left handle (which currently doesn't exist) would allow the column to resize. This is probably not trivial to implement 😊

As for the dynamic column sizing - I understand. The "prototype" solution is actually great, as in this use case all content would be the same width, but the width is not known upfront, it is set at application boot.

ykrasik avatar Dec 24 '22 09:12 ykrasik

The idea of having 2 resize zones seems to be a good one :tada: . I will reopen it for now to remember.

caduandrade avatar Dec 27 '22 01:12 caduandrade

Would it be possible to add a auto-width parameter? A simple bool, if true, sets the column width to fit the largest cell in this column.

SuricateTrading avatar Feb 20 '23 12:02 SuricateTrading