横向模式下的 OnApplyWindowInsetsListener 用于检测键盘可见性变化

2024-05-12

感谢这里的这个很好的答案:https://stackoverflow.com/a/63595830/741795 https://stackoverflow.com/a/63595830/741795我们现在可以跟踪 Android 中何时显示键盘...不幸的是我发现了一些问题。

事实证明,对于 API 29 及以下版本,OnApplyWindowInsetsListener.onApplyWindowInsets只被称为:

  • 当活动在清单中具有“调整调整大小”标志时
  • 仅适用于纵向模式。

对于 api 30+,一切都可以在纵向和横向下工作,并且没有标志。

由于这些限制,对于 api 29-我使用不同的方法(参见下面的代码),使用OnGlobalLayoutListener.onGlobalLayout

// in activity onCreate():

val rootView = window.decorView.rootView
        if (isApi30()) {
            val isKeyBoardVisible = isKeyboardShownOlderApis(rootView)
            Log.d("KeyBoardVisibility", "initial keyboard state is: $isKeyBoardVisible for view: $rootView")
            ViewCompat.setOnApplyWindowInsetsListener(rootView, WindowInsetListener(isKeyBoardVisible))
        } else {
            rootView.viewTreeObserver.addOnGlobalLayoutListener(KeyBoardListener(rootView))
        }

那么实际的听众:

//TODO: beware of leaks use weak reference
    private class KeyBoardListener(val rootView: View) : ViewTreeObserver.OnGlobalLayoutListener {
        var isKeyBoardVisible: Boolean = false

        init {
            isKeyBoardVisible = isKeyboardShownOlderApis(rootView)
            Log.d("KeyBoardVisibility", "initial keyboard state is: $isKeyBoardVisible for view: $rootView")
        }

        /**
         * Does not get called in api 21-29 landscape when keyboard is opened/closed
         */
        override fun onGlobalLayout() {
            Log.d("KeyBoardVisibility", "onGlobalLayout called: orientation: " + rootView.resources.configuration.orientation)
            val keyBoardVisible = isKeyboardShownOlderApis(rootView)
            if (keyBoardVisible != isKeyBoardVisible) {
                Log.i("KeyBoardVisibility", "Keyboard is now ${if (keyBoardVisible) "visible" else "hidden"}")
                isKeyBoardVisible = keyBoardVisible
            }
        }
    }

    /**
     * Works api 30, 31
     * Works api 25 in portrait with android:windowSoftInputMode="adjustResize"
     */
    private class WindowInsetListener(initialKeyboardVisibility: Boolean) : OnApplyWindowInsetsListener {
        var isKeyBoardVisible = initialKeyboardVisibility

        @SuppressLint("LongLogTag")
        override fun onApplyWindowInsets(v: View?, insets: WindowInsetsCompat?): WindowInsetsCompat? {
            val keyBoardVisible = insets?.isVisible(ime()) ?: false
            Log.d("KeyBoardVisibility", "onApplyWindowInsets called: $v with keyboardVisibility: $keyBoardVisible")
            if (keyBoardVisible != isKeyBoardVisible) {
                Log.i("KeyBoardVisibilityChanged", "Keyboard is now ${if (keyBoardVisible) "visible" else "hidden"}")
                isKeyBoardVisible = keyBoardVisible
            }
            insets?.let {
                v?.onApplyWindowInsets(insets.toWindowInsets())
            }
            return insets
        }
    }
}

private fun isKeyboardShownOlderApis(rootView: View?): Boolean {
    if (rootView == null) {
        return false
    }
    val insets = ViewCompat.getRootWindowInsets(rootView)
    if (insets == null) {
        Log.i("KeyBoardVisibility", "insets is null")
    }
    return insets?.isVisible(ime()) ?: false
}

private fun isApi30() = Build.VERSION.SDK_INT >= 30

问题:onGlobalLayout当键盘在横向模式下显示/隐藏时不会被调用,我在许多模拟器和手机上尝试过,它确实可以在平板电脑上运行。

我找到了这个示例项目:https://github.com/android/user-interface-samples/tree/master/WindowInsetsAnimation https://github.com/android/user-interface-samples/tree/master/WindowInsetsAnimation但在 API 21-29 中,这些方法也不会被调用,这对于动画来说很好,但在我的情况下则不然,所以那里肯定有问题。我到处找遍了,根本没有找到任何关于这方面的信息。

更多信息: 这将是一个 SDK 代码,因此我不能指望用户在清单中设置任何标志或任何 fitSystemWindows 标志 我在用androidx.core:core-ktx:1.5.0但1.6.0有同样的问题。

我可以尝试什么想法吗?我怀疑窗口有所不同,因为键盘与 editText 一起占据了整个屏幕,但为什么它可以与新的 APIS 一起使用?


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

横向模式下的 OnApplyWindowInsetsListener 用于检测键盘可见性变化 的相关文章

随机推荐

  • 如何在SQLite中的两个表之间复制数据?

    我有两个具有不同列的表 如下所示 table1 id title name number address table2 id phone name address 如何将数据 名称 地址 从表 1 复制到表 2 我的问题有两种情况 第一 t
  • 如何使用 Passport-saml 向 TestShib IdP 提供 SP 元数据?

    我有一个node js脚本 使用护照 saml https www npmjs com package passport saml 模拟 SP 我的目标是将其连接到此TestShib IdP https idp testshib org i
  • Java Sqlite Gradle

    我对 gradle 和 java 还很陌生 我有一个使用 sqlite 的项目 它通过 intellij idea 运行良好 但我无法从终端运行它 它会抛出异常 java lang ClassNotFoundException org sq
  • R testthat 单元测试数据和辅助函数约定

    我正在编写一个 R 包 并使用 testthat 进行单元测试 我的许多单元测试都是为了测试适用于我的包特定对象的功能 对于这些测试 我创建了一个辅助函数来设置模拟对象 我还有一些其他辅助函数来减少单元测试中的代码量 目前这些辅助函数在我的
  • Salesforce 返回“unsupported_grant_type”

    我们使用 Web 服务器身份验证流程实现了 OAuth 2 0 十月 十一月时运行良好 但突然停止运行 每当我们尝试授权另一个客户端时 服务器都会返回 400 Bad Request 和正文 error unsupported grant
  • nginx代理认证拦截

    我有几个服务 它们支持 nginx 实例 为了处理身份验证 在 nginx 中 我拦截每个请求并将其发送到身份验证服务 在那里 如果凭据正确 我将设置一个包含用户相关信息的 cookie 现在 请求应该被路由到适当的服务 并设置 cooki
  • Python,Bokeh:如何更改日期时间轴的范围

    我想使用按钮设置日期时间轴的范围 然而 该命令 f x range Range1d start start date end end date 不起作用 单击按钮时没有任何反应 无论是在运行 Bokeh 服务器的终端窗口中 还是在 Chro
  • 如何检测CSRF漏洞[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 给定一个网站 如何检测潜在的 CSRF 漏洞 提前致谢 这是一个CSRF https www owasp org index php
  • Numpy 的结构化数组与 xarray (xray) 有什么区别?

    有什么区别Numpy 结构化数组命名字段 https docs scipy org doc numpy 1 16 1 user basics rec html vs xarray http xarray pydata org en stab
  • 非虚实例方法继承是如何解决的?

    通过 C 从 CLR 引用 它读起来就像call将在运行时通过 CLR 搜索由基类型定义的方法 Then callIL指令用于调用实例或虚拟 方法中 您必须指定一个引用对象的变量 方式 变量本身的类型指示定义该方法的类型 CLR 应该调用
  • Mac 上的 cp --parents 选项

    在 Linux 上 我有一个可用于 cp 命令的 parents 选项 因此我可以执行以下操作 cp parents test withintest go rb test2 http www gnu org software coreuti
  • 从 JavaScript 重新启动动画 GIF,无需重新加载图像

    我正在使用动画 GIF 创建动画幻灯片 我正在从一个动画淡入淡出到下一个动画 问题是 我发现确保 GIF 从第一帧开始动画的唯一方法是每次显示时重新加载它 每个 GIF 大约 200KB 这对于连续幻灯片播放来说带宽太大了 这是我当前的代码
  • soundcloud 轨道的流 URL,其中 Streamble 为 false

    曲目有一个 streamable 属性 如果 false 我无法获取该曲目的stream url 但我发现很少有下载器获取同一首歌曲的stream url 然后获取该曲目的 CDN 链接 我什至验证了我的应用程序 但没有找到stream u
  • 使用 3.5 或 4.0 等旧版 .net 学习 C#.net、asp.net 的主要概念或基本概念是否重要? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 请向我建议是否需要学习c net和asp net的主要概念或基本概念 我需要与使用旧版本 net框架3 5或4 0的公司合作 在工作时我可以学习
  • SQL Server:索引或主键的总大小不能超过 900 字节

    我正在尝试在包含 URL 的列上放置索引 由于 URL 的最大长度超过 2000 个字符 因此我将数据类型设置为 NVARCHAR 3000 当我这样做时 我收到了错误The total size of an index or primar
  • AngularJS 服务在控制器之间传递数据

    当使用 AngularJS 服务尝试在两个控制器之间传递数据时 我的第二个控制器在尝试从服务访问数据时总是收到未定义的消息 我猜这是因为第一个服务执行了 window location href 并且我认为这是清除服务中的数据 有没有办法将
  • 通过 PowerShell 对 TFS 构建进行排队

    TFS2012 具有一个 2010 构建控制器和一个 2010 构建代理 还有一个 2012 构建控制器和多个 2012 构建代理 我们的软件有多个版本的多个版本 构建根据约定命名 例如Foo version 1 0 和 Foo versi
  • Java - 从配置文件加密/解密用户名和密码

    我们正忙于为客户开发 Java Web 服务 有两种可能的选择 将加密的用户名 密码存储在Web服务客户端上 从配置中读取 文件在客户端 解密并发送 将加密的用户名 密码存储在 Web 服务器上 从配置中读取 Web 服务器上的文件 解密并
  • 各个平台对 SHA-2 的支持情况如何?

    我读到 SHA 1 即将从 FIPS 180 2 标准中退役 http gcn com articles 2010 03 03 rsa sha competition aspxhttp gcn com articles 2010 03 03
  • 横向模式下的 OnApplyWindowInsetsListener 用于检测键盘可见性变化

    感谢这里的这个很好的答案 https stackoverflow com a 63595830 741795 https stackoverflow com a 63595830 741795我们现在可以跟踪 Android 中何时显示键盘