Skip to content

Commit d5bf990

Browse files
authored
Merge pull request #15 from Redth/scroll-to-item
Add ScrollToItem
2 parents 406f8ee + 6ec23c3 commit d5bf990

File tree

8 files changed

+72
-5
lines changed

8 files changed

+72
-5
lines changed

Sample/VirtualListViewSample/ObservableCollectionPage.xaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
xmlns:local="clr-namespace:VirtualListViewSample"
77
xmlns:vlv="clr-namespace:Microsoft.Maui.Controls;assembly=VirtualListView"
88
Title="ObservableCollectionPage">
9-
<Grid RowDefinitions="*,Auto" ColumnDefinitions="*,Auto" Padding="20">
9+
<Grid RowDefinitions="*,Auto" ColumnDefinitions="*,Auto,Auto" Padding="20">
1010
<vlv:VirtualListView
1111
Grid.Row="0"
12-
Grid.Column="0" Grid.ColumnSpan="2"
12+
Grid.Column="0" Grid.ColumnSpan="3"
1313
x:Name="vlv"
1414
OnSelectedItemsChanged="vlv_SelectedItemsChanged"
1515
SelectionMode="Multiple">
@@ -39,5 +39,6 @@
3939

4040
<Entry x:Name="entryItem" Grid.Row="1" Grid.Column="0" Placeholder="Item" />
4141
<Button Grid.Row="1" Grid.Column="1" Text="Add" Clicked="Button_Clicked" />
42+
<Button Grid.Row="1" Grid.Column="2" Text="Scroll To" Clicked="ScrollTo_Clicked" />
4243
</Grid>
4344
</ContentPage>

Sample/VirtualListViewSample/ObservableCollectionPage.xaml.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public ObservableCollectionPage()
1111

1212
Adapter = new ObservableCollectionAdapter<string>(Items);
1313

14-
for (int i = 0; i < 10; i++)
14+
for (int i = 0; i < 100; i++)
1515
{
1616
Items.Add($"Item: {i}");
1717
}
@@ -61,4 +61,16 @@ private void vlv_SelectedItemsChanged(object sender, SelectedItemsChangedEventAr
6161
Items.Remove(item);
6262
}
6363
}
64+
65+
private void ScrollTo_Clicked(object sender, EventArgs e)
66+
{
67+
if (!string.IsNullOrEmpty(entryItem.Text))
68+
{
69+
var item = Items.FirstOrDefault(i => i.Equals(entryItem.Text, StringComparison.InvariantCultureIgnoreCase));
70+
71+
var itemIndex = Items.IndexOf(item);
72+
73+
vlv.ScrollToItem(new ItemPosition(0, itemIndex), true);
74+
}
75+
}
6476
}

VirtualListView/Apple/VirtualListViewHandler.ios.maccatalyst.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ protected override void ConnectHandler(UICollectionView nativeView)
6666
VirtualView?.Scrolled(x, y));
6767

6868
nativeView.DataSource = dataSource;
69-
nativeView.Delegate = cvdelegate;
69+
nativeView.Delegate = cvdelegate;
7070

7171
nativeView.ReloadData();
7272
}
@@ -123,6 +123,18 @@ public static void MapSelectionMode(VirtualListViewHandler handler, IVirtualList
123123
public static void MapInvalidateData(VirtualListViewHandler handler, IVirtualListView virtualListView, object? parameter)
124124
=> handler?.InvalidateData();
125125

126+
void PlatformScrollToItem(ItemPosition itemPosition, bool animated)
127+
{
128+
var realIndex = PositionalViewSelector?.GetPosition(itemPosition.SectionIndex, itemPosition.ItemIndex) ?? -1;
129+
130+
if (realIndex < 0)
131+
return;
132+
133+
var indexPath = NSIndexPath.FromItemSection(realIndex, 0);
134+
135+
PlatformView.ScrollToItem(indexPath, UICollectionViewScrollPosition.Top, animated);
136+
}
137+
126138
void PlatformUpdateItemSelection(ItemPosition itemPosition, bool selected)
127139
{
128140
var realIndex = PositionalViewSelector?.GetPosition(itemPosition.SectionIndex, itemPosition.ItemIndex) ?? -1;
@@ -134,7 +146,7 @@ void PlatformUpdateItemSelection(ItemPosition itemPosition, bool selected)
134146

135147
if (cell is CvCell cvcell)
136148
{
137-
PlatformView.InvokeOnMainThread(() =>
149+
PlatformView.InvokeOnMainThread(() =>
138150
{
139151
cvcell.UpdateSelected(selected);
140152
});

VirtualListView/Controls/VirtualListView.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,9 @@ public void ClearSelectedItems()
311311
SelectedItem = null;
312312
}
313313

314+
public void ScrollToItem(ItemPosition itemPosition, bool animated)
315+
=> Handler?.Invoke(nameof(ScrollToItem), new object[] { itemPosition, animated });
316+
314317
public bool SectionHasHeader(int sectionIndex)
315318
=> SectionHeaderTemplateSelector != null || SectionHeaderTemplate != null;
316319

VirtualListView/IVirtualListView.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public interface IVirtualListView : IView
4343
void DeselectItem(ItemPosition path);
4444

4545
void ClearSelectedItems();
46+
47+
void ScrollToItem(ItemPosition path, bool animated);
4648
}
4749

4850
public enum ListOrientation

VirtualListView/Platforms/Android/VirtualListViewHandler.android.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ public void InvalidateData()
7878
adapter?.NotifyDataSetChanged();
7979
}
8080

81+
void PlatformScrollToItem(ItemPosition itemPosition, bool animated)
82+
{
83+
var position = PositionalViewSelector.GetPosition(itemPosition.SectionIndex, itemPosition.ItemIndex);
84+
85+
recyclerView.ScrollToPosition(position);
86+
}
87+
8188
public static void MapHeader(VirtualListViewHandler handler, IVirtualListView virtualListView)
8289
=> handler.InvalidateData();
8390

VirtualListView/Platforms/Windows/VirtualListViewHandler.windows.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using WVisibility = Microsoft.UI.Xaml.Visibility;
66
using WFrameworkElement = Microsoft.UI.Xaml.FrameworkElement;
77
using Microsoft.Maui.Platform;
8+
using Microsoft.UI.Xaml;
89

910
namespace Microsoft.Maui;
1011

@@ -86,6 +87,15 @@ public void InvalidateData()
8687
UpdateEmptyViewVisibility();
8788
}
8889

90+
void PlatformScrollToItem(ItemPosition itemPosition, bool animated)
91+
{
92+
var position = PositionalViewSelector.GetPosition(itemPosition.SectionIndex, itemPosition.ItemIndex);
93+
94+
var elem = itemsRepeater.GetOrCreateElement(position);
95+
96+
elem.StartBringIntoView(new BringIntoViewOptions() { AnimationDesired = animated });
97+
}
98+
8999
public static void MapHeader(VirtualListViewHandler handler, IVirtualListView virtualListView)
90100
=> handler?.InvalidateData();
91101

VirtualListView/VirtualListViewHandler.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,28 @@ public partial class VirtualListViewHandler
2222

2323
public static CommandMapper<IVirtualListView, VirtualListViewHandler> CommandMapper = new(ViewCommandMapper)
2424
{
25+
[nameof(IVirtualListView.ScrollToItem)] = MapScrollToItem,
2526
};
2627

28+
public static void MapScrollToItem(VirtualListViewHandler handler, IVirtualListView view, object parameter)
29+
{
30+
if (parameter is ItemPosition itemPosition)
31+
{
32+
handler.PlatformScrollToItem(itemPosition, true);
33+
}
34+
else if (parameter is object[] parameters)
35+
{
36+
if (parameters?[0] is ItemPosition p)
37+
{
38+
var animated = true;
39+
if (parameters?[1] is bool a)
40+
animated = a;
41+
42+
handler.PlatformScrollToItem(p, animated);
43+
}
44+
}
45+
}
46+
2747
public VirtualListViewHandler() : base(ViewMapper, CommandMapper)
2848
{
2949

0 commit comments

Comments
 (0)