widget,widget/material: scroll using only drag position delta

This commit is based on a patch by Elias that improved drag scrolling
on the scrollbar by locking some parameters of the math at the start
of the scroll event.

I discovered while playing with that implementation that there was
an even simpler approach within his changeset. You can actually
use no information other than the delta between the current and
previous frame's scroll position to compute the scroll distance.
By simplifying the math to rely on no other inputs, the jitter that
we've been fighting simply disappears (it came from other inputs).

Turns out my attempts to make the logic smart were the problem.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
This commit is contained in:
Elias Naur
2021-09-16 12:29:09 -04:00
parent c9d85c97e1
commit 799ee3374d
2 changed files with 19 additions and 4 deletions
+18 -2
View File
@@ -24,6 +24,9 @@ type Scrollbar struct {
track, indicator gesture.Click
drag gesture.Drag
delta float32
dragging bool
oldDragPos float32
}
// Layout updates the internal state of the scrollbar based on events
@@ -60,12 +63,25 @@ func (s *Scrollbar) Layout(gtx layout.Context, axis layout.Axis, viewportStart,
// Offset to account for any drags.
for _, event := range s.drag.Events(gtx.Metric, gtx, gesture.Axis(axis)) {
if event.Type != pointer.Drag {
switch event.Type {
case pointer.Drag:
case pointer.Release:
s.dragging = false
case pointer.Cancel:
s.dragging = false
continue
default:
continue
}
dragOffset := axis.FConvert(event.Position).X
normalizedDragOffset := dragOffset / trackHeight
s.delta += normalizedDragOffset - viewportStart
if !s.dragging {
s.dragging = true
s.oldDragPos = normalizedDragOffset
}
s.delta += normalizedDragOffset - s.oldDragPos
s.oldDragPos = normalizedDragOffset
}
// Process events from the indicator so that hover is
+1 -2
View File
@@ -285,8 +285,7 @@ func (l ListStyle) Layout(gtx layout.Context, length int, w layout.ListElement)
if delta := l.state.ScrollDistance(); delta != 0 {
// Handle any changes to the list position as a result of user interaction
// with the scrollbar.
deltaPx := int(math.Round(float64(float32(l.state.Position.Length) * delta)))
l.state.List.Position.Offset += deltaPx
l.state.List.Position.Offset += int(math.Round(float64(float32(l.state.Position.Length) * delta)))
// Ensure that the list pays attention to the Offset field when the scrollbar drag
// is started while the bar is at the end of the list. Without this, the scrollbar