Skip to content

Commit

Permalink
fix(droid): bringintoview for not visible items
Browse files Browse the repository at this point in the history
  • Loading branch information
ajpinedam committed May 4, 2023
1 parent f79cc9c commit 5e0c4fe
Showing 1 changed file with 47 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Uno.UI.Extensions;
using Uno.UI.DataBinding;
using Windows.Networking.NetworkOperators;
using Android.Views.Animations;

namespace Windows.UI.Xaml.Controls
{
Expand Down Expand Up @@ -2670,6 +2671,13 @@ private class VirtualizingPanelSmoothScroller : LinearSmoothScroller
{
private const float BaseDuration = 250f, ScalableDuration = 150f; // in ms

private const int TARGET_SEEK_SCROLL_DISTANCE_PX = 10000;

// Trigger a scroll to a further distance than TARGET_SEEK_SCROLL_DISTANCE_PX so that if target
// view is not laid out until interim target position is reached, we can detect the case before
// scrolling slows down and reschedule another interim target scroll
private const float TARGET_SEEK_EXTRA_SCROLL_RATIO = 1.2f;

private readonly VirtualizingPanelLayout _layout;
private readonly RecyclerView.State _state;

Expand All @@ -2681,6 +2689,45 @@ public VirtualizingPanelSmoothScroller(VirtualizingPanelLayout layout, RecyclerV

public override PointF ComputeScrollVectorForPosition(int targetPosition) => _layout.ComputeScrollVectorForPosition(targetPosition);

protected override void UpdateActionForInterimTarget(Action action)
{
// find an interim target position
var scrollVector = ComputeScrollVectorForPosition(TargetPosition); // direction only, not magniture WHERE x and y are in {-1,0,1}
if (scrollVector == null || (scrollVector.X == 0 && scrollVector.Y == 0))
{
var target = TargetPosition;
action.JumpTo(target);
Stop();
return;
}

Normalize(scrollVector);
MTargetVector = scrollVector;
MInterimTargetDx = (int)(TARGET_SEEK_SCROLL_DISTANCE_PX * scrollVector.X);
MInterimTargetDy = (int)(TARGET_SEEK_SCROLL_DISTANCE_PX * scrollVector.Y);

var extend = _layout.ComputeVerticalScrollExtent(_state);
MInterimTargetDx = Math.Min(MInterimTargetDx, extend);
MInterimTargetDy = Math.Min(MInterimTargetDy, extend);

var time = CalculateTimeForScrolling(extend);

// To avoid UI hiccups, trigger a smooth scroll to a distance little further than the
// interim target. Since we track the distance travelled in onSeekTargetStep callback, it
// won't actually scroll more than what we need.
ActionUpdate(
(int)(MInterimTargetDx * TARGET_SEEK_EXTRA_SCROLL_RATIO),
(int)(MInterimTargetDy * TARGET_SEEK_EXTRA_SCROLL_RATIO),
(int)(time * TARGET_SEEK_EXTRA_SCROLL_RATIO),
MLinearInterpolator
);

void ActionUpdate(int dx, int dy, int duration, IInterpolator interpolator)
{
action.Update(dx, dy, duration, interpolator);
}
}

// The time (in ms) it should take for each pixel. For instance, if returned value is 2 ms,
// it means scrolling 1000 pixels with LinearInterpolation should take 2 seconds.
protected override float CalculateSpeedPerPixel(Android.Util.DisplayMetrics displayMetrics)
Expand Down

0 comments on commit 5e0c4fe

Please sign in to comment.