Merge pull request #4129 from Vijay-Nirmal/SmoothScrollMadeAsync
Changed SmoothScrollIntoView method to be truly asynchronous
This commit is contained in:
Коммит
51cbc9a109
|
@ -35,14 +35,16 @@
|
|||
</Grid>
|
||||
|
||||
<StackPanel Grid.Column="1" Margin="5,10,10,0" Width="200">
|
||||
<TextBlock Text="Smooth Scroll Settings" FontSize="{StaticResource TextStyleLargeFontSize}" Margin="0,0,0,10"/>
|
||||
<TextBlock Text="Smooth Scroll Settings" FontSize="{StaticResource TextStyleLargeFontSize}"/>
|
||||
<TextBox x:Name="IndexInput"
|
||||
Header="Index"
|
||||
InputScope="Number"
|
||||
Text="100" />
|
||||
Text="100"
|
||||
Margin="0,10,0,0" />
|
||||
<ComboBox x:Name="ItemPlacementInput"
|
||||
Header="Item Placement"
|
||||
SelectedIndex="0">
|
||||
SelectedIndex="0"
|
||||
Margin="0,10,0,0" >
|
||||
<x:String>Default</x:String>
|
||||
<x:String>Left</x:String>
|
||||
<x:String>Top</x:String>
|
||||
|
@ -52,18 +54,25 @@
|
|||
</ComboBox>
|
||||
<CheckBox x:Name="DisableAnimationInput"
|
||||
Content="Disable Animation"
|
||||
IsChecked="False" />
|
||||
IsChecked="False"
|
||||
Margin="0,10,0,0" />
|
||||
<CheckBox x:Name="ScrollIfVisibileInput"
|
||||
Content="Scroll If Visible"
|
||||
IsChecked="True" />
|
||||
<TextBox x:Name="AdditionalHorizontalOffsetInput"
|
||||
Header="Horizontal Offset"
|
||||
InputScope="Number"
|
||||
Text="0" />
|
||||
Text="0"
|
||||
Margin="0,10,0,0" />
|
||||
<TextBox x:Name="AdditionalVerticalOffsetInput"
|
||||
Header="Vertical Offset"
|
||||
InputScope="Number"
|
||||
Text="0" />
|
||||
Text="0"
|
||||
Margin="0,10,0,0" />
|
||||
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
|
||||
<Ellipse x:Name="ScrollIndicator" Fill="Red" Width="15" Height="15"/>
|
||||
<TextBlock x:Name="ScrollIndicatorTest" Text="Not Scrolling" Margin="10,0,0,0"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Page>
|
||||
</Page>
|
||||
|
|
|
@ -6,9 +6,11 @@ using System;
|
|||
using System.Collections.ObjectModel;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.Toolkit.Uwp.UI;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Popups;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
||||
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
|
||||
{
|
||||
|
@ -37,7 +39,7 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
|
|||
|
||||
private void Load()
|
||||
{
|
||||
SampleController.Current.RegisterNewCommand("Start Smooth Scroll", (sender, args) =>
|
||||
SampleController.Current.RegisterNewCommand("Start Smooth Scroll", async (sender, args) =>
|
||||
{
|
||||
var index = int.TryParse(IndexInput.Text, out var i) ? i : 0;
|
||||
var itemPlacement = ItemPlacementInput.SelectedItem switch
|
||||
|
@ -55,7 +57,9 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
|
|||
var scrollIfVisibile = ScrollIfVisibileInput.IsChecked ?? true;
|
||||
var additionalHorizontalOffset = int.TryParse(AdditionalHorizontalOffsetInput.Text, out var ho) ? ho : 0;
|
||||
var additionalVerticalOffset = int.TryParse(AdditionalVerticalOffsetInput.Text, out var vo) ? vo : 0;
|
||||
sampleListView.SmoothScrollIntoViewWithIndexAsync(index, itemPlacement, disableAnimation, scrollIfVisibile, additionalHorizontalOffset, additionalVerticalOffset);
|
||||
UpdateScrollIndicator(true);
|
||||
await sampleListView.SmoothScrollIntoViewWithIndexAsync(index, itemPlacement, disableAnimation, scrollIfVisibile, additionalHorizontalOffset, additionalVerticalOffset);
|
||||
UpdateScrollIndicator(false);
|
||||
});
|
||||
|
||||
if (sampleListView != null)
|
||||
|
@ -64,6 +68,20 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
|
|||
}
|
||||
}
|
||||
|
||||
private void UpdateScrollIndicator(bool isScrolling)
|
||||
{
|
||||
if (isScrolling)
|
||||
{
|
||||
ScrollIndicatorTest.Text = "Scrolling";
|
||||
ScrollIndicator.Fill = new SolidColorBrush(Colors.Green);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScrollIndicator.Fill = new SolidColorBrush(Colors.Red);
|
||||
ScrollIndicatorTest.Text = "Not Scolling";
|
||||
}
|
||||
}
|
||||
|
||||
private ObservableCollection<string> GetOddEvenSource(int count)
|
||||
{
|
||||
var oddEvenSource = new ObservableCollection<string>();
|
||||
|
@ -103,4 +121,4 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
|
|||
await new MessageDialog($"You clicked {item} via the 'ListViewExtensions.Command' binding", "Item Clicked").ShowAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Microsoft.Toolkit.Uwp.UI
|
|||
/// <param name="scrollIfVisible">Set false to disable scrolling when the corresponding item is in view</param>
|
||||
/// <param name="additionalHorizontalOffset">Adds additional horizontal offset</param>
|
||||
/// <param name="additionalVerticalOffset">Adds additional vertical offset</param>
|
||||
/// <returns>Note: Even though this return <see cref="Task"/>, it will not wait until the scrolling completes</returns>
|
||||
/// <returns>Returns <see cref="Task"/> that completes after scrolling</returns>
|
||||
public static async Task SmoothScrollIntoViewWithIndexAsync(this ListViewBase listViewBase, int index, ScrollItemPlacement itemPlacement = ScrollItemPlacement.Default, bool disableAnimation = false, bool scrollIfVisible = true, int additionalHorizontalOffset = 0, int additionalVerticalOffset = 0)
|
||||
{
|
||||
if (index > (listViewBase.Items.Count - 1))
|
||||
|
@ -58,7 +58,7 @@ namespace Microsoft.Toolkit.Uwp.UI
|
|||
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
|
||||
void ViewChanged(object obj, ScrollViewerViewChangedEventArgs args) => tcs.TrySetResult(result: null);
|
||||
void ViewChanged(object _, ScrollViewerViewChangedEventArgs __) => tcs.TrySetResult(result: default);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -80,20 +80,7 @@ namespace Microsoft.Toolkit.Uwp.UI
|
|||
// Scrolling back to previous position
|
||||
if (isVirtualizing)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
|
||||
void ViewChanged(object obj, ScrollViewerViewChangedEventArgs args) => tcs.TrySetResult(result: null);
|
||||
|
||||
try
|
||||
{
|
||||
scrollViewer.ViewChanged += ViewChanged;
|
||||
scrollViewer.ChangeView(previousXOffset, previousYOffset, zoomFactor: null, disableAnimation: true);
|
||||
await tcs.Task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
scrollViewer.ViewChanged -= ViewChanged;
|
||||
}
|
||||
await scrollViewer.ChangeViewAsync(previousXOffset, previousYOffset, zoomFactor: null, disableAnimation: true);
|
||||
}
|
||||
|
||||
var listViewBaseWidth = listViewBase.ActualWidth;
|
||||
|
@ -185,7 +172,7 @@ namespace Microsoft.Toolkit.Uwp.UI
|
|||
}
|
||||
}
|
||||
|
||||
scrollViewer.ChangeView(finalXPosition, finalYPosition, zoomFactor: null, disableAnimation);
|
||||
await scrollViewer.ChangeViewAsync(finalXPosition, finalYPosition, zoomFactor: null, disableAnimation);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -198,10 +185,68 @@ namespace Microsoft.Toolkit.Uwp.UI
|
|||
/// <param name="scrollIfVisibile">Set true to disable scrolling when the corresponding item is in view</param>
|
||||
/// <param name="additionalHorizontalOffset">Adds additional horizontal offset</param>
|
||||
/// <param name="additionalVerticalOffset">Adds additional vertical offset</param>
|
||||
/// <returns>Note: Even though this return <see cref="Task"/>, it will not wait until the scrolling completes</returns>
|
||||
/// <returns>Returns <see cref="Task"/> that completes after scrolling</returns>
|
||||
public static async Task SmoothScrollIntoViewWithItemAsync(this ListViewBase listViewBase, object item, ScrollItemPlacement itemPlacement = ScrollItemPlacement.Default, bool disableAnimation = false, bool scrollIfVisibile = true, int additionalHorizontalOffset = 0, int additionalVerticalOffset = 0)
|
||||
{
|
||||
await SmoothScrollIntoViewWithIndexAsync(listViewBase, listViewBase.Items.IndexOf(item), itemPlacement, disableAnimation, scrollIfVisibile, additionalHorizontalOffset, additionalVerticalOffset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the view of <see cref="ScrollViewer"/> asynchronous.
|
||||
/// </summary>
|
||||
/// <param name="scrollViewer">The scroll viewer.</param>
|
||||
/// <param name="horizontalOffset">The horizontal offset.</param>
|
||||
/// <param name="verticalOffset">The vertical offset.</param>
|
||||
/// <param name="zoomFactor">The zoom factor.</param>
|
||||
/// <param name="disableAnimation">if set to <c>true</c> disable animation.</param>
|
||||
private static async Task ChangeViewAsync(this ScrollViewer scrollViewer, double? horizontalOffset, double? verticalOffset, float? zoomFactor, bool disableAnimation)
|
||||
{
|
||||
if (horizontalOffset > scrollViewer.ScrollableWidth)
|
||||
{
|
||||
horizontalOffset = scrollViewer.ScrollableWidth;
|
||||
}
|
||||
else if (horizontalOffset < 0)
|
||||
{
|
||||
horizontalOffset = 0;
|
||||
}
|
||||
|
||||
if (verticalOffset > scrollViewer.ScrollableHeight)
|
||||
{
|
||||
verticalOffset = scrollViewer.ScrollableHeight;
|
||||
}
|
||||
else if (verticalOffset < 0)
|
||||
{
|
||||
verticalOffset = 0;
|
||||
}
|
||||
|
||||
// MUST check this and return immediately, otherwise this async task will never complete because ViewChanged event won't get triggered
|
||||
if (horizontalOffset == scrollViewer.HorizontalOffset && verticalOffset == scrollViewer.VerticalOffset)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
|
||||
void ViewChanged(object _, ScrollViewerViewChangedEventArgs e)
|
||||
{
|
||||
if (e.IsIntermediate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tcs.TrySetResult(result: default);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
scrollViewer.ViewChanged += ViewChanged;
|
||||
scrollViewer.ChangeView(horizontalOffset, verticalOffset, zoomFactor, disableAnimation);
|
||||
await tcs.Task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
scrollViewer.ViewChanged -= ViewChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче