问题
In my Android app, I have a View
which displays an image and has an associated ContentDescription
.
I can enable Settings->Accessibility->Talkback, with Explore By Touch from the Talkback settings, and then single tap on the View to read the ContentDescription
aloud.
This is all as expected so far.
However, I would like Explore By Touch to repeat the ContentDescription
if I single tap the same View
again. For example, my image and description may be updated while it has the AccessibilityFocus
, so saying the new phrase would be helpful to the user. How can I achieve this?
I've tried experimenting with View.clearFocus()
and View.invalidate()
, but with no success.
Any constructive ideas would be welcome.
Update
I should have also mentioned that I want to add support from API 8 onwards. Hence, I'm trying to do the best I can with the Accessibility interface from API 4.
I'm currently working on a solution that uses View.clearFocus()
followed by View.requestFocus()
to work around the updated-view issue. This appears to work so far on my test kit with APIs 8 and 16.
I'll update again with the final result, but welcome further suggestions in the interim.
回答1:
As promised in my question, here are the results of my investigation and a working solution.
Firstly, many thanks to alanv for his help and support, and for answering the question for later APIs (14 and upwards). Although he didn't find the solution for older APIs, he did provide critical information which helped me find an answer.
At the time of writing, it is not possible to construct a successfully-spoken AccessibilityEvent
, due to a known bug in TalkBack - see Send accessibility event not linked to view for further details. If the event source is null, the event is ignored by TalkBack (v3.5.0_r105) and as AccessibilityEvent.setSource(View)
first appeared in API 14, it is not possible to set the source prior to that - see Google Eyes-Free issue #379
However, it is possible to make Android generate such events by using View.requestFocus()
as I previously hinted.
Make your View focusable in its XML layout using:
android:focusable="true"
android:focusableInTouchMode="true"
Set the spoken text using
View.setContentDescription(text)
inActivity.onCreate
or withandroid:contentDescription="text"
in the XML layout if it is static, or dynamically in code if necessary.When the spoken text is required, move the focus to the correct view using
View.requestFocus()
to trigger anAccessibilityEvent
.To ensure that a phrase is repeated (my original question), call
View.clearFocus()
before requesting focus in the previous step.
I have a tested implementation of this approach working on API 8, and it also works on API 16. It should work all the way back to API 4, when the Accessibility API was first introduced.
This solution may not be required for developers who only support more recent Android APIs (14 and later), but I believe there are few other options currently for those supporting Accessibility in earlier APIs. Good luck.
Update
Unfortunately, alanv's answer seems to have disappeared - possibly deleted - taking with it all the associated detail and discussion in the comments. I have attempted to recapture the main points below.
For Android API 14 and later, it is possible to create focused events as follows:
if (mAccessibilityService.isEnabled()) { AccessibilityEvent event = AccessibilityEvent.obtain( AccessibilityEvent.TYPE_VIEW_FOCUSED); event.setSource(myView); // API 14 & later event.setClassName(myView.getClass().getName()); event.setPackageName(myView.getContext().getPackageName()); event.setEnabled(true); event.setContentDescription(text); myView.sendAccessibilityEventUnchecked(event); }
For Android API 16 and later,
View.announceForAccessibility(text)
can be used.
来源:https://stackoverflow.com/questions/24809471/android-how-to-force-explore-by-touch-talkback-to-repeat-the-contentdescription