Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - Set TalkBack accessibility focus to a specific view

When TalkBack is enabled, is there any way to set the accessibility focus manual to a specific view? For instance, when my Activity is started I want TalkBack to automatically focus on a certain Button (yellow frame around the view) and read its content description.

What I've tried so far:

    myButton.setFocusable(true);     myButton.setFocusableInTouchMode(true);     myButton.requestFocus(); 

requestFocus(), it seems, is only requesting input focus and has nothing to do with accessibility focus. I've also tried:

    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);     } 

None of this seems to work.

like image 263
Skywalker10 Avatar asked Feb 12 '15 08:02

Skywalker10


People also ask

How do you use TalkBack Accessibility?

Enabling TalkBack: Go to Settings > Accessibility > TalkBack to turn on TalkBack. To activate the TalkBack shortcut, go to Settings > Accessibility and turn on the Volume Key Shortcut. You can then hold the volume keys for a few seconds to turn TalkBack on or off.

How do I turn off focus in Accessibility?

performAccessibilityAction( AccessibilityNodeInfo. ACTION_CLEAR_ACCESSIBILITY_FOCUS, null); to clear the accessibility focus.


2 Answers

DISCLAIMER: Forcing focus on Activity load to be anywhere but at the top bar is always (okay, always should almost never be said), but really, just don't do it. It is a violation of all sorts of WCAG 2.0 regulations, including 3.2.1 and 3.2.3, regarding predictable navigation and context changes respectively. You are, likely, actually making your app MORE inaccessible by doing this.

http://www.w3.org/TR/WCAG20/#consistent-behavior

END DISCLAIMER.

You are using the correct function calls. All you should need to do is this:

myButton.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); 

The problem is more likely the point at which your attempting to do this. Talkback attaches itself to your activity slightly later in the activity cycle. The following solution illustrates this problem, I'm not sure there is a better way to do this, to be honest. I tried onPostResume, which is the last callback the Android OS calls, regarding the loading of activities, and still I had to add in a delay.

@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);  } 

You might be able to create a custom view. The callbacks within view, may provide the logic you need to do this, without the race condition! I might look into it more later if I get time.

like image 88
ChrisCM Avatar answered Sep 20 '22 08:09

ChrisCM


Recently I had the same problem. I created an Android extension function to focus a view that was not focused with a postDelayed like the other solutions proposed;

sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED) 

But I had another scenario where it didn't work. However, I got it to work with this:

fun View.accessibilityFocus(): View {     this.performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)     this.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED)     return this } 
like image 29
Gilberto Ibarra Avatar answered Sep 17 '22 08:09

Gilberto Ibarra