linebender / druid

A data-first Rust-native UI design toolkit.
https://linebender.org/druid/
Apache License 2.0
9.53k stars 569 forks source link

scroll list can't scroll in flex column with a top button #2171

Open Sherlock-Holo opened 2 years ago

Sherlock-Holo commented 2 years ago

I want to scroll the list, thats my codes

use druid::im::Vector;
use druid::widget::{Button, Flex, Label, List, Scroll};
use druid::{AppLauncher, Data, Lens, Widget, WidgetExt, WindowDesc};

pub fn run() {
    let main_window = WindowDesc::new(ui_builder()).title("Clipboards");

    let contents = (1..100).map(|i| format!("text 测试 {}", i)).collect();

    let clipboards = Clipboards { contents };

    AppLauncher::with_window(main_window)
        .log_to_console()
        .launch(clipboards)
        .unwrap()
}

#[derive(Debug, Clone, Data, Lens)]
pub struct Clipboards {
    contents: Vector<String>,
}

fn ui_builder() -> impl Widget<Clipboards> {
    let button_text = Label::new("button").with_text_size(20.0);
    let button = Button::from_label(button_text)
        .on_click(|_ctx, _: &mut Clipboards, _env| println!("top click"));

    let list = List::new(|| {
        Label::dynamic(|content: &String, _env| content.to_string())
            .with_text_size(20.0)
            .on_click(|_ctx, content, _env| {
                println!("click {}", content);
            })
    })
    .with_spacing(20.0)
    .center()
    .expand_width()
    .scroll()
    .vertical()
    .lens(Clipboards::contents);

    /*Flex::column()
        .with_child(button)
        .with_default_spacer()
        .with_child(list)*/
    list
}

it can scroll image

and now I want to add a button on the top

use druid::im::Vector;
use druid::widget::{Button, Flex, Label, List, Scroll};
use druid::{AppLauncher, Data, Lens, Widget, WidgetExt, WindowDesc};

pub fn run() {
    let main_window = WindowDesc::new(ui_builder()).title("Clipboards");

    let contents = (1..100).map(|i| format!("text 测试 {}", i)).collect();

    let clipboards = Clipboards { contents };

    AppLauncher::with_window(main_window)
        .log_to_console()
        .launch(clipboards)
        .unwrap()
}

#[derive(Debug, Clone, Data, Lens)]
pub struct Clipboards {
    contents: Vector<String>,
}

fn ui_builder() -> impl Widget<Clipboards> {
    let button_text = Label::new("button").with_text_size(20.0);
    let button = Button::from_label(button_text)
        .on_click(|_ctx, _: &mut Clipboards, _env| println!("top click"));

    let list = List::new(|| {
        Label::dynamic(|content: &String, _env| content.to_string())
            .with_text_size(20.0)
            .on_click(|_ctx, content, _env| {
                println!("click {}", content);
            })
    })
    .with_spacing(20.0)
    .center()
    .expand_width()
    .scroll()
    .vertical()
    .lens(Clipboards::contents);

    Flex::column()
        .with_child(button)
        .with_default_spacer()
        .with_child(list)
}

but now the list can't scroll and the scroll bar is miss image

how should I do to add the button on the top and keep the list scrollable?

Sherlock-Holo commented 2 years ago

by the way I am using the master branch

univerz commented 2 years ago

i would like to know why, but this works:

Flex::column().with_child(button).with_default_spacer().with_flex_child(list, 1.)
kzbt commented 2 years ago

I believe this is because when using Flex.with_child the child widget has infinite height. with_flex_child restricts the height to the "viewport"(?).