Expose scrollable offset properly

This commit is contained in:
Héctor Ramón Jiménez 2019-10-27 01:24:08 +02:00
parent 719c073fc6
commit 09bd2c46c0
4 changed files with 44 additions and 26 deletions

View file

@ -1,4 +1,4 @@
use crate::{Align, Column, Justify, Length}; use crate::{Align, Column, Justify, Length, Rectangle};
#[derive(Debug)] #[derive(Debug)]
pub struct Scrollable<'a, Element> { pub struct Scrollable<'a, Element> {
@ -112,11 +112,35 @@ impl<'a, Element> Scrollable<'a, Element> {
#[derive(Debug, Clone, Copy, Default)] #[derive(Debug, Clone, Copy, Default)]
pub struct State { pub struct State {
pub offset: u32, offset: u32,
} }
impl State { impl State {
pub fn new() -> Self { pub fn new() -> Self {
State::default() State::default()
} }
pub fn scroll(
&mut self,
delta_y: f32,
bounds: Rectangle,
content_bounds: Rectangle,
) {
if bounds.height >= content_bounds.height {
return;
}
// TODO: Configurable speed (?)
self.offset = (self.offset as i32 - delta_y.round() as i32 * 15)
.max(0)
.min((content_bounds.height - bounds.height) as i32)
as u32;
}
pub fn offset(&self, bounds: Rectangle, content_bounds: Rectangle) -> u32 {
let hidden_content =
(content_bounds.height - bounds.height).round() as u32;
self.offset.min(hidden_content).max(0)
}
} }

View file

@ -1,6 +1,6 @@
use iced::{ use iced::{
button, scrollable, Align, Application, Button, Color, Element, Image, button, scrollable, Align, Application, Button, Color, Column, Element,
Length, Scrollable, Text, Image, Justify, Length, Scrollable, Text,
}; };
pub fn main() { pub fn main() {
@ -32,12 +32,7 @@ impl Application for Example {
} }
fn view(&mut self) -> Element<Message> { fn view(&mut self) -> Element<Message> {
let content = Scrollable::new(&mut self.scroll) let content = Scrollable::new(&mut self.scroll).spacing(20).padding(20);
.width(Length::Fill)
.max_width(Length::Units(600))
.spacing(20)
.padding(20)
.align_self(Align::Center);
//let content = (0..self.paragraph_count) //let content = (0..self.paragraph_count)
// .fold(content, |column, _| column.push(lorem_ipsum())) // .fold(content, |column, _| column.push(lorem_ipsum()))
@ -49,8 +44,12 @@ impl Application for Example {
// .align_self(Align::Center), // .align_self(Align::Center),
// ); // );
(0..10) Column::new()
.fold(content, |content, _| { .height(Length::Fill)
.max_width(Length::Units(600))
.align_self(Align::Center)
.justify_content(Justify::Center)
.push((0..3).fold(content, |content, _| {
content.push( content.push(
Image::new(format!( Image::new(format!(
"{}/examples/resources/ferris.png", "{}/examples/resources/ferris.png",
@ -59,7 +58,7 @@ impl Application for Example {
.width(Length::Units(400)) .width(Length::Units(400))
.align_self(Align::Center), .align_self(Align::Center),
) )
}) }))
.into() .into()
} }
} }

View file

@ -56,12 +56,7 @@ where
Event::Mouse(mouse::Event::WheelScrolled { Event::Mouse(mouse::Event::WheelScrolled {
delta_y, .. delta_y, ..
}) => { }) => {
// TODO: Configurable speed (?) self.state.scroll(delta_y, bounds, content_bounds);
self.state.offset = (self.state.offset as i32
- delta_y.round() as i32 * 15)
.max(0)
.min((content_bounds.height - bounds.height) as i32)
as u32;
} }
_ => {} _ => {}
} }
@ -70,7 +65,8 @@ where
let cursor_position = if is_mouse_over { let cursor_position = if is_mouse_over {
Point::new( Point::new(
cursor_position.x, cursor_position.x,
cursor_position.y + self.state.offset as f32, cursor_position.y
+ self.state.offset(bounds, content_bounds) as f32,
) )
} else { } else {
Point::new(cursor_position.x, -1.0) Point::new(cursor_position.x, -1.0)

View file

@ -16,11 +16,10 @@ impl scrollable::Renderer for Renderer {
let content = layout.children().next().unwrap(); let content = layout.children().next().unwrap();
let content_bounds = content.bounds(); let content_bounds = content.bounds();
let offset = scrollable.state.offset(bounds, content_bounds);
let cursor_position = if bounds.contains(cursor_position) { let cursor_position = if bounds.contains(cursor_position) {
Point::new( Point::new(cursor_position.x, cursor_position.y + offset as f32)
cursor_position.x,
cursor_position.y + scrollable.state.offset as f32,
)
} else { } else {
Point::new(cursor_position.x, -1.0) Point::new(cursor_position.x, -1.0)
}; };
@ -30,7 +29,7 @@ impl scrollable::Renderer for Renderer {
let primitive = Primitive::Scrollable { let primitive = Primitive::Scrollable {
bounds, bounds,
offset: scrollable.state.offset, offset,
content: Box::new(content), content: Box::new(content),
}; };
@ -41,7 +40,7 @@ impl scrollable::Renderer for Renderer {
{ {
let ratio = bounds.height / content_bounds.height; let ratio = bounds.height / content_bounds.height;
let scrollbar_height = bounds.height * ratio; let scrollbar_height = bounds.height * ratio;
let y_offset = scrollable.state.offset as f32 * ratio; let y_offset = offset as f32 * ratio;
let scrollbar = Primitive::Quad { let scrollbar = Primitive::Quad {
bounds: Rectangle { bounds: Rectangle {