Skip to content

Commit

Permalink
fix(listview): [Android] Fix glitches during drag-and-drop
Browse files Browse the repository at this point in the history
Address issues when dragging, particularly when there are too few items to fill the available viewport.
  • Loading branch information
davidjohnoliver committed Aug 12, 2021
1 parent baa0fc1 commit df5a4ed
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ protected enum ViewType { Item, GroupHeader, Header, Footer }
/// </summary>
private int _pendingReorderScrollAdjustment = 0;

private bool IsReordering => GetAndUpdateReorderingIndex() != null;

public VirtualizingPanelLayout()
{
ResetLayoutInfo();
Expand Down Expand Up @@ -1216,7 +1218,12 @@ private void UpdateLayout(GeneratorDirection direction, int availableExtent, int
/// </summary>
private void UpdateScrollPositionForPaddingChanges(RecyclerView.Recycler recycler, RecyclerView.State state)
{
if (XamlParent?.NativePanel != null && XamlParent.NativePanel.ChildCount > 0)
if (
XamlParent?.NativePanel != null &&
XamlParent.NativePanel.ChildCount > 0 &&
// Skip this correction when reordering, since we rely on the assumption while reordering that only dragging will cause a scroll
!IsReordering
)
{
var gapToStart = GetContentStart();
if (gapToStart > 0)
Expand Down Expand Up @@ -1316,7 +1323,17 @@ private void FillLayout(GeneratorDirection direction, int scrollOffset, int avai

AssertValidState();

var nextItemPath = GetNextUnmaterializedItem(direction, _dynamicSeedIndex ?? GetLeadingMaterializedItem(direction));
Uno.UI.IndexPath? GetLeading()
{
var leading = GetLeadingMaterializedItem(direction);
if (_pendingReorder?.index is { } reorderingIndex && reorderingIndex == leading)
{
// Don't count the currently reordering item when getting the leading item, since the reordering item is generally out of order
leading = GetLeadingMaterializedItem(direction, i => i != reorderingIndex);
}
return leading;
}
var nextItemPath = GetNextUnmaterializedItem(direction, _dynamicSeedIndex ?? GetLeading());
while (nextItemPath != null)
{
//Handle the case there are no groups, this may happen during a lightweight rebuild of the layout.
Expand Down Expand Up @@ -1619,7 +1636,7 @@ private void UnfillLayout(GeneratorDirection direction, int offset, int availabl
/// </remarks>
private void TryTrimReorderingView(GeneratorDirection fillDirection, RecyclerView.Recycler recycler)
{
if (GetAndUpdateReorderingIndex() is { } reorderingIndex)
if (IsReordering)
{
// Keep at least one item materialized as a seed
while (ItemViewCount > 1)
Expand Down Expand Up @@ -2383,10 +2400,10 @@ private int GetFooterViewIndex()
/// return the top-most item.
/// </summary>
private Uno.UI.IndexPath? GetLeadingMaterializedItem(GeneratorDirection fillDirection)
{
var group = GetLeadingNonEmptyGroup(fillDirection);
return group?.GetLeadingMaterializedItem(fillDirection);
}
=> GetLeadingNonEmptyGroup(fillDirection)?.GetLeadingMaterializedItem(fillDirection);

private Uno.UI.IndexPath? GetLeadingMaterializedItem(GeneratorDirection fillDirection, Func<Uno.UI.IndexPath, bool> condition)
=> GetLeadingNonEmptyGroup(fillDirection)?.GetLeadingMaterializedItem(fillDirection, condition);

private View GetLeadingItemView(GeneratorDirection fillDirection)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Linq;
using Windows.UI.Xaml.Controls.Primitives;
using System.Diagnostics;
using Uno.Extensions;

namespace Windows.UI.Xaml.Controls
{
Expand Down Expand Up @@ -146,6 +147,7 @@ public Line GetLeadingLine(GeneratorDirection fillDirection, Func<Uno.UI.IndexPa

public void AddLine(Line newLine, GeneratorDirection fillDirection)
{
Debug.Assert(_lines.None(l => l.FirstItem == newLine.FirstItem), "Duplicate line detected");
if (fillDirection == GeneratorDirection.Forward)
{
_lines.AddToBack(newLine);
Expand Down Expand Up @@ -185,6 +187,13 @@ public Uno.UI.IndexPath GetLeadingMaterializedItem(GeneratorDirection fillDirect
GetFirstLine().FirstItem;
}

public Uno.UI.IndexPath GetLeadingMaterializedItem(GeneratorDirection fillDirection, Func<Uno.UI.IndexPath, bool> condition)
{
return fillDirection == GeneratorDirection.Forward ?
GetLastLine(condition).LastItem :
GetFirstLine(condition).FirstItem;
}

public Uno.UI.IndexPath GetTrailingMaterializedItem(GeneratorDirection fillDirection)
{
return fillDirection == GeneratorDirection.Forward ?
Expand Down

0 comments on commit df5a4ed

Please sign in to comment.