启用TalkBack时,有没有办法将辅助功能焦点手动设置为特定视图?例如,当我的Activity启动时,我希望TalkBack自动关注某个Button(视图周围的黄色框)并阅读其内容描述。
到目前为止我已尝试过:
myButton.setFocusable(true);
myButton.setFocusableInTouchMode(true);
myButton.requestFocus();
看来,requestFocus()似乎只是请求输入焦点而与可访问性焦点无关。我也试过了:
myButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
myButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
myButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
myButton.announceForAccessibility("accessibility test");
myButton.performAccessibilityAction(64, null); // Equivalent to ACTION_ACCESSIBILITY_FOCUS
AccessibilityManager manager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
if (manager.isEnabled()) {
AccessibilityEvent e = AccessibilityEvent.obtain();
e.setSource(myButton);
e.setEventType(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
e.setClassName(getClass().getName());
e.setPackageName(getPackageName());
e.getText().add("another accessibility test");
manager.sendAccessibilityEvent(e);
}
这些似乎都不起作用。
答案 0 :(得分:30)
免责声明:强制将活动负载集中在任何地方,但总是在顶部栏上(好吧,总是几乎不应该说),但实际上,就是不要这样做。它违反了各种WCAG 2.0法规,包括3.2.1和3.2.3,分别涉及可预测的导航和上下文变更。实际上,您可能实际上无法访问您的应用程序。
http://www.w3.org/TR/WCAG20/#consistent-behavior
结束免责声明。
您正在使用正确的函数调用。您需要做的就是:
myButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
问题更可能是您尝试执行此操作的时间点。对话会在活动周期的稍后阶段将您的活动与自己的活动联系起来。以下解决方案说明了这个问题,老实说,我不确定有更好的方法可以做到这一点。我尝试了onPostResume,这是Android操作系统调用的最后一个回调,关于加载活动,但我仍然需要延迟添加。
@Override
protected void onPostResume() {
super.onPostResume();
Log.wtf(this.getClass().getSimpleName(), "onPostResume");
Runnable task = new Runnable() {
@Override
public void run() {
Button theButton = (Button)WelcomeScreen.this.findViewById(R.id.idButton);
theButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
};
final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
worker.schedule(task, 5, TimeUnit.SECONDS);
}
您可以创建自定义视图。视图中的回调可以提供您执行此操作所需的逻辑,而不会出现竞争条件!如果我有时间的话,我可能会在以后更深入地研究它。
答案 1 :(得分:5)
我遇到了同样的问题,因为为了保持一致的导航,我们希望选择新打开的页面的标题。 问题是屏幕阅读器选择的是页面左上方的第一个标题按钮,而不是标题。
对于整个视图,我有一个myRootView
变量,对于标题文本视图,我有一个myTitleView
变量。
ChrisCM为使可访问性集中在正确视图上而提出的解决方案肯定对我有帮助:
myTitleView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
但是我仍然有一个问题,因为屏幕阅读器尚未准备好,所以在应用程序启动时调用此代码没有任何效果,而我提出的等待5整秒的“等待对讲可用”的解决方案不是我所需要的想要这样做,因为到那时,用户可能已经在使用该界面,并且自动聚焦会打断他们的选择。
我注意到在打开应用程序时,可访问性系统地选择了左上角的标题按钮,因此我编写了一个类来侦听该选择并随后触发我自己的选择。
这是相关课程的代码:
import android.view.View;
import android.view.View.AccessibilityDelegate;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public abstract class OnFirstAccessibilityFocusRunner extends AccessibilityDelegate implements Runnable {
@NonNull
private final View rootView;
private boolean hasAlreadyRun = false;
public OnFirstAccessibilityFocusRunner(@NonNull final View _rootView) {
rootView = _rootView;
init();
}
private void init() {
rootView.setAccessibilityDelegate(this);
}
@Override
public boolean onRequestSendAccessibilityEvent(@Nullable final ViewGroup host, @Nullable final View child,
@Nullable final AccessibilityEvent event) {
if (!hasAlreadyRun
&& event != null
&& event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
) {
hasAlreadyRun = true;
rootView.setAccessibilityDelegate(null);
run();
}
return super.onRequestSendAccessibilityEvent(host, child, event);
}
}
然后,我使用这样的代码(例如,在Activity的onPostResume方法中):
@Override
protected void onPostResume() {
new OnFirstAccessibilityFocusRunner(myRootView) {
@Override
public void run() {
myTitleView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
};
}
我花了几个小时才弄清楚如何立即将焦点对准正确的视图,希望对其他人也有帮助!
答案 2 :(得分:2)
最近我遇到了同样的问题。我创建了一个Android扩展功能,以像上面的解决方案一样聚焦未使用postDelayed
聚焦的视图;
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
但是我还有另一种情况,它不起作用。但是,我可以使用它:
fun View.accessibilityFocus(): View {
this.performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)
this.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED)
return this
}
答案 3 :(得分:0)
免责声明:似乎某些视图拦截了可访问性焦点(例如RecyclerView,PreferenceFragmentCompat),而我的解决方案是“等待对讲可用”。
当视图准备好向用户显示时,Kotlin KTX提供了执行smth的方法,Coroutine可以帮助您延迟。这不是最好的方法,但又快速又简单。
CoroutineScope(Dispatchers.Default).launch {
delay(300)
withContext(Dispatchers.Main) { customView.doOnLayout {it.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED) }}
}