From 992f568ac78ed19d1583b362234fc24f2f5c032c Mon Sep 17 00:00:00 2001 From: Dominik Honnef Date: Thu, 30 Jun 2022 01:21:06 +0200 Subject: [PATCH] widget: when clicking on scrollbar, center on that point Previously, we'd scroll so the new viewportStart corresponded to the clicked position. This felt okay if clicking above the current indicator, but felt jarring when clicking below it. Centering gives a consistent behavior regardless of the scroll direction. Signed-off-by: Dominik Honnef --- widget/list.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/widget/list.go b/widget/list.go index 32fcbd80..9c1b9562 100644 --- a/widget/list.go +++ b/widget/list.go @@ -46,6 +46,20 @@ func (s *Scrollbar) Layout(gtx layout.Context, axis layout.Axis, viewportStart, trackHeight := float32(axis.Convert(gtx.Constraints.Max).X) s.delta = 0 + centerOnClick := func(normalizedPos float32) { + // When the user clicks on the scrollbar we center on that point, respecting the limits of the beginning and end + // of the scrollbar. + // + // Centering gives a consistent experience whether the user clicks above or below the indicator. + target := normalizedPos - (viewportEnd-viewportStart)/2 + s.delta += target - viewportStart + if s.delta < -viewportStart { + s.delta = -viewportStart + } else if s.delta > 1-viewportEnd { + s.delta = 1 - viewportEnd + } + } + // Jump to a click in the track. for _, event := range s.track.Events(gtx) { if event.Type != gesture.TypeClick || @@ -61,7 +75,7 @@ func (s *Scrollbar) Layout(gtx layout.Context, axis layout.Axis, viewportStart, // Clicking on the indicator should not jump to that position on the track. The user might've just intended to // drag and changed their mind. if !(normalizedPos >= viewportStart && normalizedPos <= viewportEnd) { - s.delta += normalizedPos - viewportStart + centerOnClick(normalizedPos) } } @@ -100,7 +114,7 @@ func (s *Scrollbar) Layout(gtx layout.Context, axis layout.Axis, viewportStart, Y: int(event.Position.Y), }) normalizedPos := float32(pos.X) / trackHeight - s.delta += normalizedPos - viewportStart + centerOnClick(normalizedPos) } } else { s.delta += normalizedDragOffset - s.oldDragPos