繁体   English   中英

无法在 Android 9 上隐藏 Android 键盘

[英]Unable to hide Android Keyboard on Android 9

创建一个应用程序,点击 webview 输入字段,必须执行一个操作。 捕获并启动选定的操作工作正常,但由于它是通过单击输入字段启动的,因此需要键盘。 在 Android < 版本 9 上,我当前的代码可以很好地隐藏键盘,但在 Android 版本 9 上,它没有。

我已经尝试了这篇文章中被认为是最佳答案的所有庄园或组合,但没有一个适用于我在 Android 9 上的应用程序

下面是我的 MainActivity 中的一些代码,其中创建了我的键盘服务实现的实例。 MainActivity 代码之后是我为 android 制作的键盘服务实现。

[Activity(Label = "Dental.App", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ScreenOrientation = ScreenOrientation.SensorLandscape, 
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, WindowSoftInputMode = SoftInput.StateAlwaysHidden) ]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
protected override void OnCreate(Bundle savedInstanceState)
        {
            ...
            DependencyService.Get<IServiceCollection>().SetKeyboardService(new KeyboardService(this, GetInputMethodManager()));            
            ...
        }

public InputMethodManager GetInputMethodManager()
        {
            return (InputMethodManager)GetSystemService(Context.InputMethodService);
        }
    }
public class KeyboardService : IKeyboardService
    {
        private InputMethodManager inputMethodManager;
        private readonly object mainActivity;
        public KeyboardService(object activity, InputMethodManager methodManager)
        {
            mainActivity = activity;
            inputMethodManager = methodManager;
        }
        public bool IsKeyboardShown => inputMethodManager.IsAcceptingText;

        public void HideKeyboard()
        {
            if (inputMethodManager == null || !(mainActivity is Activity activity)) return;

            Logging.Log(LogType.Information, $"Attempting to Hide Keyboard via 1st method...");

            //var view = activity.CurrentFocus;
            var view = activity.FindViewById(Android.Resource.Id.Content).RootView;
            if (view == null) Logging.Log(LogType.Warning, $"Failed to get View from Activity...");

            var token = view?.WindowToken;
            if (token == null) Logging.Log(LogType.Warning, $"Failed to get Token from View...");

            var success = inputMethodManager.HideSoftInputFromWindow(token, HideSoftInputFlags.None);
            Logging.Log(LogType.Information,
                $"{nameof(inputMethodManager.HideSoftInputFromWindow)} returned => {success}");

            if(success) view?.ClearFocus();
            if (!IsKeyboardShown)
            {
                view?.ClearFocus();
                return;
            }

            Logging.Log(LogType.Warning,
                $"Failed to Hide Keyboard via {nameof(inputMethodManager.HideSoftInputFromWindow)}...");
            HideKeyboardAttemptTwo(activity);
        }

        private void HideKeyboardAttemptTwo(Activity activity)
        {
            Logging.Log(LogType.Information, $"Attempting to Hide Keyboard via 2nd method...");

            //var view = activity.CurrentFocus;
            var view = activity.FindViewById(Android.Resource.Id.Content).RootView;
            if (view == null) Logging.Log(LogType.Warning, $"Failed to get View from Activity...");

            var token = view?.WindowToken;
            if (token == null) Logging.Log(LogType.Warning, $"Failed to get Token from View...");

            inputMethodManager.ToggleSoftInputFromWindow(token, ShowSoftInputFlags.None, HideSoftInputFlags.None);

            if (!IsKeyboardShown)
            {
                view?.ClearFocus();
                return;
            }

            Logging.Log(LogType.Warning, $"Failed to Hide Keyboard via {nameof(inputMethodManager.ToggleSoftInputFromWindow)}...");
        }

        public void ReInitializeInputMethod()
        {
            inputMethodManager = InputMethodManager.FromContext((Context) mainActivity);
        }

没有一个空检查返回真,即没有任何东西是空的。 方法 HideKeyboard 中名为 success 的变量在 99% 的 Android 版本 9 上调用它的情况下返回 false。在 1% 的情况下为 true,键盘仍处于打开状态。 如果键盘仍然显示在 HideKeyboard 的末尾,则代码尝试通过在 HideKeyboardAttemptTwo 方法中切换它来关闭键盘。 在 Android 9 上执行这些方法中的任何一种都不起作用,但是在 Android 7.1 上运行完全相同的代码可以正常工作。

我不完全确定我是否正确实现了 ToggleSoftInputFromWindow 的使用,它旨在仅在键盘打开时才能运行,即始终用于隐藏键盘。

重申我的问题:如何在 Android 9 上成功隐藏键盘。

如果需要任何其他信息,请询问,我会尝试找到并提供它。

我将它用于我的应用程序,试一试

主项目中的接口

namespace *.Services.Interfaces
{
    public interface IForceKeyboardDismissalService
    {
        void DismissKeyboard();
    }
}

电话特定代码

using Plugin.CurrentActivity;  //Nugget used to get activity

[assembly: Xamarin.Forms.Dependency(typeof(AndroidForceKeyboardDismissalService))]
namespace *.Droid.PhoneSpecific
{
    public class AndroidForceKeyboardDismissalService : IForceKeyboardDismissalService
    {
        public void DismissKeyboard()
        {
            var imm = InputMethodManager.FromContext(CrossCurrentActivity.Current.Activity.ApplicationContext);
            imm?.HideSoftInputFromWindow(CrossCurrentActivity.Current.Activity.Window.DecorView.WindowToken, HideSoftInputFlags.NotAlways);

            var currentFocus = CrossCurrentActivity.Current.Activity.CurrentFocus;
            if (currentFocus != null && currentFocus is EditText)
                currentFocus.ClearFocus();
        }
    }
}

用法

DependencyService.Get<IForceKeyboardDismissalService>().DismissKeyboard();

让我知道它是否适合你。

为了解决我的问题,我将一些 JavaScript 注入到 Webview 中,在其中我没有聚焦输入字段,然后单击该字段。

在我的 Webview 类中,我创建了一个方法,如果给定元素的字符串 id,它将切换该元素是否获得焦点。 作为第二个输入,可以提供一个布尔值,但默认为 True,以指示您是否只想取消对元素的关注。

public class AdvancedWebView : HybridWebView
{
...
public void ToggleElementFocus(string elementId, bool onlyUnFocus = true)
        {
            var js = GetJsInvertFocus(elementId, onlyUnFocus);

            InjectJavaScript(js);

            // Logging.Logging.Log(LogType.Information, $"Injected Javascript => {js}");
        }
...
private string GetJsInvertFocus(string elementId, bool onlyUnFocus)
        {
            var builder = new StringBuilder();

            builder.Append($"if (document.getElementById('{elementId}'))");
            builder.Append("{");
            builder.Append($"var element = document.getElementById('{elementId}');");
            builder.Append($"if (element === document.activeElement)");
            builder.Append("{");
            builder.Append($"element.blur();");
            builder.Append("}");
            builder.Append($"else if({onlyUnFocus} == False)");
            builder.Append("{");
            builder.Append($"element.focus();");
            builder.Append("}");
            builder.Append("}");

            return builder.ToString();
        }
...
}

我正在从 XLabs 扩展 HybridWebview,因为它已经具有将 JavaScript 注入 Webview 的功能。 这就是我从中获取 InjectJavaScript 方法的地方。

在我的应用程序页面上,使用 Webview,然后当单击元素时,我有一个运行的方法。 要在单击 Webview 时获得单击事件,请查看此链接 在这个方法中,我从事件参数中找出元素 id 是什么,然后使用这个 id 注入上面显示的 JavaScript,使元素失去焦点,导致键盘根本不出现。 在我的 OnClicked 方法下方可以看到。

public partial class DentalWebPage : AdvancedTabbedPage
{
...
 private void DentalWebView_OnClicked(object sender, ClickEvent e)
        {
            try
            {
                if (LogUserPosition(sender, e)) return;

                SwapToScanningTap();
            }
            catch (Exception ex)
            {
                Logging.Log(LogType.Exception,
                    ex.GetType().Namespace == typeof(BaseException).Namespace
                        ? $"{ex.GetType()} => {ex}"
                        : $"{ex.GetType()} => {ex.Message}; Stacktrace => {ex.StackTrace}");
            }
        }

private bool LogUserPosition(object sender, ClickEvent e)
        {
            if (Config.DebugMode) Logging.Log(LogType.Debug, $"WebView was clicked...");

            if (Config.DebugMode) Logging.Log(LogType.Debug, $"Element that was clicked is the following one => {e.Element}");

            var success = Enum.TryParse(e.Element.Split(' ')[1].Split('=')[1], out clickedInputId);

            if (!success && !(clickedInputId == InputId.MainContent_TextBoxInputStr ||
                              clickedInputId == InputId.MainContent_TextBoxScanOrder ||
                              clickedInputId == InputId.MainContent_TextBoxSelectProd ||
                              clickedInputId == InputId.MainContent_TextBoxStockReturn))
                return true;

            if (Config.DebugMode && webPageEnding == WebsiteControllers.Stock.ToString().ToLowerInvariant())
                Logging.Log(LogType.Debug, $"WebView was clicked while on the stock page...");

            return false;
        }

private void SwapToScanningTap()
        {
            PerformOnMainThread(() =>
            {
                CurrentPage = Children[1];

                ScanningToggle.IsToggled = true;

                try
                {
                    var isKeyboardShown = services.KeyboardService.IsKeyboardShown;
                    if (Config.DebugMode) Logging.Log(LogType.Debug, $"IsKeyboardShown returns => {isKeyboardShown}");

                    DentalWebView.ToggleElementFocus(clickedInputId.ToString());
                }
                catch (ObjectDisposedException)
                {
                    if (DisposedReattempt) throw;

                    if (Config.DebugMode)
                        Logging.Log(LogType.Debug,
                            $"Input Method has been Disposed; Attempting to reinitialize it and rerun the {nameof(SwapToScanningTap)} method ones again");

                    DisposedReattempt = true;
                    services.KeyboardService.ReInitializeInputMethod();
                    SwapToScanningTap();
                }
            });
        }
...
private void PerformOnMainThread(Action action)
        {
            try
            {
                Device.BeginInvokeOnMainThread(action);
            }
            catch (Exception ex)
            {
                Logging.Log(LogType.Exception,
                    ex.GetType().Namespace == typeof(BaseException).Namespace
                        ? $"{ex.GetType()} => {ex}"
                        : $"{ex.GetType()} => {ex.Message}; Stacktrace => {ex.StackTrace}");
            }
        }
}

如果您想了解 e.Element 中包含的字符串的格式,请查看之前提供的链接。

随意提出进一步的问题,以防我错过了什么。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM