Skip to content

Add platform feedback api for sound and haptic feedback#21189

Open
emmauss wants to merge 6 commits intomasterfrom
platform_feedback_2
Open

Add platform feedback api for sound and haptic feedback#21189
emmauss wants to merge 6 commits intomasterfrom
platform_feedback_2

Conversation

@emmauss
Copy link
Copy Markdown
Contributor

@emmauss emmauss commented Apr 14, 2026

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.Platform
{
    /// <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>
        /// If available, triggers both sound and haptic feedback for the attached control
        /// </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>
    /// Predefined platform feedback effect.
    /// </summary>
    public enum FeedbackEffect
    {
        /// <summary>
        /// The feedback is related to the Click action
        /// </summary>
        Click,

        /// <summary>
        /// The feedback is related to the Hold action
        /// </summary>
        LongPress,
    }
    
    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="feedbackEffect">The feedback effect relating to the action that triggered it</param>
        public static void PerformFeedback(this InputElement inputElement, FeedbackEffect feedbackEffect);
    }

    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 needs-api-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();
Copy link
Copy Markdown
Contributor

@TomEdwardsEnscape TomEdwardsEnscape Apr 14, 2026

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]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature needs-api-review The PR adds new public APIs that should be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants