Closed jm-observer closed 1 year ago
I've had to figure out the same thing just now:
pub struct AutoScrollController;
impl<T: Data, W: Widget<T>> Controller<T, Scroll<T, W>> for AutoScrollController {
fn update(
&mut self,
child: &mut Scroll<T, W>,
ctx: &mut UpdateCtx,
old_data: &T,
data: &T,
env: &Env,
) {
if !ctx.is_disabled() {
let size = child.child_size();
let end_region = Rect::new(size.width - 1., size.height - 1., size.width, size.height);
child.scroll_to(ctx, end_region);
}
child.update(ctx, old_data, data, env)
}
}
Then use something like WidgetExt::controller
to apply that to your Scroll
.
UpdateCtx::scroll_to_view
exists, too, but with a List
nested in Scroll
, I didn't find a way to get the individual child elements to pass to that function.
@sclu1034 thanks! I gave it a try,it does roll, but not to the end, it will scroll to last but one. because _child.childsize() gets the current size, not the updated size that it should scroll to. i try to use Command to let it scroll, if it works, I'll get back to you
@sclu1034 can use Command to auto scroll:
pub struct AutoScrollController;
impl<T: druid::Data, W: Widget<T>> Controller<T, Scroll<T, W>> for AutoScrollController {
fn event(
&mut self,
child: &mut Scroll<T, W>,
_ctx: &mut EventCtx,
event: &Event,
data: &mut T,
_env: &Env,
) {
match event {
Event::Command(cmd) => {
if let Some(_) = cmd.get(SELECTOR_AUTO_SCROLL) {
let size = child.child_size();
let end_region =
Rect::new(size.width - 1., size.height - 1., size.width, size.height);
child.scroll_to(_ctx, end_region);
}
}
_ => child.event(_ctx, event, data, _env),
}
}
}
when add elements, you should submit a command:
async fn receive_public(
event_sink: &druid::ExtEventSink,
index: usize,
topic: Arc<String>,
payload: Arc<Bytes>,
qos: QoS,
) -> Result<()> {
event_sink.add_idle_callback(move |data: &mut AppData| {
data.receive_msg(index, topic, payload, qos);
});
sleep(Duration::from_millis(150)).await;
event_sink.submit_command(SELECTOR_AUTO_SCROLL, (), SCROLL_MSG_ID)?;
Ok(())
}
other code:
pub const SCROLL_MSG_ID: WidgetId = WidgetId::reserved(3);
pub const SELECTOR_AUTO_SCROLL: Selector<()> = Selector::new("scroll.auto");
……
let scroll = Scroll::<Vector<Msg>, List<Msg>>::new(list)
.vertical()
.controller(AutoScrollController)
.with_id(SCROLL_MSG_ID)
……
How to make the scroll view automatically scroll when new data is added?