question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Proposal: NavigationView: Allow developers to turn off the selection indicator animation via an API

See original GitHub issue

Proposal: NavigationView: Allow developers to turn off the selection indicator animation via an API

Summary

There is currently no (reasonable) way for developers to turn off the animation of the selection indicator used in the NavigationView control as it is currently embedded in the NavigationView implementation and not exposed to the outside world in any way. While users can disable animations in Windows which would disable this particular animation, this is not an option to developers who want to ship their app with a NavigationView powered in-app navigation experience simply without this animation.

Why would developers want to disable the selection indicator animation?

There are a lot of Windows apps out there which use an in-app navigation design closely resembling the one provided by the NavigationView control. Among these apps are, for example, Windows Settings, Microsoft To Do, Your Phone, OneNote for Windows 10 and legacy Edge UWP. See below for images:

Windows Settings (Windows Settings) MS Todo (Microsoft To Do)
image (Your Phone) image (OneNote for Windows 10)
image (Edge UWP)

The key detail for this proposal here is that for all these apps their selection indicator is not animated. Whereas developers, who want to utilize the powerful NavigationView to create similar such navigation designs, will automatically get the selection indicator animation included with no way for them to turn it off for their app. This means that developers who want to match these showcased in-app navigation designs might not currently be able to utilize the power of the NavigationView here. Instead, they might be forced to re-build their in-app navigation from the ground up using controls like the SplitView and the ListView…and if hierarchical navigation support is required for their in-app navigation, this task will soon become quite complex and time-consuming.

Rationale

The NavigationView control is a powerful in-app navigation control which keeps getting more and more feature rich. Just recently, for example, we have seen support for hierarchical navigation being added. It would be a tremendous shame if developers would be forced to miss out on all these provided navigation features for free simply because they cannot remove the selection indicator animation. This animation is such a small part of the overall NavigationView control that it shouldn’t act as a blocker when it comes to building a powerful in-app navigation experience where most of the functionality is already provided “for free” by the NavigationView control.

Along with proposal https://github.com/microsoft/microsoft-ui-xaml/issues/2877, this proposal will enable developers to easily create in-app navigation experiences matching the showcased in-app navigation UI examples in well-known Windows apps while being able to utilize the powerful NavigationView control.

Scope

Capability Priority
This proposal will allow developers to turn off the NavigationView’s selection indicator animation via an API. Must
This proposal will allow developers to provide a custom selection indicator animation. Could
This proposal will remove or change the default in-built selection indicator animation. Won’t

API Proposal

There are at least two possible ways we could provide an API for developers to use here. Note that the APIs presented below are just meant to provide a conceptual overview for now. I do not claim their designs are perfect or final.

API Example 1 - Theme resource and lightweight styling

We could introduce a new theme resource for the NavigationView:

<x:Boolean x:Key="IsSelectionIndicatorAnimationEnabled">True</x:Boolean>

This theme resource would essentially act as a flag which can be set by the developer to control whether the selection indicator animation will be played or not. An example to turn off the animation could then look like this:

<NavigationView>
    <NavigationView.Resources>
        <x:Boolean x:Key="IsSelectionIndicatorAnimationEnabled">False</x:Boolean>
    </NavigationView.Resources>
</NavigationView>

This approach could also be realized by adding a new boolean API to the NavigationView class, enabling developers to easily set this flag at runtime back-and-forth as well, like so:

public class NavigationView
{
    bool IsSelectionIndicatorAnimationEnabled { get; set; } = true;

    static Windows.UI.Xaml.DependencyProperty IsSelectionIndicatorAnimationEnabledProperty { get; };
}

API Example 2 - Create a new INavigationViewSelectionIndicatorAnimator API in the NavigationView class

Alternatively, a new API can be created on the NavigationView class which the developer can use to turn off the animation or even provide a custom animation, if they so wish. This could conceptually look like the following:

public class NavigationView
{
    INavigationViewSelectionIndicatorAnimator SelectionIndicatorAnimator { get; set; };

    static Windows.UI.Xaml.DependencyProperty SelectionIndicatorAnimatorProperty { get; };
}

where the interface INavigationViewSelectionIndicatorAnimator is defined like this:

interface INavigationViewSelectionIndicatorAnimator
{
    // Raised when the animation is completed.
    event Windows.Foundation.EventHandler<Object> AnimationCompleted;

    /// <summary>
    /// Called before <see cref="INavigationViewSelectionIndicatorAnimator.StartAnimation()"/> is called. Allows the developer to check if 
    /// an animation is already running and how to treat such an animation. The return value can be used to decide if a new animation should be played
    /// or not.
    /// </summary>
    /// <param name="prevIndicator">The source selection indicator for the animation to be started.</param>
    /// <param name="nextIndicator">The target selection indicator for the animation to be started.</param>
    /// <param name="currentAnimationPrevIndicator">The source selection indicator of the currently running animation, if any.</param>
    /// <param name="currentAnimationNextIndicator">The target selection indicator of the currently running animation, if any.</param>
    /// <returns>True to indicate <see cref="INavigationViewSelectionIndicatorAnimator.StartAnimation()"/> should be called next, false otherwise </returns>
    bool PrepareForAnimation(
        Windows.UI.Xaml.UIElement prevIndicator,
        Windows.UI.Xaml.UIElement nextIndicator,
        Windows.UI.Xaml.UIElement currentAnimationPrevIndicator,
        Windows.UI.Xaml.UIElement currentAnimationNextIndicator);

    /// <summary>
    /// Start a selection indicator animation. Will be called when the return value of <see cref="INavigationViewSelectionIndicatorAnimator.PrepareForAnimation()" was <c>true</c>./>
    /// </summary>
    /// <param name="navigationViewVisual">The visual object of the NavigationView. Can be used to create composition animations. </param>
    /// <param name="container">The NavigationView UI element containing the NavigationView items and selection indicators. 
    /// Can be used to obtain the position of a selection indicator in the coordinate system of the container.</param>
    /// <param name="prevIndicator">The source selection indicator for the animation.</param>
    /// <param name="nextIndicator">The target selection indicator for the animation.</param>
    /// <param name="isTopNavigationView">Specifies whether the NavigationView is in Left mode or Top pane display mode.</param>
    void StartAnimation(
        Windows.UI.Composition.Visual navigationViewVisual, 
        Windows.UI.Xaml.UIElement container, 
        Windows.UI.Xaml.UIElement prevIndicator, 
        Windows.UI.Xaml.UIElement nextIndicator, 
        bool isTopNavigationView);
}

WinUI would then provide the current selection indicator animation as an implementation of the INavigationViewSelectionIndicatorAnimator interface, for example as a class named NavigationViewSelectionIndicatorDefaultAnimator living in the Microsoft.UI.Xaml.Controls namespace.

The default style of the WinUI NavigationView (in NavigationView.xaml) could then look like this:

<local:NavigationViewSelectionIndicatorDefaultAnimator x:Key="SelectionIndicatorDefaultAnimator" />

<Style TargetType="local:NavigationView">
    <Setter Property="SelectionIndicatorAnimator" Value="{StaticResource SelectionIndicatorDefaultAnimator}" />
</Style>

and developers can set the SelectionIndicatorAnimator API to null if they don’t want a selection indicator animation to be played, like so:

<NavigationView SelectionIndicatorAnimator="{x:Null}"/>

This approach, while more challenging to implement, has some benefits compared to the approach using a theme resource (or boolean property):

  • The developer can supply their own custom animation in the future by implementing the INavigationViewSelectionIndicatorAnimator interface.
  • Using an on/off flag for the animation would lose its meaning if the default animation of the selection indicator should ever be removed - developers could set it to True but no animation would be played. Given this API here, developers can instead always supply an animation to be played.

Open Questions

Well, I guess if this proposal will get the OK sign: How will the API look like? Should we provide an option to developers to potentially create their own selection indicator animation?

Additional Context

I realize there was a proposal asking for the removal of the selection indicator animation which was declined. To my understanding, the motivation behind that proposal, and the reason why it was declined, was that the selection indicator animation did not play nicely with the NavigationViewItems added in the NavigationView.PaneFooter area of the NavigationView. Instead of thus disabling the animation (or providing such an option) PR #1997 was created to make the selection indicator play nicely with those items as well.

To stress it again: This issue has a completely different motivation. It asks for the option to disable the animation so that developers can provide delightful in-app navigation experiences using the powerful NavigationView control “for free”. Developers shouldn’t be forced to have the re-built a potentially complex in-app navigation experience simply because a small detail like the selection indicator animation stands in the way.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:2
  • Comments:8 (7 by maintainers)

github_iconTop GitHub Comments

3reactions
BreeceWcommented, Jul 11, 2020

My issue with the NavigationView animation is that it starts with a delay that causes the indicator to jump around if you click around too fast. A much nicer experience is the ribbon in the OneNote UWP, where the indicator elegantly slides into place where you click it. Try clicking around quickly in any default NavigationView and OneNote to see how this feels.

As far as user experience goes, for users of NavigationView, it’s fine if a user just clicks on one item. But if, say, a user clicked on the wrong item and then corrected themself, they would see the indicator jump in a glitchy looking way. It is this user experience that makes me wonder if it is why apps like Your Phone disable this.

Basically—the default animation looks glitchy, and people probably want to disable it because of that.

3reactions
mdtaukcommented, Jul 11, 2020

… I can only tell you that I myself had to “re-build” my in-app navigation using a SplitView and a ListView to match UWP Edge’s Settings pane you can see above. I explicitly did not want to have the default selection indicator animation in that case so using the NavigationView was not really an option for me…

Why do you want to take the joy away from user interaction 😁

I personally will be happier when Settings moves to using WinUI, adding those little animated features, and changing the Acrylic to 80% but not ditching it entirely.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Removing the hover animation on NavigationMenuItem
I would like the remove the hover animation which is displayed on navigation menu items in the UWP navigation menu. I have looked...
Read more >
How to disable NavigationView push and pop animations
Right now there is no modifier to disable NavigationView animations. You can use your struct init() to disable animations, as below: struct ...
Read more >
NavigationView | Android Developers
Listener for handling events on navigation items. class, NavigationView.SavedState. User interface state that is stored by NavigationView ...
Read more >
NavigationBarView
Provides an abstract implementation of a navigation bar that can be used to implementation such as Bottom Navigation or Navigation rail.
Read more >
Core Animation | Apple Developer Forums
On iOS, to make animation faster (reduce animation time), I'm using UIView.animate(withDuration: 0.2) { mapView.setRegion(region, animated: true) } and it ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found