Open cat0363 opened 1 year ago
We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.
Additional Information: At the timing of OnNavigatedTo event or OnAppearing event, the Handler below is null.
[src\Controls\src\Core\ScrollView\ScrollView.cs]
void OnScrollToRequested(ScrollToRequestedEventArgs e)
{
CheckTaskCompletionSource();
ScrollToRequested?.Invoke(this, e);
Handler?.Invoke(nameof(IScrollView.RequestScrollTo), ConvertRequestMode(e).ToRequest());
}
Therefore, the asynchronous scrolling task will never be executed and the caller will be waiting for its completion. I don't know if this solution is correct, but you can solve this problem by staggering the execution timing.
[src\Controls\src\Core\ScrollView\ScrollView.cs]
void OnScrollToRequested(ScrollToRequestedEventArgs e)
{
CheckTaskCompletionSource();
ScrollToRequested?.Invoke(this, e);
if (Handler is not null)
{
Handler.Invoke(nameof(IScrollView.RequestScrollTo), ConvertRequestMode(e).ToRequest());
}
else
{
Loaded += async (s, e2) =>
{
await Task.Delay(1);
Handler?.Invoke(nameof(IScrollView.RequestScrollTo), ConvertRequestMode(e).ToRequest());
};
}
}
However, if you don't insert await Task.Delay(1), it won't scroll properly.
Below is the execution result. In the video, the scroll position is intentionally set to (x, y) = (0, 200) because it is unclear whether it was scrolled or remains in the initial display.
[Android]
https://github.com/dotnet/maui/assets/125236133/5716245a-4987-4090-96e4-0c625d6275ff
[iOS]
https://github.com/dotnet/maui/assets/125236133/bdc5ae88-c13b-4599-a932-dfaee6ba5d5b
I suspect that the call to await Task.Delay(1) establishes the required size for scrolling.
By the way, the ScrollView's size was assigned when there was a call to await Task.Delay(1). If not, the size is unassigned and the value of both Width and Height is -1.
I hope it will be a hint for solving this issue. I'm sorry if I'm wrong.
Alternatively, writing it like this also worked:
[src\Controls\src\Core\ScrollView\ScrollView.cs]
void OnScrollToRequested(ScrollToRequestedEventArgs e)
{
CheckTaskCompletionSource();
ScrollToRequested?.Invoke(this, e);
if (Handler is not null)
{
Handler.Invoke(nameof(IScrollView.RequestScrollTo), ConvertRequestMode(e).ToRequest());
}
else
{
Loaded += (s, e2) =>
{
Dispatcher.Dispatch(() =>
{
Handler?.Invoke(nameof(IScrollView.RequestScrollTo), ConvertRequestMode(e).ToRequest());
});
};
}
}
Calling await Task.Delay(1) is unnecessary in this case
This solution works only for iOS and Android. On Windows, it works in the NavigatedTo event when displayed for the first time, but it does not work in the NavigatedTo event when transitioning from another page. I requested a scroll in the ChangeView method, but the ViewChanged event is not firing. Because the ViewChanged event will not fire unless there is a change in the scrollbar position. For this reason, ScrollToAsync will not returned if the scrollbar position does not change when returning to the original page from another page.
Description
Place a BindableLayout inside the ScrollView and set the BindableLayout's ItemsSource in the constructor.
Layout as shown below.
Call the ScrollView's ScrollToAsync method within the OnNavigatedTo event.
If the ScrollToAsync method call completes successfully, the following log should be displayed on the screen.
But the actual log is below.
The ScrollToAsync method remains called and does not return.
In the reproduction code, no code is written after the ScrollToAsync method, but in reality, initialization processing on the screen is written. Therefore, the code written after the ScrollToAsync method is not executed.
This issue occurs on both Android and iOS.
[.NET MAUI Android]
https://github.com/dotnet/maui/assets/125236133/f00d3340-f5ab-4aab-a95b-c9cb6ce19c3e
[.NET MAUI iOS]
https://github.com/dotnet/maui/assets/125236133/70518d94-a773-499a-94be-fa198a2f0cce
This problem also occurred within the OnAppearing event.
The ScrollToAsync method call does not return in the OnNavigatedTo event or the OnAppearing event at the time of initial display. In the OnNavigatedTo or OnAppearing event when returning from another screen, the ScrollToAsync method call will return. I expected the ScrollToAsync method call to return in the OnNavigatedTo or OnAppearing event.
At least it was working as intended on iOS in Xamarin.Forms. Android on Xamarin.Forms had the same results as Android on .NET MAUI.
[Xamarin.Forms iOS]
https://github.com/dotnet/maui/assets/125236133/3889b178-5e05-47c6-b892-84d4947c885d
Please let me know if there are any points to note during implementation. Any good ideas? Thank you.
Steps to Reproduce
The steps to reproduce are as follows.
In step 1, the call to the ScollToAsync method does not return. I expected the ScrollToAsync method call to return in the OnNavigatedTo or OnAppearing event.
Link to public reproduction project repository
https://github.com/cat0363/Maui-IssueScrollToAsync2.git
Version with bug
7.0.86
Last version that worked well
Unknown/Other
Affected platforms
iOS, Android
Affected platform versions
iOS 16.4, Android 11.0
Did you find any workaround?
It is possible to avoid it by calling await Task.Delay(XXX) before the ScrollToAsync call. XXX is any millisecond. However, this is not the preferred workaround.
Relevant log output
No response