Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Invoke AnimationFinished from fragment if no animation has been added #13260

Merged
merged 1 commit into from
Jan 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Xamarin.Forms.ControlGallery.Android/CustomRenderers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,39 @@
[assembly: ExportRenderer(typeof(Xamarin.Forms.Controls.Tests.TestClasses.CustomButton), typeof(CustomButtonRenderer))]
[assembly: ExportRenderer(typeof(ScrolView11185), typeof(ScrollViewFadeRenderer))]

[assembly: ExportRenderer(typeof(ShellWithCustomRendererDisabledAnimations), typeof(ShellWithCustomRendererDisabledAnimationsRenderer))]

#if PRE_APPLICATION_CLASS
#elif FORMS_APPLICATION_ACTIVITY
#else
[assembly: ExportRenderer(typeof(FlyoutPage), typeof(NativeDroidFlyoutPage))]
#endif
namespace Xamarin.Forms.ControlGallery.Android
{
public class ShellWithCustomRendererDisabledAnimationsRenderer : ShellRenderer
{
public ShellWithCustomRendererDisabledAnimationsRenderer(Context context) : base(context)
{
}

protected override IShellItemRenderer CreateShellItemRenderer(ShellItem shellItem)
{
return new ShellWithCustomRendererDisabledAnimationsShellItemRenderer(this);
}

public class ShellWithCustomRendererDisabledAnimationsShellItemRenderer : ShellItemRenderer
{
public ShellWithCustomRendererDisabledAnimationsShellItemRenderer(IShellContext shellContext) : base(shellContext)
{
}

protected override void SetupAnimation(ShellNavigationSource navSource, AndroidX.Fragment.App.FragmentTransaction t, Page page)
{
// Don't setup any animations
}
}
}

public sealed class ScrollViewFadeRenderer : ScrollViewRenderer
{
public ScrollViewFadeRenderer(Context context) : base(context)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;


#if UITEST
using Xamarin.UITest;
using NUnit.Framework;
using Xamarin.Forms.Core.UITests;
#endif

namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.None, 0, "[Shell] Overriding animation with custom renderer to remove animation breaks next navigation",
PlatformAffected.All)]
#if UITEST
[NUnit.Framework.Category(UITestCategories.Shell)]
#endif
public class ShellWithCustomRendererDisabledAnimations : TestShell
{
protected override void Init()
{
ContentPage contentPage = new ContentPage();
base.AddFlyoutItem(contentPage, "Root");

contentPage.Content = new Button()
{
Text = "Click Me",
AutomationId = "PageLoaded",
Command = new Command(async () =>
{
await Navigation.PushAsync(CreateSecondPage());
})
};
}

ContentPage CreateSecondPage()
{
ContentPage page = new ContentPage();

page.Content = new StackLayout()
{
Children =
{
new Label()
{
Text = "If clicking `Go Back` goes back to previous page then test has passed"
},
new Button()
{
Text = "Go Back",
Command = new Command(async () =>
{
await GoToAsync("..");
}),
AutomationId = "GoBack"
}
}
};

return page;
}

#if UITEST && __ANDROID__
[Test]
public void NavigationWithACustomRendererThatDoesntSetAnAnimationStillWorks()
{
RunningApp.Tap("PageLoaded");
RunningApp.Tap("GoBack");
RunningApp.WaitForElement("PageLoaded");
}
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<Compile Include="$(MSBuildThisFileDirectory)CollectionViewGroupTypeIssue.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue11214.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue13109.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ShellWithCustomRendererDisabledAnimations.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ShellFlyoutContent.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue4720.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue10897.xaml.cs">
Expand Down
13 changes: 8 additions & 5 deletions Xamarin.Forms.Core/Shell/ShellNavigationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,15 @@ public async Task GoToAsync(ShellNavigationParameters shellNavigationParameters)
{
var navigatingArgs = ProposeNavigation(source, state, _shell.CurrentState != null, animate ?? true);

bool accept = !navigatingArgs.NavigationDelayedOrCancelled;
if (navigatingArgs.DeferredTask != null)
accept = await navigatingArgs.DeferredTask;
if (navigatingArgs != null)
{
bool accept = !navigatingArgs.NavigationDelayedOrCancelled;
if (navigatingArgs.DeferredTask != null)
accept = await navigatingArgs.DeferredTask;

if (!accept)
return;
if (!accept)
return;
}
}

Routing.RegisterImplicitPageRoutes(_shell);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public ShellContentFragment(IShellContext shellContext, Page page)
public event EventHandler AnimationFinished;

public Fragment Fragment => this;

public override AndroidAnimation OnCreateAnimation(int transit, bool enter, int nextAnim)
{
var result = base.OnCreateAnimation(transit, enter, nextAnim);
Expand All @@ -82,7 +82,10 @@ public override AndroidAnimation OnCreateAnimation(int transit, bool enter, int
}

if (result == null)
{
AnimationFinished?.Invoke(this, EventArgs.Empty);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically if the user creates a custom renderer that doesn't actually add an animation then the following code

https://github.com/xamarin/Xamarin.Forms/blob/5.0.0/Xamarin.Forms.Platform.Android/Renderers/ShellItemRendererBase.cs#L254

will never execute and the "async push" operation will never complete

This invokes the AnimationFinished event so the calling code can continue on and complete the animation Task

return result;
}

// we only want to use a hardware layer for the entering view because its quite likely
// the view exiting is animating a button press of some sort. This means lots of GPU
Expand Down