当在 Android 中启用 Talkback 时,视图在延迟转换后变为 VISIBLE 后不可选择

如何解决当在 Android 中启用 Talkback 时,视图在延迟转换后变为 VISIBLE 后不可选择

当以某种方式使视图可见时,Talkback 无法再选择/单击/聚焦该视图,请参阅: https://github.com/kai-vala/DemoForAccessibilityBugs/blob/master/images/animation.gif

(没有足够的代表嵌入图像)

完整的示例应用程序在这里: https://github.com/kai-vala/DemoForAccessibilityBugs

意识到它是由过渡引起的,如果我们删除:TransitionManager.beginDelayedTransition(it),视图总是可选的。

我正在寻找一种方法,即使在延迟过渡的情况下,焦点/可点击也能始终如一地工作。


在模拟器上运行 Android 11 时应始终如一地出现以下情况:

  1. 重新启动应用

  2. 点击按钮执行转换

  3. 尝试选择“Edit text 2”视图,注意它不能被点击(使用 Talkback 滑动导航也会绕过它)


为了完整起见,我将在下面添加一个最小的代码示例,但我建议直接从 repo 中查看。

编辑:在我意识到这是由转换引起的后,修改了示例代码以使其更简单。

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable
            name="vm"
            type="com.valagroup.demoforaccessibilitybugs.MainViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="12.5dp"
        android:layout_marginTop="12.5dp"
        android:layout_marginEnd="12.5dp"
        android:layout_marginBottom="12.5dp"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/title_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:minWidth="44dp"
            android:minHeight="44dp"
            android:text="Remember to enable Talkback"
            android:textAppearance="@style/TextAppearance.AppCompat.Headline"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <!-- See MainActivity.kt where the transition is started -->
        <androidx.appcompat.widget.AppCompatButton
            android:id="@+id/toggleButton"
            style="@style/Widget.AppCompat.Button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="44dp"
            android:text="Transition between text boxes"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/title_text" />

        <androidx.appcompat.widget.AppCompatEditText
            android:id="@+id/editTextByButton1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="12.5dp"
            android:text="Edit text other 1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/toggleButton"
            app:visible="@{vm.buttonState == true}" />

        <androidx.appcompat.widget.AppCompatEditText
            android:id="@+id/editTextByButton2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="12.5dp"
            android:text="Edit text other 2"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/editTextByButton1"
            app:visible="@{vm.buttonState == false}" />

        <TextView
            android:id="@+id/bottom_text2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="12.5dp"
            android:text="Above text boxes are not enabled correctly \nWhen transitions are used with Talkback enabled"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/editTextByButton2" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

MainViewModel.kt

class MainViewModel : ViewModel() {
    val buttonState = MutableLiveData<Boolean>().apply { value = true }

    fun toggleButtonState() {
        buttonState.value = !buttonState.value!!
    }

    init {
        Log.d("MainViewModel","init")
    }
}

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: ActivityMainBinding =
            DataBindingUtil.setContentView(this,R.layout.activity_main)
        binding.vm = ViewModelProvider(this).get(MainViewModel::class.java)
        binding.lifecycleOwner = this

        binding.toggleButton.setOnClickListener { v ->
            if (v != null) {
                Log.d("OnClick","toggleButton")
                val viewModel = binding.vm as MainViewModel
                viewModel.toggleButtonState()
                binding.toggleButton.findParent<ConstraintLayout>()?.let {
                    // TODO/FIXME: The issue where edit texts are not enabled is caused by the transition
                    TransitionManager.beginDelayedTransition(it)
                }
            }
        }
    }
}

@BindingAdapter("visible")
fun visible(view: View,visible: Boolean?) {
    Log.d("BindingAdapter","Changing visibility of view '${view.id}' to: $visible")
    view.visibility = if (visible == true) View.VISIBLE else View.GONE
}

private inline fun <reified T : ViewGroup> View.findParent(): T? {
    var view = this.parent
    while (view != null) {
        if (view is T)
            return view
        view = view.parent
    }
    return null
}

解决方法

AOSP 开发人员回答的解决方法: https://issuetracker.google.com/185532478

我们修复了 S 中与可见性更改相关的错误,我认为该错误是导致此错误的原因,尽管有一些细节我无法解释。

问题在于,当视图变得不可见时,我们没有发送辅助功能事件,因为我们不允许不可见的视图发送事件。解决方法是让父级发送子树更改事件。

我认为,如果您检查 AccessibilityManager#isEnabled 是否已启用,如果是,则在父级上调用 notifySubtreeAccessibilityStateChanged,您将强制发送正确的事件并提醒服务旧视图已消失。

parent= view.parent
// null check,etc
parent.notifySubtreeAccessibilityStateChanged(parent,parent,AccessibilityEvent#CONTENT_CHANGE_TYPE_SUBTREE)

原则上,您应该只在视图变得不可见时才需要这样做,因为视图变得可见会发送一个事件。但是按照这个推理,我不明白为什么使第二个编辑文本可见并不能解决问题。无论哪种方式,我认为通知子树更改应该可以解决问题。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-