How to achieve a column that wraps horizontally and scrolls vertically?

I am trying to get a list of elements. These should take up the width of my window as much as possible, so the new wrap() function for column seems appropriate.

However, the user may have an insufficiently sized window, so I need to have it in a scrollable as well - this should be vertically scrollable in my opinion (though for now, if horizontally works it’d be something).

Now the obvious idea is to put the wrapping column into a scrollable, but that does not work. Once inside a scrollable, the column just lists every element in one single row - no matter the width of the window.

Here is a minimal example:

use iced::{widget::{button, column, container, row, scrollable, text}, Element, Length::Fill};

fn main() → iced::Result{
iced::run(WrappingScrollable::update, WrappingScrollable::view)
}

#[derive(Default)]
struct WrappingScrollable {
scrolling: bool
}

#[derive(Debug, Clone, Copy)]
enum Message{
ToggleScrolling
}

impl WrappingScrollable {

fn new() -> Self {
    Self{
        scrolling: false,
    }
}

fn update(&mut self, message: Message) {
    match message {
        Message::ToggleScrolling => self.scrolling = !self.scrolling,
    }
}

fn view(&self) -> Element<Message> {
    let mut v = vec!["somewhat long text"];
    for i in 0..50 {
        v.push("somewhat long text");
    }

    let c = column(
        v.iter()
        .enumerate()
            .map(|(index, label_text)| {
                text(label_text.clone()).into()
            })
    ).wrap();

    let toggle_button = button("Toggle").on_press(Message::ToggleScrolling);
    if self.scrolling {
        container(
            row![
                scrollable(c)
                    .width(Fill)
                    .height(Fill),
                toggle_button
            ]
        ).into()
    }
    else {
        container(
            row![
                c,
                toggle_button
            ]
        ).into()
    }
}

}

Here is what it looks like:

Screencast_20251208_160302(3)

Is there a chance you could use a wrapping row instead?

column currently only sees an infinite amount of vertical space provided by the scrollable during layout, so it won’t ever wrap.

In theory this works, yes. However, it messes up my ordering. Here is a screenshot when using row from the actual program I’m working on:


This goes from left to right, then from top to bottom (alphabetic ordering).
In this particular case, I think it makes finding what you look for harder, my aim is to have it top to bottom first and then left to right.

On an unrelated note, this does not put all the names into neat rows - which is also what I would like to have. This didn’t occur to me in the minimal example earlier, as I just had the same dummy text over and over. Is there some way of achieving “neat” rows, kind of like you would have them in a table?