Library used to add support for the on-screen keyboard in Avalonia.
$ dotnet add package TabTip.Avalonia
Avalonia-based and cross-platform re-imagining of WPFTabTip that came to be after I stumbled upon this discussion in the Avalonia repo
[!NOTE]
Currently, the Software Keyboard is only supported on Windows and the defaultTabTipIntegrationtriggers based only on the PointerType that is used when clicking a TextBox. This is all configurable. In the future, I'm looking to add some functionality to allow detecting whether a hardware keyboard is connected so that we can forgo triggering the software keyboard if the hardware keyboard is connected.
Just Install the NuGet package and decide whether you want to use the Global Integration or the Targeted Integration.
Add the following to App.xaml.cs:
// At the top of your file
using TabTip.Avalonia;
// ... start of App.xaml.cs
public override void OnFrameworkInitializationCompleted()
{
// ...
// Integrate the tabtip manager into the entire app.
TabTipManager.Integrate(); // (defaults to `true` for the `Integrate(bool global)` parameter.)
// ...
}
This will integrate the TabTipManager into the entire app, causing it to trigger the TabTip for any TextBox that is clicked.
Just like for the Global Integration, we need to add a line to App.xaml.cs, but this time, we pass in
false for the global parameter. This will only integrate the TabTipManager but prevent it from triggering the TabTip
indiscriminately for any TextBox that is clicked:
// At the top of your file
using TabTip.Avalonia;
// ... start of App.xaml.cs
public override void OnFrameworkInitializationCompleted()
{
// ...
// Integrate the tabtip manager into the entire app but don't trigger unless a textbox is registered.
TabTipManager.Integrate(false);
// ...
}
Once the TabTipManager has been integrated into the app, you only need to explicitly register the TextBox that you want to
trigger the TabTip for. This can be done by calling TabTipManager.Register(TextBox) as follows:
// In this example, this is inside of a `Control`, so we need to override `OnApplyTemplate`
// to register the TextBox so that we're sure that it has been initialized.
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
TabTipManager.Register(IntegratedTextBox);
// Even though `NumericUpDown` is not itself a TextBox, we can still register it as the `Register` command will allow
// any child TextBox of the registered control to trigger the TabTip. This applies to any control.
TabTipManager.Register(IntegratedNumericUpDown);
}
By default, the software keyboard is only opened if the PointerType used when clicking is either PointerType.Touch or
PointerType.Pen.
If you would like to use any other setting, provide an array of PointerTypes that you want to trigger the software
keyboard as below:
// Trigger on all pointer types.
TabTipManager.OverrideIntegrationTrigger([PointerType.Touch, PointerType.Mouse, PointerType.Pen]);
The ITabTipFactory interface allows you to provide your own implementation of the ITabTip interface, giving you the flexibility to create it based
on which OS the host is running on. The current default is DefaultTabTipFactory which creates a TabTip instance for Windows or, if not running on Windows,
simply creates a NullTabTip instance, which has an empty Toggle method so that we don't do anything on other OSs.
To override the default factory,
provide an implementation of ITabTipFactory to TabTipManager.OverrideTabTipFactory as follows:
TabTipManager.OverrideTabTipFactory(myCustomFactory);
This will change the factory used and set the TabTip used by the manager to the one returned by myCustomFactory.
The TabTip is the platform-specific implementation of the ITabTip interface. It is responsible for opening and closing
the software keyboard. We currently have only two built-in implementations:
The recommended way to override the TabTip used it to override the ITabTipFactory as described above.
The ITabTipIntegration interface defines the methods used to integrate the TabTip into the application. The implementing
class is responsible for when to trigger the TabTip as well as setting up the appropriate event handlers to know
when a TextBox has been clicked.
Before fully replacing the default integration, it is recommended to override the TabTipIntegration class.
The Integrate method is purposefully virtual so that it can be overridden. Simply create a new class that inherits from
TabTipIntegration and override the Integrate method. If you specifically call base.Integrate() in your override,
it will call the default implementation of Integrate which will set up the default event handlers while allowing you to
add any new ones you want. This is useful if all you want to do is integrate controls other than TextBox.
Regardless of whether you create a brand new class that implements ITabTipIntegration or extends TabTipIntegration,
you need to set it as the one that is used by calling:
TabTipManager.OverrideIntegration(myCustomIntegration);
| OS | Supported | Notes |
|---|---|---|
| Windows | ✅ | |
| Mac | ❌⚠️ | Macs don't currently have touchscreens so... I don't see the benefit of adding support. Let me know if you disagree! |
| Linux | ❌ | I might look into adding support in future versions but I suspect this will require distro-specific handling. |
| Android | ❌⚠️ | I have not added specific support for this library as I THINK Avalonia already supports Android properly. |
| iOs/iPadOS | ❌⚠️ | I have not added specific support for this library as I THINK Avalonia already supports Android properly. |
TabTip?"TabTip" refers to the Touch Keyboard and Handwriting Panel, also known as the Tablet Text Input Panel, which is a virtual keyboard in Windows. Since this project was heavily inspired by the WPF version, the name is also inspired by the WPF version.
Integrate which allows us to specify a specific control so that it integrates it and all its
children only.
Integrate(MyCustomControlReference) would trigger for that control and all its children, but not any other
controls in the app.Microsoft.Extensions.DependencyInjection