Skip to content

Add platform feedback api for sound and haptic feedback - #21189

Merged
MrJul merged 12 commits into
masterfrom
platform_feedback_2
Jun 6, 2026
Merged

Add platform feedback api for sound and haptic feedback#21189
MrJul merged 12 commits into
masterfrom
platform_feedback_2

Conversation

@emmauss

@emmauss emmauss commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

What does the pull request do?

Add audio and haptic feedback for common interact-able controls.
This PR is a rework of #9420 .The api has been stripped down and the core implementation is internal.

namespace Avalonia.Controls
{
    /// <summary>
    /// The feedback type to be triggered for the attached control.
    /// </summary>
    public enum FeedbackType
    {
        /// <summary>
        /// Disables feedback for the attached control
        /// </summary>
        None,
    
        /// <summary>
        /// Triggers the most suitable feedback type based on the feedback effect on the current platform.
        /// </summary>
        Auto,
    
        /// <summary>
        /// If available, triggers only sound feedback for the attached control
        /// </summary>
        Sound,
    
        /// <summary>
        /// If available, triggers only haptic feedback for the attached control
        /// </summary>
        Haptic
    }

    /// <summary>
    /// Defines which action triggered the feedback.
    /// </summary>
    public class FeedbackAction
    {
        internal string Key { get; }
        internal FeedbackAction(string label)
        {
            Key = label;
        }

        /// <summary>
        /// The feedback is related to the Click action
        /// </summary>
        public static FeedbackAction Click { get; } = new FeedbackAction("Click");

        /// <summary>
        /// The feedback is related to the Hold action
        /// </summary>
        public static FeedbackAction Hold { get; } = new FeedbackAction("Hold");
    }
    
    public static class PlatformFeedbackExtensions
    {
        /// <summary>
        /// Performs the specified <see cref="FeedbackEffect"/> on this <see cref="InputElement"/>. The type of feedback to perform is defined in the <see cref="PlatformFeedback.FeedbackTypeProperty"/>
        /// </summary>
        /// <param name="inputElement">The element to trigger the feedback effect on</param>
        /// <param name="feedbackAction">The feedback action relating to the action that triggered it</param>
        public static void PerformFeedback(this InputElement inputElement, FeedbackAction feedbackAction);
    }

    public class PlatformFeedback
    {
        public static readonly AttachedProperty<FeedbackType> FeedbackTypeProperty =
            AvaloniaProperty.RegisterAttached<PlatformFeedback, InputElement, FeedbackType>("FeedbackType", defaultValue: FeedbackType.None);

        public static void SetFeedbackType(InputElement control, FeedbackType feedbackType);

        public static FeedbackType GetFeedbackType(InputElement control);
    }
}

By default, custom controls have feedback disabled. They can enable it using PlatformFeedback.FeedbackType attached property and trigger either sound or haptic feedback based on the set value using PerformFeedback extension method,
e.g. this.PerformFeedback(FeedbackType.Click).

What is the current behavior?

What is the updated/expected behavior with this PR?

How was the solution implemented (if it's not obvious)?

Checklist

Breaking changes

Obsoletions / Deprecations

Fixed issues

@emmauss
emmauss requested review from MrJul and maxkatz6 April 14, 2026 12:17
@MrJul MrJul added feature api-needs-review The PR adds new public APIs that should be reviewed. labels Apr 14, 2026
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0064816-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0064824-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

Comment thread src/iOS/Avalonia.iOS/IOSPlatformFeedback.cs Outdated
Comment on lines +42 to +43
FeedbackEffect.Click => UIImpactFeedbackStyle.Light,
FeedbackEffect.LongPress => UIImpactFeedbackStyle.Medium,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

iOS has five different feedback styles, but this system only permits the use of two.

What if feedback effects worked like theme variants, so that instead of an enum the parameter is a reference type? Cross-platform values can be defined in Avalonia.Controls and platform-specific values can be defined in Avalonia.iOS, Avalonia.Android, etc.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

How would users access those platform specific ones?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

By referencing the platform specific projects in their own platform-specific projects.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm still not quite clear on how that can be done. View and viewmodels can't access platform specific without DI. If they are like theme variants, then they would have to call PerformFeedback multiple times. First for the crossplatform version, then another for whatever platform they want special effects.
Also, how often would devs want to trigger effects outside the defaults for just 1 platform?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

View and viewmodels can't access platform specific without DI.

Huh? People are allowed to make apps which only target one platform. It's quite alright for your views to be defined in a project which references that platform's Avalonia library, e.g. Avalonia.iOS.

But in the project where I used these features, our views were indeed in a platform-agnostic project. So I created a RoutedEventArgs class requesting haptic feedback and defining if it was a "scroll" or "snap". Then in our iOS executable project, I installed a TopLevel handler for that event which translated scroll to Light and snap to Soft and made the appropriate iOS SDK calls.

I think this answers your question about developers triggering effect types other than what you deem the "defaults".

I have no idea what you mean about performing feedback multiple times.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think its a bit beyond the scope of this pr. The focus here is to provide basic feedback for the built-in controls, while allowing devs to do the same for their custom controls. This is to ensure behavior is the same or native across all platforms that supports some form of feedback.
Devs can create their own feedback system to provide custom effects for their control, but most devs should be good with just the basic effects.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sure, but anyone doing that must implement everything from scratch. The simple change I suggested above would allow them to use this code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

How would the api look like?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Remove: public enum FeedbackEffect { ... }.

Add: public abstract class FeedbackEffect;, public class ClickFeedbackEffect : FeedbackEffect;, and so on.

Everything else stays the same. You can define an internal constructor for the abstract class if you don't want third parties deriving their own effects.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If we go this API route, I think TextTrimming-like API is a better fit.

public abstract class TextTrimming
{
internal const string DefaultEllipsisChar = "\u2026";
/// <summary>
/// Text is not trimmed.
/// </summary>
public static TextTrimming None { get; } = new TextNoneTrimming();
/// <summary>
/// Text is trimmed at a character boundary. An ellipsis (...) is drawn in place of remaining text.
/// </summary>
public static TextTrimming CharacterEllipsis { get; } = new TextTrailingTrimming(DefaultEllipsisChar, false);

? UIImpactFeedbackGenerator.GetFeedbackGenerator(FeedbackToImpactStyle(feedback), _avaloniaView)
: new UIImpactFeedbackGenerator(FeedbackToImpactStyle(feedback));
generator.Prepare();
generator.ImpactOccurred();

@TomEdwardsEnscape TomEdwardsEnscape Apr 14, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This method has an overload which accepts a position parameter. It would be trivial to accept an Avalonia position and provide it to iOS here.

Comment thread src/iOS/Avalonia.iOS/IOSPlatformFeedback.cs
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0064873-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@MrJul MrJul added this to the 12.1 milestone May 7, 2026
@MrJul MrJul added api-needs-changes The new public APIs need some changes. and removed api-needs-review The PR adds new public APIs that should be reviewed. labels May 7, 2026
@MrJul

MrJul commented May 7, 2026

Copy link
Copy Markdown
Member

Notes from the API review meeting:

  • Rename FeedbackEffect to FeedbackAction.
  • Make FeedbackAction a class (with an internal constructor for now, extensibility will happen later).
  • Add static FeedbackAction.Click and FeedbackAction.Hold members.
  • Change the documentation on Auto to make clear that it's platform-specific.

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0065351-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@emmauss

emmauss commented May 13, 2026

Copy link
Copy Markdown
Contributor Author

Updated API with review

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0065357-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@MrJul MrJul added api-approved The new public APIs have been approved. and removed api-needs-changes The new public APIs need some changes. labels May 15, 2026
Comment thread src/Avalonia.Controls/Control.cs Outdated
Comment thread src/Avalonia.Controls/Platform/PlatformFeedback.cs Outdated
Comment thread src/Avalonia.Controls/Platform/IPlatformFeedback.cs Outdated
Comment thread src/Android/Avalonia.Android/Platform/AndroidPlatformFeedback.cs Outdated
Comment thread src/iOS/Avalonia.iOS/IOSPlatformFeedback.cs Outdated
Comment thread src/iOS/Avalonia.iOS/IOSPlatformFeedback.cs Outdated
Comment thread src/iOS/Avalonia.iOS/IOSPlatformFeedback.cs Outdated
Comment thread src/iOS/Avalonia.iOS/IOSPlatformFeedback.cs Outdated
@emmauss

emmauss commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

Api change
IPlatformFeedback and PlatformFeedback moved to Avalonia.Controls to allow access in xaml.

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0066042-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0066115-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@MrJul MrJul left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM!

@MrJul
MrJul added this pull request to the merge queue Jun 6, 2026
Merged via the queue into master with commit 326badf Jun 6, 2026
11 checks passed
@MrJul
MrJul deleted the platform_feedback_2 branch June 6, 2026 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-approved The new public APIs have been approved. feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants