pub struct ScrollView { /* private fields */ }Expand description
Scroll container state with UIKit-style indicator behavior.
Implementations§
Source§impl ScrollView
impl ScrollView
Sourcepub const fn new() -> Self
pub const fn new() -> Self
Creates a scroll view with an enabled vertical indicator.
Examples found in repository?
60fn main() {
61 let mut canvas = support::NullCanvas::new(Size::new(320, 240));
62 let viewport = Rectangle::new(Point::new(16, 16), Size::new(180, 160));
63
64 let mut scroll = ScrollView::new();
65 scroll.begin_drag(TouchEvent::new(Point::new(8, 8), TouchPhase::Start, 1));
66 let _ = scroll.drag(
67 TouchEvent::new(Point::new(8, 32), TouchPhase::Move, 2),
68 420,
69 160,
70 );
71 let _ = scroll.end_drag(
72 TouchEvent::new(Point::new(8, 32), TouchPhase::End, 3),
73 420,
74 160,
75 );
76 let _ = scroll.tick(16, 420, 160);
77 let _ = scroll.scroll_bar(viewport, 420);
78
79 let mut list = ListView::new(DemoDataSource, DemoDelegate);
80 let _ = list.handle_touch(
81 TouchEvent::new(Point::new(24, 24), TouchPhase::Start, 10),
82 viewport,
83 );
84 let _ = list.handle_touch(
85 TouchEvent::new(Point::new(24, 60), TouchPhase::Move, 11),
86 viewport,
87 );
88 let _ = list.handle_touch(
89 TouchEvent::new(Point::new(24, 60), TouchPhase::End, 12),
90 viewport,
91 );
92 list.draw(
93 &mut canvas,
94 viewport,
95 &ViewEnvironment {
96 theme: &support::theme(),
97 i18n: &support::i18n(),
98 },
99 );
100}More examples
26 pub fn new(data_source: DataSource, delegate: Delegate) -> Self {
27 Self {
28 scroll_view: ScrollView::new(),
29 data_source,
30 delegate,
31 touch_started_inside: false,
32 tap_candidate: false,
33 highlighted_index: None,
34 selected_index: None,
35 allows_selection: true,
36 }
37 }Sourcepub const fn state(&self) -> &ScrollViewState
pub const fn state(&self) -> &ScrollViewState
Returns the underlying scroll state.
Sourcepub fn state_mut(&mut self) -> &mut ScrollViewState
pub fn state_mut(&mut self) -> &mut ScrollViewState
Returns the underlying scroll state mutably.
Sourcepub const fn shows_vertical_scroll_indicator(&self) -> bool
pub const fn shows_vertical_scroll_indicator(&self) -> bool
Returns whether the vertical indicator is enabled.
Sourcepub fn set_shows_vertical_scroll_indicator(&mut self, shows: bool)
pub fn set_shows_vertical_scroll_indicator(&mut self, shows: bool)
Enables or disables the vertical indicator.
Sourcepub const fn is_dragging(&self) -> bool
pub const fn is_dragging(&self) -> bool
Returns whether a touch drag is active.
Examples found in repository?
12 pub fn handle_touch<'text>(
13 &mut self,
14 touch: TouchEvent,
15 viewport: Rectangle,
16 ) -> ListEvent<Delegate::Message>
17 where
18 Delegate: ListDelegate<'text, DataSource::ItemId>,
19 {
20 if !touch.within(viewport) && !self.scroll_view.is_dragging() {
21 return ListEvent::none();
22 }
23
24 let local_touch = offset_touch(touch, viewport.top_left);
25 let touched_index = self.item_index_at_point(touch.point, viewport);
26 let was_dragging = self.scroll_view.is_dragging();
27 let previous_highlight = self.highlighted_index;
28 let previous_selection = self.selected_index;
29 let mut activity = ListActivity::None;
30 let mut message = None;
31
32 let scrolled = match touch.phase {
33 TouchPhase::Start => {
34 self.touch_started_inside = touch.within(viewport);
35 self.tap_candidate = self.touch_started_inside;
36 self.scroll_view.begin_drag(local_touch);
37 message = message.or(
38 self.set_highlighted_index(touched_index.filter(|_| self.touch_started_inside))
39 );
40 false
41 }
42 TouchPhase::Move => {
43 let changed =
44 self.scroll_view
45 .drag(local_touch, self.content_height(), viewport.size.height);
46 if changed || self.scroll_view.is_scrolling() {
47 self.tap_candidate = false;
48 message = message.or(self.set_highlighted_index(None));
49 } else {
50 let next_highlight = if self.touch_started_inside && touch.within(viewport) {
51 touched_index
52 } else {
53 None
54 };
55 message = message.or(self.set_highlighted_index(next_highlight));
56 }
57 changed
58 }
59 TouchPhase::End | TouchPhase::Cancel => {
60 let changed = self.scroll_view.end_drag(
61 local_touch,
62 self.content_height(),
63 viewport.size.height,
64 );
65
66 if matches!(touch.phase, TouchPhase::End)
67 && self.touch_started_inside
68 && self.tap_candidate
69 && touch.within(viewport)
70 {
71 if let Some(index) = touched_index {
72 if self.allows_selection {
73 self.selected_index = Some(index);
74 }
75 if let Some(selection) = self.selection_for_index(index) {
76 message = message.or(self.delegate.did_select_item(selection));
77 }
78 }
79 }
80
81 message = message.or(self.set_highlighted_index(None));
82 self.touch_started_inside = false;
83 self.tap_candidate = false;
84 changed
85 }
86 };
87
88 let visual_state_changed = previous_highlight != self.highlighted_index
89 || previous_selection != self.selected_index;
90 let motion_active = scrolled || self.scroll_view.is_scrolling();
91
92 if motion_active {
93 activity = ListActivity::Motion;
94 } else if visual_state_changed {
95 activity = ListActivity::Interactive;
96 }
97
98 ListEvent {
99 redraw: match activity {
100 ListActivity::None => ViewRedraw::None,
101 ListActivity::Interactive | ListActivity::Motion => ViewRedraw::Dirty(viewport),
102 },
103 captured: was_dragging || touch.within(viewport) || self.touch_started_inside,
104 message,
105 activity,
106 }
107 }Sourcepub const fn is_scrolling(&self) -> bool
pub const fn is_scrolling(&self) -> bool
Returns whether the view is actively scrolling.
Examples found in repository?
12 pub fn handle_touch<'text>(
13 &mut self,
14 touch: TouchEvent,
15 viewport: Rectangle,
16 ) -> ListEvent<Delegate::Message>
17 where
18 Delegate: ListDelegate<'text, DataSource::ItemId>,
19 {
20 if !touch.within(viewport) && !self.scroll_view.is_dragging() {
21 return ListEvent::none();
22 }
23
24 let local_touch = offset_touch(touch, viewport.top_left);
25 let touched_index = self.item_index_at_point(touch.point, viewport);
26 let was_dragging = self.scroll_view.is_dragging();
27 let previous_highlight = self.highlighted_index;
28 let previous_selection = self.selected_index;
29 let mut activity = ListActivity::None;
30 let mut message = None;
31
32 let scrolled = match touch.phase {
33 TouchPhase::Start => {
34 self.touch_started_inside = touch.within(viewport);
35 self.tap_candidate = self.touch_started_inside;
36 self.scroll_view.begin_drag(local_touch);
37 message = message.or(
38 self.set_highlighted_index(touched_index.filter(|_| self.touch_started_inside))
39 );
40 false
41 }
42 TouchPhase::Move => {
43 let changed =
44 self.scroll_view
45 .drag(local_touch, self.content_height(), viewport.size.height);
46 if changed || self.scroll_view.is_scrolling() {
47 self.tap_candidate = false;
48 message = message.or(self.set_highlighted_index(None));
49 } else {
50 let next_highlight = if self.touch_started_inside && touch.within(viewport) {
51 touched_index
52 } else {
53 None
54 };
55 message = message.or(self.set_highlighted_index(next_highlight));
56 }
57 changed
58 }
59 TouchPhase::End | TouchPhase::Cancel => {
60 let changed = self.scroll_view.end_drag(
61 local_touch,
62 self.content_height(),
63 viewport.size.height,
64 );
65
66 if matches!(touch.phase, TouchPhase::End)
67 && self.touch_started_inside
68 && self.tap_candidate
69 && touch.within(viewport)
70 {
71 if let Some(index) = touched_index {
72 if self.allows_selection {
73 self.selected_index = Some(index);
74 }
75 if let Some(selection) = self.selection_for_index(index) {
76 message = message.or(self.delegate.did_select_item(selection));
77 }
78 }
79 }
80
81 message = message.or(self.set_highlighted_index(None));
82 self.touch_started_inside = false;
83 self.tap_candidate = false;
84 changed
85 }
86 };
87
88 let visual_state_changed = previous_highlight != self.highlighted_index
89 || previous_selection != self.selected_index;
90 let motion_active = scrolled || self.scroll_view.is_scrolling();
91
92 if motion_active {
93 activity = ListActivity::Motion;
94 } else if visual_state_changed {
95 activity = ListActivity::Interactive;
96 }
97
98 ListEvent {
99 redraw: match activity {
100 ListActivity::None => ViewRedraw::None,
101 ListActivity::Interactive | ListActivity::Motion => ViewRedraw::Dirty(viewport),
102 },
103 captured: was_dragging || touch.within(viewport) || self.touch_started_inside,
104 message,
105 activity,
106 }
107 }Sourcepub fn content_offset_y(&self) -> i32
pub fn content_offset_y(&self) -> i32
Returns the integer content offset.
Examples found in repository?
19 pub fn content_offset_y(&self) -> i32 {
20 self.scroll_view.content_offset_y()
21 }
22
23 /// Returns the total content height.
24 pub fn content_height(&self) -> u32 {
25 (0..self.data_source.item_count())
26 .map(|index| self.data_source.item_height(index))
27 .sum()
28 }
29
30 /// Returns the selected row index, if any.
31 pub fn selected_index(&self) -> Option<usize> {
32 self.selected_index
33 .filter(|index| *index < self.data_source.item_count())
34 }
35
36 /// Returns the selected row payload, if any.
37 pub fn selected_item(&self) -> Option<ListSelection<DataSource::ItemId>> {
38 self.selection_for_index(self.selected_index()?)
39 }
40
41 /// Returns the highlighted row payload, if any.
42 pub fn highlighted_item(&self) -> Option<ListSelection<DataSource::ItemId>> {
43 self.selection_for_index(self.highlighted_index?)
44 }
45
46 /// Sets the selected row index.
47 pub fn set_selected_index(&mut self, index: Option<usize>) -> bool {
48 let normalized = index.filter(|index| *index < self.data_source.item_count());
49 if self.selected_index == normalized {
50 return false;
51 }
52 self.selected_index = normalized;
53 true
54 }
55
56 /// Clears row selection.
57 pub fn clear_selection(&mut self) -> bool {
58 self.set_selected_index(None)
59 }
60
61 /// Returns whether the vertical indicator is enabled.
62 pub fn shows_vertical_scroll_indicator(&self) -> bool {
63 self.scroll_view.shows_vertical_scroll_indicator()
64 }
65
66 /// Enables or disables the vertical indicator.
67 pub fn set_shows_vertical_scroll_indicator(&mut self, shows: bool) {
68 self.scroll_view.set_shows_vertical_scroll_indicator(shows);
69 }
70
71 /// Returns the current scrollbar thumb, if visible.
72 pub fn scroll_bar(&self, viewport: Rectangle) -> Option<ScrollBar> {
73 self.scroll_view.scroll_bar(viewport, self.content_height())
74 }
75
76 /// Returns the dirty rect for indicator updates, if any.
77 pub fn scroll_bar_dirty(&self, viewport: Rectangle) -> Option<Rectangle> {
78 self.scroll_view
79 .scroll_bar_dirty(viewport, self.content_height())
80 }
81
82 /// Returns the content rect used for scroll blitting.
83 pub fn motion_content_rect(&self, viewport: Rectangle) -> Rectangle {
84 self.scroll_view
85 .motion_content_rect(viewport, self.content_height())
86 }
87
88 /// Advances list animation state.
89 pub fn tick(&mut self, dt_ms: u32, viewport: Rectangle) -> ViewRedraw {
90 if self
91 .scroll_view
92 .tick(dt_ms, self.content_height(), viewport.size.height)
93 {
94 ViewRedraw::Dirty(viewport)
95 } else {
96 ViewRedraw::None
97 }
98 }
99
100 /// Returns the frame for one item index, even if only partially visible.
101 pub fn item_frame(&self, index: usize, viewport: Rectangle) -> Option<Rectangle> {
102 if index >= self.data_source.item_count() {
103 return None;
104 }
105
106 let mut cursor = self.scroll_view.content_offset_y();
107 for current in 0..self.data_source.item_count() {
108 let height = self.data_source.item_height(current);
109 let frame = Rectangle::new(
110 Point::new(viewport.top_left.x, viewport.top_left.y + cursor),
111 Size::new(viewport.size.width, height),
112 );
113 if current == index {
114 return Some(frame);
115 }
116 cursor += height as i32;
117 }
118 None
119 }
120
121 /// Draws the list and its scroll indicator.
122 pub fn draw<'text, D>(
123 &self,
124 display: &mut D,
125 viewport: Rectangle,
126 env: &ViewEnvironment<'_, 'text>,
127 ) where
128 D: DrawTarget<Color = Rgb565>,
129 Delegate: ListDelegate<'text, DataSource::ItemId>,
130 {
131 let mut cursor = self.scroll_view.content_offset_y();
132 let mut clipped = display.clipped(&viewport);
133 for index in 0..self.data_source.item_count() {
134 let height = self.data_source.item_height(index);
135 let frame = Rectangle::new(
136 Point::new(viewport.top_left.x, viewport.top_left.y + cursor),
137 Size::new(viewport.size.width, height),
138 );
139 if rects_intersect(frame, viewport) {
140 self.delegate.draw_row(
141 &mut clipped,
142 ListRow {
143 item: ListItem {
144 id: self.data_source.item_id(index),
145 index,
146 frame,
147 },
148 state: ListRowState {
149 selected: self.selected_index() == Some(index),
150 highlighted: self.highlighted_index == Some(index),
151 },
152 },
153 env,
154 );
155 }
156 cursor += height as i32;
157 }
158 self.scroll_view
159 .draw_scroll_bar(display, viewport, self.content_height(), env.theme);
160 }More examples
118 fn item_index_at_point(&self, point: Point, viewport: Rectangle) -> Option<usize> {
119 if !point_in_rect(point, viewport) {
120 return None;
121 }
122
123 let mut cursor = self.scroll_view.content_offset_y();
124 for index in 0..self.data_source.item_count() {
125 let height = self.data_source.item_height(index);
126 let frame = Rectangle::new(
127 Point::new(viewport.top_left.x, viewport.top_left.y + cursor),
128 embedded_graphics::prelude::Size::new(viewport.size.width, height),
129 );
130 if point_in_rect(point, frame) {
131 return Some(index);
132 }
133 cursor += height as i32;
134 }
135 None
136 }Sourcepub fn begin_drag(&mut self, touch: TouchEvent)
pub fn begin_drag(&mut self, touch: TouchEvent)
Starts a drag sequence.
Examples found in repository?
60fn main() {
61 let mut canvas = support::NullCanvas::new(Size::new(320, 240));
62 let viewport = Rectangle::new(Point::new(16, 16), Size::new(180, 160));
63
64 let mut scroll = ScrollView::new();
65 scroll.begin_drag(TouchEvent::new(Point::new(8, 8), TouchPhase::Start, 1));
66 let _ = scroll.drag(
67 TouchEvent::new(Point::new(8, 32), TouchPhase::Move, 2),
68 420,
69 160,
70 );
71 let _ = scroll.end_drag(
72 TouchEvent::new(Point::new(8, 32), TouchPhase::End, 3),
73 420,
74 160,
75 );
76 let _ = scroll.tick(16, 420, 160);
77 let _ = scroll.scroll_bar(viewport, 420);
78
79 let mut list = ListView::new(DemoDataSource, DemoDelegate);
80 let _ = list.handle_touch(
81 TouchEvent::new(Point::new(24, 24), TouchPhase::Start, 10),
82 viewport,
83 );
84 let _ = list.handle_touch(
85 TouchEvent::new(Point::new(24, 60), TouchPhase::Move, 11),
86 viewport,
87 );
88 let _ = list.handle_touch(
89 TouchEvent::new(Point::new(24, 60), TouchPhase::End, 12),
90 viewport,
91 );
92 list.draw(
93 &mut canvas,
94 viewport,
95 &ViewEnvironment {
96 theme: &support::theme(),
97 i18n: &support::i18n(),
98 },
99 );
100}More examples
12 pub fn handle_touch<'text>(
13 &mut self,
14 touch: TouchEvent,
15 viewport: Rectangle,
16 ) -> ListEvent<Delegate::Message>
17 where
18 Delegate: ListDelegate<'text, DataSource::ItemId>,
19 {
20 if !touch.within(viewport) && !self.scroll_view.is_dragging() {
21 return ListEvent::none();
22 }
23
24 let local_touch = offset_touch(touch, viewport.top_left);
25 let touched_index = self.item_index_at_point(touch.point, viewport);
26 let was_dragging = self.scroll_view.is_dragging();
27 let previous_highlight = self.highlighted_index;
28 let previous_selection = self.selected_index;
29 let mut activity = ListActivity::None;
30 let mut message = None;
31
32 let scrolled = match touch.phase {
33 TouchPhase::Start => {
34 self.touch_started_inside = touch.within(viewport);
35 self.tap_candidate = self.touch_started_inside;
36 self.scroll_view.begin_drag(local_touch);
37 message = message.or(
38 self.set_highlighted_index(touched_index.filter(|_| self.touch_started_inside))
39 );
40 false
41 }
42 TouchPhase::Move => {
43 let changed =
44 self.scroll_view
45 .drag(local_touch, self.content_height(), viewport.size.height);
46 if changed || self.scroll_view.is_scrolling() {
47 self.tap_candidate = false;
48 message = message.or(self.set_highlighted_index(None));
49 } else {
50 let next_highlight = if self.touch_started_inside && touch.within(viewport) {
51 touched_index
52 } else {
53 None
54 };
55 message = message.or(self.set_highlighted_index(next_highlight));
56 }
57 changed
58 }
59 TouchPhase::End | TouchPhase::Cancel => {
60 let changed = self.scroll_view.end_drag(
61 local_touch,
62 self.content_height(),
63 viewport.size.height,
64 );
65
66 if matches!(touch.phase, TouchPhase::End)
67 && self.touch_started_inside
68 && self.tap_candidate
69 && touch.within(viewport)
70 {
71 if let Some(index) = touched_index {
72 if self.allows_selection {
73 self.selected_index = Some(index);
74 }
75 if let Some(selection) = self.selection_for_index(index) {
76 message = message.or(self.delegate.did_select_item(selection));
77 }
78 }
79 }
80
81 message = message.or(self.set_highlighted_index(None));
82 self.touch_started_inside = false;
83 self.tap_candidate = false;
84 changed
85 }
86 };
87
88 let visual_state_changed = previous_highlight != self.highlighted_index
89 || previous_selection != self.selected_index;
90 let motion_active = scrolled || self.scroll_view.is_scrolling();
91
92 if motion_active {
93 activity = ListActivity::Motion;
94 } else if visual_state_changed {
95 activity = ListActivity::Interactive;
96 }
97
98 ListEvent {
99 redraw: match activity {
100 ListActivity::None => ViewRedraw::None,
101 ListActivity::Interactive | ListActivity::Motion => ViewRedraw::Dirty(viewport),
102 },
103 captured: was_dragging || touch.within(viewport) || self.touch_started_inside,
104 message,
105 activity,
106 }
107 }Sourcepub fn drag(
&mut self,
touch: TouchEvent,
content_height: u32,
viewport_height: u32,
) -> bool
pub fn drag( &mut self, touch: TouchEvent, content_height: u32, viewport_height: u32, ) -> bool
Updates dragging with a new touch sample.
Examples found in repository?
60fn main() {
61 let mut canvas = support::NullCanvas::new(Size::new(320, 240));
62 let viewport = Rectangle::new(Point::new(16, 16), Size::new(180, 160));
63
64 let mut scroll = ScrollView::new();
65 scroll.begin_drag(TouchEvent::new(Point::new(8, 8), TouchPhase::Start, 1));
66 let _ = scroll.drag(
67 TouchEvent::new(Point::new(8, 32), TouchPhase::Move, 2),
68 420,
69 160,
70 );
71 let _ = scroll.end_drag(
72 TouchEvent::new(Point::new(8, 32), TouchPhase::End, 3),
73 420,
74 160,
75 );
76 let _ = scroll.tick(16, 420, 160);
77 let _ = scroll.scroll_bar(viewport, 420);
78
79 let mut list = ListView::new(DemoDataSource, DemoDelegate);
80 let _ = list.handle_touch(
81 TouchEvent::new(Point::new(24, 24), TouchPhase::Start, 10),
82 viewport,
83 );
84 let _ = list.handle_touch(
85 TouchEvent::new(Point::new(24, 60), TouchPhase::Move, 11),
86 viewport,
87 );
88 let _ = list.handle_touch(
89 TouchEvent::new(Point::new(24, 60), TouchPhase::End, 12),
90 viewport,
91 );
92 list.draw(
93 &mut canvas,
94 viewport,
95 &ViewEnvironment {
96 theme: &support::theme(),
97 i18n: &support::i18n(),
98 },
99 );
100}More examples
12 pub fn handle_touch<'text>(
13 &mut self,
14 touch: TouchEvent,
15 viewport: Rectangle,
16 ) -> ListEvent<Delegate::Message>
17 where
18 Delegate: ListDelegate<'text, DataSource::ItemId>,
19 {
20 if !touch.within(viewport) && !self.scroll_view.is_dragging() {
21 return ListEvent::none();
22 }
23
24 let local_touch = offset_touch(touch, viewport.top_left);
25 let touched_index = self.item_index_at_point(touch.point, viewport);
26 let was_dragging = self.scroll_view.is_dragging();
27 let previous_highlight = self.highlighted_index;
28 let previous_selection = self.selected_index;
29 let mut activity = ListActivity::None;
30 let mut message = None;
31
32 let scrolled = match touch.phase {
33 TouchPhase::Start => {
34 self.touch_started_inside = touch.within(viewport);
35 self.tap_candidate = self.touch_started_inside;
36 self.scroll_view.begin_drag(local_touch);
37 message = message.or(
38 self.set_highlighted_index(touched_index.filter(|_| self.touch_started_inside))
39 );
40 false
41 }
42 TouchPhase::Move => {
43 let changed =
44 self.scroll_view
45 .drag(local_touch, self.content_height(), viewport.size.height);
46 if changed || self.scroll_view.is_scrolling() {
47 self.tap_candidate = false;
48 message = message.or(self.set_highlighted_index(None));
49 } else {
50 let next_highlight = if self.touch_started_inside && touch.within(viewport) {
51 touched_index
52 } else {
53 None
54 };
55 message = message.or(self.set_highlighted_index(next_highlight));
56 }
57 changed
58 }
59 TouchPhase::End | TouchPhase::Cancel => {
60 let changed = self.scroll_view.end_drag(
61 local_touch,
62 self.content_height(),
63 viewport.size.height,
64 );
65
66 if matches!(touch.phase, TouchPhase::End)
67 && self.touch_started_inside
68 && self.tap_candidate
69 && touch.within(viewport)
70 {
71 if let Some(index) = touched_index {
72 if self.allows_selection {
73 self.selected_index = Some(index);
74 }
75 if let Some(selection) = self.selection_for_index(index) {
76 message = message.or(self.delegate.did_select_item(selection));
77 }
78 }
79 }
80
81 message = message.or(self.set_highlighted_index(None));
82 self.touch_started_inside = false;
83 self.tap_candidate = false;
84 changed
85 }
86 };
87
88 let visual_state_changed = previous_highlight != self.highlighted_index
89 || previous_selection != self.selected_index;
90 let motion_active = scrolled || self.scroll_view.is_scrolling();
91
92 if motion_active {
93 activity = ListActivity::Motion;
94 } else if visual_state_changed {
95 activity = ListActivity::Interactive;
96 }
97
98 ListEvent {
99 redraw: match activity {
100 ListActivity::None => ViewRedraw::None,
101 ListActivity::Interactive | ListActivity::Motion => ViewRedraw::Dirty(viewport),
102 },
103 captured: was_dragging || touch.within(viewport) || self.touch_started_inside,
104 message,
105 activity,
106 }
107 }Sourcepub fn end_drag(
&mut self,
touch: TouchEvent,
content_height: u32,
viewport_height: u32,
) -> bool
pub fn end_drag( &mut self, touch: TouchEvent, content_height: u32, viewport_height: u32, ) -> bool
Ends dragging and starts any fling animation.
Examples found in repository?
60fn main() {
61 let mut canvas = support::NullCanvas::new(Size::new(320, 240));
62 let viewport = Rectangle::new(Point::new(16, 16), Size::new(180, 160));
63
64 let mut scroll = ScrollView::new();
65 scroll.begin_drag(TouchEvent::new(Point::new(8, 8), TouchPhase::Start, 1));
66 let _ = scroll.drag(
67 TouchEvent::new(Point::new(8, 32), TouchPhase::Move, 2),
68 420,
69 160,
70 );
71 let _ = scroll.end_drag(
72 TouchEvent::new(Point::new(8, 32), TouchPhase::End, 3),
73 420,
74 160,
75 );
76 let _ = scroll.tick(16, 420, 160);
77 let _ = scroll.scroll_bar(viewport, 420);
78
79 let mut list = ListView::new(DemoDataSource, DemoDelegate);
80 let _ = list.handle_touch(
81 TouchEvent::new(Point::new(24, 24), TouchPhase::Start, 10),
82 viewport,
83 );
84 let _ = list.handle_touch(
85 TouchEvent::new(Point::new(24, 60), TouchPhase::Move, 11),
86 viewport,
87 );
88 let _ = list.handle_touch(
89 TouchEvent::new(Point::new(24, 60), TouchPhase::End, 12),
90 viewport,
91 );
92 list.draw(
93 &mut canvas,
94 viewport,
95 &ViewEnvironment {
96 theme: &support::theme(),
97 i18n: &support::i18n(),
98 },
99 );
100}More examples
12 pub fn handle_touch<'text>(
13 &mut self,
14 touch: TouchEvent,
15 viewport: Rectangle,
16 ) -> ListEvent<Delegate::Message>
17 where
18 Delegate: ListDelegate<'text, DataSource::ItemId>,
19 {
20 if !touch.within(viewport) && !self.scroll_view.is_dragging() {
21 return ListEvent::none();
22 }
23
24 let local_touch = offset_touch(touch, viewport.top_left);
25 let touched_index = self.item_index_at_point(touch.point, viewport);
26 let was_dragging = self.scroll_view.is_dragging();
27 let previous_highlight = self.highlighted_index;
28 let previous_selection = self.selected_index;
29 let mut activity = ListActivity::None;
30 let mut message = None;
31
32 let scrolled = match touch.phase {
33 TouchPhase::Start => {
34 self.touch_started_inside = touch.within(viewport);
35 self.tap_candidate = self.touch_started_inside;
36 self.scroll_view.begin_drag(local_touch);
37 message = message.or(
38 self.set_highlighted_index(touched_index.filter(|_| self.touch_started_inside))
39 );
40 false
41 }
42 TouchPhase::Move => {
43 let changed =
44 self.scroll_view
45 .drag(local_touch, self.content_height(), viewport.size.height);
46 if changed || self.scroll_view.is_scrolling() {
47 self.tap_candidate = false;
48 message = message.or(self.set_highlighted_index(None));
49 } else {
50 let next_highlight = if self.touch_started_inside && touch.within(viewport) {
51 touched_index
52 } else {
53 None
54 };
55 message = message.or(self.set_highlighted_index(next_highlight));
56 }
57 changed
58 }
59 TouchPhase::End | TouchPhase::Cancel => {
60 let changed = self.scroll_view.end_drag(
61 local_touch,
62 self.content_height(),
63 viewport.size.height,
64 );
65
66 if matches!(touch.phase, TouchPhase::End)
67 && self.touch_started_inside
68 && self.tap_candidate
69 && touch.within(viewport)
70 {
71 if let Some(index) = touched_index {
72 if self.allows_selection {
73 self.selected_index = Some(index);
74 }
75 if let Some(selection) = self.selection_for_index(index) {
76 message = message.or(self.delegate.did_select_item(selection));
77 }
78 }
79 }
80
81 message = message.or(self.set_highlighted_index(None));
82 self.touch_started_inside = false;
83 self.tap_candidate = false;
84 changed
85 }
86 };
87
88 let visual_state_changed = previous_highlight != self.highlighted_index
89 || previous_selection != self.selected_index;
90 let motion_active = scrolled || self.scroll_view.is_scrolling();
91
92 if motion_active {
93 activity = ListActivity::Motion;
94 } else if visual_state_changed {
95 activity = ListActivity::Interactive;
96 }
97
98 ListEvent {
99 redraw: match activity {
100 ListActivity::None => ViewRedraw::None,
101 ListActivity::Interactive | ListActivity::Motion => ViewRedraw::Dirty(viewport),
102 },
103 captured: was_dragging || touch.within(viewport) || self.touch_started_inside,
104 message,
105 activity,
106 }
107 }Sourcepub fn tick(
&mut self,
dt_ms: u32,
content_height: u32,
viewport_height: u32,
) -> bool
pub fn tick( &mut self, dt_ms: u32, content_height: u32, viewport_height: u32, ) -> bool
Advances animation and indicator fade state.
Examples found in repository?
60fn main() {
61 let mut canvas = support::NullCanvas::new(Size::new(320, 240));
62 let viewport = Rectangle::new(Point::new(16, 16), Size::new(180, 160));
63
64 let mut scroll = ScrollView::new();
65 scroll.begin_drag(TouchEvent::new(Point::new(8, 8), TouchPhase::Start, 1));
66 let _ = scroll.drag(
67 TouchEvent::new(Point::new(8, 32), TouchPhase::Move, 2),
68 420,
69 160,
70 );
71 let _ = scroll.end_drag(
72 TouchEvent::new(Point::new(8, 32), TouchPhase::End, 3),
73 420,
74 160,
75 );
76 let _ = scroll.tick(16, 420, 160);
77 let _ = scroll.scroll_bar(viewport, 420);
78
79 let mut list = ListView::new(DemoDataSource, DemoDelegate);
80 let _ = list.handle_touch(
81 TouchEvent::new(Point::new(24, 24), TouchPhase::Start, 10),
82 viewport,
83 );
84 let _ = list.handle_touch(
85 TouchEvent::new(Point::new(24, 60), TouchPhase::Move, 11),
86 viewport,
87 );
88 let _ = list.handle_touch(
89 TouchEvent::new(Point::new(24, 60), TouchPhase::End, 12),
90 viewport,
91 );
92 list.draw(
93 &mut canvas,
94 viewport,
95 &ViewEnvironment {
96 theme: &support::theme(),
97 i18n: &support::i18n(),
98 },
99 );
100}More examples
Sourcepub fn scroll_bar(
&self,
viewport: Rectangle,
content_height: u32,
) -> Option<ScrollBar>
pub fn scroll_bar( &self, viewport: Rectangle, content_height: u32, ) -> Option<ScrollBar>
Returns the current scrollbar thumb geometry, if visible.
Examples found in repository?
60fn main() {
61 let mut canvas = support::NullCanvas::new(Size::new(320, 240));
62 let viewport = Rectangle::new(Point::new(16, 16), Size::new(180, 160));
63
64 let mut scroll = ScrollView::new();
65 scroll.begin_drag(TouchEvent::new(Point::new(8, 8), TouchPhase::Start, 1));
66 let _ = scroll.drag(
67 TouchEvent::new(Point::new(8, 32), TouchPhase::Move, 2),
68 420,
69 160,
70 );
71 let _ = scroll.end_drag(
72 TouchEvent::new(Point::new(8, 32), TouchPhase::End, 3),
73 420,
74 160,
75 );
76 let _ = scroll.tick(16, 420, 160);
77 let _ = scroll.scroll_bar(viewport, 420);
78
79 let mut list = ListView::new(DemoDataSource, DemoDelegate);
80 let _ = list.handle_touch(
81 TouchEvent::new(Point::new(24, 24), TouchPhase::Start, 10),
82 viewport,
83 );
84 let _ = list.handle_touch(
85 TouchEvent::new(Point::new(24, 60), TouchPhase::Move, 11),
86 viewport,
87 );
88 let _ = list.handle_touch(
89 TouchEvent::new(Point::new(24, 60), TouchPhase::End, 12),
90 viewport,
91 );
92 list.draw(
93 &mut canvas,
94 viewport,
95 &ViewEnvironment {
96 theme: &support::theme(),
97 i18n: &support::i18n(),
98 },
99 );
100}More examples
158 pub fn draw_scroll_bar<D>(
159 &self,
160 display: &mut D,
161 viewport: Rectangle,
162 content_height: u32,
163 theme: &FsTheme,
164 ) where
165 D: DrawTarget<Color = Rgb565>,
166 {
167 if let Some(indicator) = self.scroll_bar(viewport, content_height) {
168 draw_scrollbar(display, indicator, theme);
169 }
170 }Sourcepub fn scroll_bar_dirty(
&self,
viewport: Rectangle,
content_height: u32,
) -> Option<Rectangle>
pub fn scroll_bar_dirty( &self, viewport: Rectangle, content_height: u32, ) -> Option<Rectangle>
Returns the viewport area that may be affected by scrollbar updates.
Sourcepub fn motion_content_rect(
&self,
viewport: Rectangle,
content_height: u32,
) -> Rectangle
pub fn motion_content_rect( &self, viewport: Rectangle, content_height: u32, ) -> Rectangle
Returns the motion content rect, excluding reserved indicator gutter.
Sourcepub fn draw_scroll_bar<D>(
&self,
display: &mut D,
viewport: Rectangle,
content_height: u32,
theme: &FsTheme,
)where
D: DrawTarget<Color = Rgb565>,
pub fn draw_scroll_bar<D>(
&self,
display: &mut D,
viewport: Rectangle,
content_height: u32,
theme: &FsTheme,
)where
D: DrawTarget<Color = Rgb565>,
Draws the vertical scrollbar thumb.
Examples found in repository?
122 pub fn draw<'text, D>(
123 &self,
124 display: &mut D,
125 viewport: Rectangle,
126 env: &ViewEnvironment<'_, 'text>,
127 ) where
128 D: DrawTarget<Color = Rgb565>,
129 Delegate: ListDelegate<'text, DataSource::ItemId>,
130 {
131 let mut cursor = self.scroll_view.content_offset_y();
132 let mut clipped = display.clipped(&viewport);
133 for index in 0..self.data_source.item_count() {
134 let height = self.data_source.item_height(index);
135 let frame = Rectangle::new(
136 Point::new(viewport.top_left.x, viewport.top_left.y + cursor),
137 Size::new(viewport.size.width, height),
138 );
139 if rects_intersect(frame, viewport) {
140 self.delegate.draw_row(
141 &mut clipped,
142 ListRow {
143 item: ListItem {
144 id: self.data_source.item_id(index),
145 index,
146 frame,
147 },
148 state: ListRowState {
149 selected: self.selected_index() == Some(index),
150 highlighted: self.highlighted_index == Some(index),
151 },
152 },
153 env,
154 );
155 }
156 cursor += height as i32;
157 }
158 self.scroll_view
159 .draw_scroll_bar(display, viewport, self.content_height(), env.theme);
160 }Trait Implementations§
Source§impl Clone for ScrollView
impl Clone for ScrollView
Source§fn clone(&self) -> ScrollView
fn clone(&self) -> ScrollView
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more