Skip to main content

ScrollViewState

Struct ScrollViewState 

Source
pub struct ScrollViewState { /* private fields */ }
Expand description

Shared inertial scrolling state used by crate::ScrollView and crate::ListView.

Implementations§

Source§

impl ScrollViewState

Source

pub const fn new() -> Self

Creates an empty scroll state.

Examples found in repository?
src/scroll_view/mod.rs (line 27)
25    pub const fn new() -> Self {
26        Self {
27            state: ScrollViewState::new(),
28            shows_vertical_scroll_indicator: true,
29            indicator_alpha: 0,
30            indicator_hold_ms: 0,
31        }
32    }
Source

pub const fn is_dragging(&self) -> bool

Returns whether a drag is currently active.

Examples found in repository?
src/scroll_view/mod.rs (line 60)
59    pub const fn is_dragging(&self) -> bool {
60        self.state.is_dragging()
61    }
Source

pub const fn is_scrolling(&self) -> bool

Returns whether drag slop has been crossed and scrolling is active.

Examples found in repository?
src/scroll_view/mod.rs (line 65)
64    pub const fn is_scrolling(&self) -> bool {
65        self.state.is_scrolling()
66    }
67
68    /// Returns the integer content offset.
69    pub fn content_offset_y(&self) -> i32 {
70        self.state.content_offset_y()
71    }
72
73    /// Starts a drag sequence.
74    pub fn begin_drag(&mut self, touch: TouchEvent) {
75        self.state.begin_drag(touch);
76    }
77
78    /// Updates dragging with a new touch sample.
79    pub fn drag(&mut self, touch: TouchEvent, content_height: u32, viewport_height: u32) -> bool {
80        let changed = self.state.drag(touch, content_height, viewport_height);
81        if changed || self.state.is_scrolling() {
82            self.reveal_indicator();
83        }
84        changed
85    }
86
87    /// Ends dragging and starts any fling animation.
88    pub fn end_drag(
89        &mut self,
90        touch: TouchEvent,
91        content_height: u32,
92        viewport_height: u32,
93    ) -> bool {
94        let changed = self.state.end_drag(touch, content_height, viewport_height);
95        if changed || self.state.is_animating(content_height, viewport_height) {
96            self.reveal_indicator();
97        }
98        changed
99    }
100
101    /// Advances animation and indicator fade state.
102    pub fn tick(&mut self, dt_ms: u32, content_height: u32, viewport_height: u32) -> bool {
103        let scrolled = self.state.tick(dt_ms, content_height, viewport_height);
104        if !self.shows_vertical_scroll_indicator || content_height <= viewport_height {
105            let indicator_changed = self.indicator_alpha != 0;
106            self.indicator_alpha = 0;
107            self.indicator_hold_ms = 0;
108            return scrolled || indicator_changed;
109        }
110
111        let was_alpha = self.indicator_alpha;
112        if self.state.is_scrolling() || self.state.is_animating(content_height, viewport_height) {
113            self.reveal_indicator();
114        } else if self.indicator_hold_ms > 0 {
115            self.indicator_hold_ms = self.indicator_hold_ms.saturating_sub(dt_ms);
116        } else if self.indicator_alpha > 0 {
117            self.indicator_alpha = self.indicator_alpha.saturating_sub(
118                (dt_ms.saturating_mul(u32::from(SCROLLBAR_FADE_PER_MS))).min(255) as u8,
119            );
120        }
121        scrolled || was_alpha != self.indicator_alpha
122    }
Source

pub fn content_offset_y(&self) -> i32

Returns the rounded integer content offset.

Examples found in repository?
src/scroll_view/mod.rs (line 70)
69    pub fn content_offset_y(&self) -> i32 {
70        self.state.content_offset_y()
71    }
More examples
Hide additional examples
src/list.rs (line 79)
73    pub fn drag(&mut self, touch: TouchEvent, content_height: u32, viewport_height: u32) -> bool {
74        if !self.touch_active {
75            self.begin_drag(touch);
76            return false;
77        }
78
79        let before = self.content_offset_y();
80        let max = max_position_px(content_height, viewport_height);
81        let delta_y = touch.point.y as f32 - self.drag_anchor_y;
82        let delta_abs = delta_y.abs();
83        if !self.scrolling {
84            if delta_abs < DRAG_SLOP_PX {
85                return false;
86            }
87            self.scrolling = true;
88        }
89        self.tracker.add(touch);
90
91        let effective_delta_y = delta_y.signum() * (delta_abs - DRAG_SLOP_PX).max(0.0);
92        let raw_position = self.drag_anchor_position_px - effective_delta_y;
93        self.position_px = apply_rubber_band(raw_position, max, viewport_height as f32);
94        before != self.content_offset_y()
95    }
96
97    /// Ends the drag sequence and computes fling state.
98    pub fn end_drag(
99        &mut self,
100        touch: TouchEvent,
101        content_height: u32,
102        viewport_height: u32,
103    ) -> bool {
104        if !self.touch_active {
105            return false;
106        }
107
108        let changed = self.drag(touch, content_height, viewport_height);
109        self.touch_active = false;
110        let max = max_position_px(content_height, viewport_height);
111        self.velocity_px_per_s = if !self.scrolling || outside_bounds(self.position_px, max) {
112            0.0
113        } else {
114            release_velocity(self.tracker.velocity())
115        };
116        self.scrolling = false;
117        changed
118    }
119
120    /// Advances inertial scrolling and overscroll recovery.
121    pub fn tick(&mut self, dt_ms: u32, content_height: u32, viewport_height: u32) -> bool {
122        if self.touch_active || dt_ms == 0 {
123            return false;
124        }
125
126        let before = self.content_offset_y();
127        let dt = (dt_ms as f32 / 1000.0).min(MAX_DT_SECONDS);
128        let max = max_position_px(content_height, viewport_height);
129
130        if outside_bounds(self.position_px, max) {
131            self.snap_toward_bounds(dt, max);
132        } else if self.velocity_px_per_s.abs() >= MIN_VELOCITY {
133            let next = self.position_px + (self.velocity_px_per_s * dt);
134            if next < 0.0 {
135                self.position_px = 0.0;
136                self.velocity_px_per_s = 0.0;
137            } else if next > max {
138                self.position_px = max;
139                self.velocity_px_per_s = 0.0;
140            } else {
141                self.position_px = next;
142                self.velocity_px_per_s = apply_decay(self.velocity_px_per_s, dt_ms);
143            }
144        }
145
146        if self.velocity_px_per_s.abs() < MIN_VELOCITY {
147            self.velocity_px_per_s = 0.0;
148        }
149        before != self.content_offset_y()
150    }
Source

pub fn content_offset(&self) -> f32

Returns the raw floating-point content offset.

Examples found in repository?
src/scroll_view/mod.rs (line 136)
125    pub fn scroll_bar(&self, viewport: Rectangle, content_height: u32) -> Option<ScrollBar> {
126        if !self.shows_vertical_scroll_indicator
127            || self.indicator_alpha == 0
128            || content_height <= viewport.size.height
129        {
130            return None;
131        }
132
133        scroll_bar_thumb(
134            viewport,
135            content_height,
136            self.state.content_offset(),
137            self.indicator_alpha,
138        )
139    }
Source

pub fn begin_drag(&mut self, touch: TouchEvent)

Starts a drag sequence.

Examples found in repository?
src/scroll_view/mod.rs (line 75)
74    pub fn begin_drag(&mut self, touch: TouchEvent) {
75        self.state.begin_drag(touch);
76    }
More examples
Hide additional examples
src/list.rs (line 75)
73    pub fn drag(&mut self, touch: TouchEvent, content_height: u32, viewport_height: u32) -> bool {
74        if !self.touch_active {
75            self.begin_drag(touch);
76            return false;
77        }
78
79        let before = self.content_offset_y();
80        let max = max_position_px(content_height, viewport_height);
81        let delta_y = touch.point.y as f32 - self.drag_anchor_y;
82        let delta_abs = delta_y.abs();
83        if !self.scrolling {
84            if delta_abs < DRAG_SLOP_PX {
85                return false;
86            }
87            self.scrolling = true;
88        }
89        self.tracker.add(touch);
90
91        let effective_delta_y = delta_y.signum() * (delta_abs - DRAG_SLOP_PX).max(0.0);
92        let raw_position = self.drag_anchor_position_px - effective_delta_y;
93        self.position_px = apply_rubber_band(raw_position, max, viewport_height as f32);
94        before != self.content_offset_y()
95    }
Source

pub fn drag( &mut self, touch: TouchEvent, content_height: u32, viewport_height: u32, ) -> bool

Applies a drag update.

Examples found in repository?
src/scroll_view/mod.rs (line 80)
79    pub fn drag(&mut self, touch: TouchEvent, content_height: u32, viewport_height: u32) -> bool {
80        let changed = self.state.drag(touch, content_height, viewport_height);
81        if changed || self.state.is_scrolling() {
82            self.reveal_indicator();
83        }
84        changed
85    }
More examples
Hide additional examples
src/list.rs (line 108)
98    pub fn end_drag(
99        &mut self,
100        touch: TouchEvent,
101        content_height: u32,
102        viewport_height: u32,
103    ) -> bool {
104        if !self.touch_active {
105            return false;
106        }
107
108        let changed = self.drag(touch, content_height, viewport_height);
109        self.touch_active = false;
110        let max = max_position_px(content_height, viewport_height);
111        self.velocity_px_per_s = if !self.scrolling || outside_bounds(self.position_px, max) {
112            0.0
113        } else {
114            release_velocity(self.tracker.velocity())
115        };
116        self.scrolling = false;
117        changed
118    }
Source

pub fn end_drag( &mut self, touch: TouchEvent, content_height: u32, viewport_height: u32, ) -> bool

Ends the drag sequence and computes fling state.

Examples found in repository?
src/scroll_view/mod.rs (line 94)
88    pub fn end_drag(
89        &mut self,
90        touch: TouchEvent,
91        content_height: u32,
92        viewport_height: u32,
93    ) -> bool {
94        let changed = self.state.end_drag(touch, content_height, viewport_height);
95        if changed || self.state.is_animating(content_height, viewport_height) {
96            self.reveal_indicator();
97        }
98        changed
99    }
Source

pub fn tick( &mut self, dt_ms: u32, content_height: u32, viewport_height: u32, ) -> bool

Advances inertial scrolling and overscroll recovery.

Examples found in repository?
src/scroll_view/mod.rs (line 103)
102    pub fn tick(&mut self, dt_ms: u32, content_height: u32, viewport_height: u32) -> bool {
103        let scrolled = self.state.tick(dt_ms, content_height, viewport_height);
104        if !self.shows_vertical_scroll_indicator || content_height <= viewport_height {
105            let indicator_changed = self.indicator_alpha != 0;
106            self.indicator_alpha = 0;
107            self.indicator_hold_ms = 0;
108            return scrolled || indicator_changed;
109        }
110
111        let was_alpha = self.indicator_alpha;
112        if self.state.is_scrolling() || self.state.is_animating(content_height, viewport_height) {
113            self.reveal_indicator();
114        } else if self.indicator_hold_ms > 0 {
115            self.indicator_hold_ms = self.indicator_hold_ms.saturating_sub(dt_ms);
116        } else if self.indicator_alpha > 0 {
117            self.indicator_alpha = self.indicator_alpha.saturating_sub(
118                (dt_ms.saturating_mul(u32::from(SCROLLBAR_FADE_PER_MS))).min(255) as u8,
119            );
120        }
121        scrolled || was_alpha != self.indicator_alpha
122    }
Source

pub fn is_animating(&self, content_height: u32, viewport_height: u32) -> bool

Returns whether the state is still animating after touch release.

Examples found in repository?
src/scroll_view/mod.rs (line 95)
88    pub fn end_drag(
89        &mut self,
90        touch: TouchEvent,
91        content_height: u32,
92        viewport_height: u32,
93    ) -> bool {
94        let changed = self.state.end_drag(touch, content_height, viewport_height);
95        if changed || self.state.is_animating(content_height, viewport_height) {
96            self.reveal_indicator();
97        }
98        changed
99    }
100
101    /// Advances animation and indicator fade state.
102    pub fn tick(&mut self, dt_ms: u32, content_height: u32, viewport_height: u32) -> bool {
103        let scrolled = self.state.tick(dt_ms, content_height, viewport_height);
104        if !self.shows_vertical_scroll_indicator || content_height <= viewport_height {
105            let indicator_changed = self.indicator_alpha != 0;
106            self.indicator_alpha = 0;
107            self.indicator_hold_ms = 0;
108            return scrolled || indicator_changed;
109        }
110
111        let was_alpha = self.indicator_alpha;
112        if self.state.is_scrolling() || self.state.is_animating(content_height, viewport_height) {
113            self.reveal_indicator();
114        } else if self.indicator_hold_ms > 0 {
115            self.indicator_hold_ms = self.indicator_hold_ms.saturating_sub(dt_ms);
116        } else if self.indicator_alpha > 0 {
117            self.indicator_alpha = self.indicator_alpha.saturating_sub(
118                (dt_ms.saturating_mul(u32::from(SCROLLBAR_FADE_PER_MS))).min(255) as u8,
119            );
120        }
121        scrolled || was_alpha != self.indicator_alpha
122    }
Source

pub fn visible_range( &self, item_height: u32, item_count: usize, viewport_height: u32, ) -> Range<usize>

Returns the approximate visible index range for fixed-height rows.

Trait Implementations§

Source§

impl Clone for ScrollViewState

Source§

fn clone(&self) -> ScrollViewState

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ScrollViewState

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ScrollViewState

Source§

fn default() -> ScrollViewState

Returns the “default value” for a type. Read more
Source§

impl Copy for ScrollViewState

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Az for T

Source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

Source§

fn cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> CheckedAs for T

Source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

Source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> OverflowingAs for T

Source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

Source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
Source§

impl<T> SaturatingAs for T

Source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

Source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> UnwrappedAs for T

Source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

Source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> WrappingAs for T

Source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

Source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.