mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 06:40:06 -04:00
Fix: ScrollArea layout jitter with floating bars and zoom levels (#7944)
Fix: ScrollArea layout jitter with floating bars and zoom levels * Closes #7937 * Closes #7942 This PR improves the stability of `ScrollArea` by addressing two layout issues: 1. **Discrete Layout for Floating Bars:** Fixed content "shaking" in `floating` mode when a non-zero `allocated_width` is used. By using discrete visibility (`show_bars`) instead of the animated factor for space allocation, we ensure the layout remains stable during scrollbar animations. 2. **Zoom-level Stability:** Introduced a small epsilon (0.1) when checking if content exceeds the viewport. This prevents scrollbars from flickering on and off due to floating-point rounding errors at specific zoom factors (e.g., 1.01 or 0.95).
This commit is contained in:
@@ -753,7 +753,12 @@ impl ScrollArea {
|
|||||||
ctx.animate_bool_responsive(id.with("v"), show_bars[1]),
|
ctx.animate_bool_responsive(id.with("v"), show_bars[1]),
|
||||||
);
|
);
|
||||||
|
|
||||||
let current_bar_use = show_bars_factor.yx() * ui.spacing().scroll.allocated_width();
|
let scroll_style = ui.spacing().scroll;
|
||||||
|
let current_bar_use = if scroll_style.floating {
|
||||||
|
show_bars.to_vec2().yx() * scroll_style.allocated_width()
|
||||||
|
} else {
|
||||||
|
show_bars_factor.yx() * scroll_style.allocated_width()
|
||||||
|
};
|
||||||
|
|
||||||
let available_outer = ui.available_rect_before_wrap();
|
let available_outer = ui.available_rect_before_wrap();
|
||||||
|
|
||||||
@@ -1187,9 +1192,15 @@ impl Prepared {
|
|||||||
|
|
||||||
let outer_rect = Rect::from_min_size(inner_rect.min, inner_rect.size() + current_bar_use);
|
let outer_rect = Rect::from_min_size(inner_rect.min, inner_rect.size() + current_bar_use);
|
||||||
|
|
||||||
|
let limit_rect = if ui.spacing().scroll.floating {
|
||||||
|
outer_rect
|
||||||
|
} else {
|
||||||
|
inner_rect
|
||||||
|
};
|
||||||
|
|
||||||
let content_is_too_large = Vec2b::new(
|
let content_is_too_large = Vec2b::new(
|
||||||
direction_enabled[0] && inner_rect.width() < content_size.x,
|
direction_enabled[0] && (limit_rect.width().ceil() < content_size.x),
|
||||||
direction_enabled[1] && inner_rect.height() < content_size.y,
|
direction_enabled[1] && (limit_rect.height().ceil() < content_size.y),
|
||||||
);
|
);
|
||||||
|
|
||||||
let max_offset = content_size - inner_rect.size();
|
let max_offset = content_size - inner_rect.size();
|
||||||
|
|||||||
Reference in New Issue
Block a user