-
If I remove flex_direction: FlexDirection::Column, on line 24 scroll position will not work at all. //! Scrollable list with clickable items like Iphone settings in 0.16.0-rc.5
//!
//! Like Iphone settings, scroll by drag and click only without drag started.
//!
//! Maybe something like `PointerDragging` and `update_pointer_dragging` must be implemented in bevy?
//!
//! I write small example how I do this:
use bevy::{
color::palettes::tailwind, picking::pointer::PointerId, platform::collections::HashSet,
prelude::*,
};
fn spawn_camera(mut commands: Commands) {
commands.spawn(Camera2d);
}
fn spawn_ui(mut commands: Commands) {
commands
.spawn(Node {
width: Val::Percent(100.),
height: Val::Percent(100.),
overflow: Overflow::scroll_y(),
flex_direction: FlexDirection::Column,
..Default::default()
})
.with_children(|c| {
c.spawn(Node {
width: Val::Percent(100.),
flex_wrap: FlexWrap::Wrap,
row_gap: Val::Px(10.),
..Default::default()
})
.observe(scroll_drag)
.with_children(|c| {
for i in 1..=100 {
c.spawn((
Node {
width: Val::Percent(100.),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
padding: UiRect::vertical(Val::Px(20.)),
border: UiRect::all(Val::Px(2.)),
..Default::default()
},
BackgroundColor(tailwind::GRAY_500.into()),
BorderColor(tailwind::GRAY_300.into()),
))
.observe(item_click)
.with_child(Text::new(format!("Item #{i}")));
}
});
});
}
fn scroll_drag(
trigger: Trigger<Pointer<Drag>>,
node_query: Query<(&ChildOf, &ComputedNode)>,
mut parent_node_query: Query<(&ComputedNode, &mut ScrollPosition)>,
) {
let Ok((child_of, node)) = node_query.get(trigger.target()) else {
return;
};
let Ok((parent_node, mut scroll_position)) = parent_node_query.get_mut(child_of.parent())
else {
return;
};
let max_y = (node.size.y - parent_node.size.y).max(0.0);
scroll_position.offset_y = (scroll_position.offset_y - trigger.delta.y).clamp(0.0, max_y);
println!("{scroll_position:?}");
}
fn item_click(
trigger: Trigger<Pointer<Released>>,
state: Res<PointerDragging>,
text_query: Query<(&ChildOf, &Text)>,
) {
if state.contains(&(trigger.pointer_id, trigger.button)) {
return;
}
if let Some(text) = text_query
.iter()
.find_map(|(child_of, text)| (trigger.target() == child_of.parent()).then_some(text))
{
println!("Click at: {}", text.0);
};
}
#[derive(Debug, Default, Deref, DerefMut, Resource)]
struct PointerDragging(HashSet<(PointerId, PointerButton)>);
fn update_pointer_dragging(
mut state: ResMut<PointerDragging>,
mut drag_start_events: EventReader<Pointer<DragStart>>,
mut drag_end_events: EventReader<Pointer<DragEnd>>,
) {
for drag_start_event in drag_start_events.read() {
state.insert((drag_start_event.pointer_id, drag_start_event.button));
}
for drag_end_event in drag_end_events.read() {
state.remove(&(drag_end_event.pointer_id, drag_end_event.button));
}
}
fn main() {
App::new()
.init_resource::<PointerDragging>()
.add_plugins(DefaultPlugins)
.add_systems(Startup, (spawn_camera, spawn_ui))
.add_systems(Update, update_pointer_dragging)
.run();
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Let's call the first node This might not correctly answer your question but my guess are:
So the correct code should be fn spawn_ui(mut commands: Commands) {
commands
.spawn(Node {
width: Val::Percent(100.),
height: Val::Percent(100.),
overflow: Overflow::scroll_y(),
..Default::default()
})
.with_children(|c| {
c.spawn(Node {
width: Val::Percent(100.),
flex_direction: FlexDirection::Column, // here
position_type: PositionType::Absolute, // and here
row_gap: Val::Px(10.),
..Default::default()
})
.observe(scroll_drag)
.with_children(|c| {
for i in 1..=100 {
c.spawn((
Node {
width: Val::Percent(100.),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
padding: UiRect::vertical(Val::Px(20.)),
border: UiRect::all(Val::Px(2.)),
..Default::default()
},
BackgroundColor(tailwind::GRAY_500.into()),
BorderColor(tailwind::GRAY_300.into()),
))
.observe(item_click)
.with_child(Text::new(format!("Item #{i}")));
}
});
});
} Again, this might not be the exact answer you want. |
Beta Was this translation helpful? Give feedback.
Ok, after I watch example https://bevyengine.org/examples/ui-user-interface/scroll/ I understand how it works.
Need only specify overflow on container node.
And that's all.
Updated: