File: SoftInputExtensions.cs
Web Access
Project: src\src\Core\src\Core.csproj (Microsoft.Maui)
using System.Diagnostics.CodeAnalysis;
using Microsoft.Maui.Dispatching;
using Microsoft.Maui.Platform;
using System.Threading.Tasks;
using System.Threading;
using System;
 
#if IOS || MACCATALYST
using PlatformView = UIKit.UIView;
#elif ANDROID
using PlatformView = Android.Views.View;
#elif WINDOWS
using PlatformView = Microsoft.UI.Xaml.FrameworkElement;
#elif TIZEN
using PlatformView = Tizen.NUI.BaseComponents.View;
#elif (NETSTANDARD || !PLATFORM) || (NET6_0_OR_GREATER && !IOS && !ANDROID && !TIZEN)
using PlatformView = System.Object;
using IPlatformViewHandler = Microsoft.Maui.IViewHandler;
#endif
 
namespace Microsoft.Maui;
 
/// <summary>
/// Extension methods for interacting with a platform's Soft Input Pane
/// </summary>
public static partial class SoftInputExtensions
{
	/// <summary>
	/// If a soft input pane is currently showing, this will attempt to hide it.
	/// </summary>
	/// <param name="targetView"></param>
	/// <param name="token">Cancellation token</param>
	/// <returns>
	/// Returns <c>true</c> if the platform was able to hide the soft input pane.</returns>
	public static Task<bool> HideSoftInputAsync(this ITextInput targetView, CancellationToken token)
	{
#if NETSTANDARD
		return Task.FromResult(false);
#else
		token.ThrowIfCancellationRequested();
		if (!targetView.TryGetPlatformView(out var platformView, out _, out _))
		{
			return Task.FromResult(false);
		}
 
		return Task.FromResult(platformView.HideSoftInput());
#endif
	}
 
	/// <summary>
	/// If a soft input pane is currently hiding, this will attempt to show it.
	/// </summary>
	/// <param name="targetView"></param>
	/// <param name="token">Cancellation token</param>
	/// <returns>
	/// Returns <c>true</c> if the platform was able to show the soft input pane.</returns>
	public static Task<bool> ShowSoftInputAsync(this ITextInput targetView, CancellationToken token)
	{
#if NETSTANDARD
		return Task.FromResult(false);
#else
		token.ThrowIfCancellationRequested();
 
		if (!targetView.TryGetPlatformView(out var platformView, out var handler, out var view))
		{
			return Task.FromResult(false);
		}
 
		if (!view.IsFocused)
		{
			var showKeyboardTCS = new TaskCompletionSource<bool>();
 
#pragma warning disable CS0618
			handler.Invoke(nameof(IView.Focus), new FocusRequest(false));
#pragma warning restore CS0618

			handler.GetRequiredService<IDispatcher>().Dispatch(() =>
			{
				try
				{
					var result = platformView.ShowSoftInput();
					showKeyboardTCS.SetResult(result);
				}
				catch (Exception e)
				{
					showKeyboardTCS.SetException(e);
				}
			});
 
			return showKeyboardTCS.Task.WaitAsync(token);
		}
		else
		{
			var result = platformView.ShowSoftInput();
			return Task.FromResult(result).WaitAsync(token);
		}
#endif
	}
 
	/// <summary>
	/// Checks to see if the platform is currently showing the soft input pane
	/// </summary>
	/// <param name="targetView"></param>
	/// <returns>
	/// Returns <c>true</c> if the soft input pane is currently showing.</returns>
	public static bool IsSoftInputShowing(this ITextInput targetView)
	{
		if (!targetView.TryGetPlatformView(out PlatformView? platformView, out _, out _))
		{
			return false;
		}
 
		return platformView.IsSoftInputShowing();
	}
 
	static bool TryGetPlatformView(this ITextInput textInput,
									[NotNullWhen(true)] out PlatformView? platformView,
									[NotNullWhen(true)] out IPlatformViewHandler? handler,
									[NotNullWhen(true)] out IView? view)
	{
		if (textInput is not IView iView ||
			iView.Handler is not IPlatformViewHandler platformViewHandler)
		{
			platformView = null;
			handler = null;
			view = null;
 
			return false;
		}
 
		if (iView.Handler?.PlatformView is not PlatformView platform)
		{
			platformView = null;
			handler = null;
			view = null;
 
			return false;
		}
 
		handler = platformViewHandler;
		platformView = platform;
		view = iView;
 
		return true;
	}
}
 
#if NETSTANDARD || !PLATFORM
public static partial class SoftInputExtensions
{
	static bool HideSoftInput(this object _) => throw new NotSupportedException();
 
	static bool ShowSoftInput(this object _) => throw new NotSupportedException();
 
	static bool IsSoftInputShowing(this object _) => throw new NotSupportedException();
}
#endif