I have gone through many questions, API demo regarding Accessibility feature in Android but it couldn't help.
I want to support Accessibility in my Android application. Inbuilt Accessibility is taking care of all the focusable items and reads out the Hints correctly when clicked.
I want to fire Accessibility events whenever user clicks on TextView.And the first time the screen is opened, I want it to read out custom information which I provide. I have managed to do it with dispatchPopulateAccessibilityEvent but it reads everytime when screen is resumed. Also I can not identify which view is sending the event.
You can use the call "sendAccessibilityEvent", from within your TextView, like this:
if (AccessibilityManager.getInstance(mContext).isEnabled()) {
setContentDescription("The content description for this view");
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
The text read off (depending on which Accessibility Service is being used) will be based off the content description, not necessarily the text in the TextView.
If you want your view to be focused and annouce associated content description for that view then, You can use,
view.requestFocus()
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
If you just want to announce the change once only and don't want to change contentDescription associated with that view, you can use
view.announceForAccessibility = "Alert to a user about some event."
Note: announceForAccessibility will not get accessibility focus on your view.
You can use the
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
On your TextView, also you can add the "announceForAccessibility" but you should validation if the version is greater or equals than Jelly Bean but for that you need a change on the view.
Finally if you want to announce the "title" of the page, for example, the activity you could add the setTitle for the activity and put your text, remember use a Toolbar with a title because this setTitle by default will override the action bar title.
Let me know if you have any other issue.
Related
What is the difference between accessible, accessibilityLabel and accessibilityHint properties of Text component in react native? React native documentation is not enough to understand. Examples would be more appreciated.
accessible - the flag set to true will enable the view or component to be an accessibility element that can be read by VoiceOver for people with disabilities.
accessibilityLabel - When the VoiceOver goes over the accessibility element if there is no label given it will just read as a textfield, label or button. Instead you can make it read as "username field", "password field", "Login button" etc
accessibilityHint - This is used to inform the user what will be the action performed on tapping or interacting with that UI element.
For example if you've a "Login button" when the user clicks on it. You want to inform the user the action that will be performed after that some like - "When you tap on this login button. Your username and password will be validated and on successfull login you will be taken to the dashboard screen"
Also please refer this section of the ReactNative documentation. It is very thorough with some code examples https://facebook.github.io/react-native/docs/accessibility.
I hope this should help.
Get truth from the source: https://reactnative.dev/docs/accessibility:
accessible When true, indicates that the view is an accessibility element. When a view is an accessibility element, it groups its children into a single selectable component. By default, all touchable elements are accessible.On Android, accessible={true} property for a react-native View will be translated into native focusable={true}.
accessibilityHint
An accessibility hint helps users understand what will happen when they perform an action on the accessibility element when that result is not clear from the accessibility label.
Hints are only necessary for elements that are uncertain, and primarily intended for interactive elements, not text. Login buttons don't need hints. You know you are logging in. But maybe selecting text plays a song. What? That is not expected, so the accessibilityHint for that would be something simple and direct, like "plays this song". Notice the verb is not a command. And it's not a long sentence like #Hasseb here suggested. Also note that this interactive example is a button because it performs an action. Code it as a button with accessibilityRole="button".
accessibilityLabel
When a view is marked as accessible, it is a good practice to set an accessibilityLabel on the view, so that people who use VoiceOver know what element they have selected. VoiceOver will read this string when a user selects the associated element.
The example in ReactNative of stating "Tap me" when a button has text saying "Press me!" is not good; text is already there and the suggested label is a different word. That's straight up confusing! AccessibilityLabel is more intended for icons like info icons; or a settings menu (whether shaped like a hamburger menu, person outline, or a gear, it's still settings); or images that are tappable. The accessibilityLabel for settings is AccessibilityLabel="settings". Until you label that icon, it's just "button".
There are quiet a few more ReactNative APIs. Learn them, it will help your career.
I have a button in Android which has text "Next" written on it.
when, I have the accsessibility cursor focus on the button, it reads out "Next button". This is something I don't want. I want whenever, the cursor to have focus on the "Next" button, it must read out as "Next button. Double tap to select". This I can easily do, by setting the
btn.contentDescription("Next button. Double tap to select"),
but then it reads out as
"Next button. Double tap to select button", means it additionally reads out the last button, which seems very odd, with the "button" text getting read twice.
Is there any way, by which I can stop the last button to be announced?
You're trying to do things that are the responsibility of the AT. The AT knows that the object is a button due to its class type. The AT knows that it is clickable, because Clickable is a valid accessibility action.
TalkBack will then share this information, here is the breakdown:
"Next button, (pause) double tap to select"
"Next" -> Content Description/Text. This is the part you control.
"Button" -> Calculated in TalkBack based off of the valid actions and type(class) of the object.
"Double tap to select" -> This announcement is based off of Clickable being a valid accessibility action.
SO, when you set the contentdescription to "Next ....." you end up with an announcement of "next ....... button (pause) double tap to select" and no, there is no way to override this.
IF you are absolutely intent on making your app less accessible, you could create a custom control, write your own gesture recognizers (as in not using "onClick" events, because this would make your element accessibility clickable) to recognize tap gestures. And then write your own content description, that includes name, role, and instructions yourself.
This would be very silly in my opinion! Just let the content-description be "next" and let TalkBack tell users that your element is a button and how to interact with it. While perhaps not the "perfect" wording you/whoever this requirement came from's vision. It will be the way TalkBack users are accustomed to having this type of control announced. Consistency is sometimes more important than having things "just so".
I know I'm way late to the game, but posting an answer here for anyone that may happen to come across this post.
The others are right... we should not be putting the type of widget or how to interact with the widget in the content description. However, all is not lost.
Starting with API 21, there is a way to customize the interaction text through AccessibilityNodeInfo. You can use this class in two different ways:
AccessibilityNodeInfo has a getActionList() method. You can add customize the text that is read out by TalkBack by adding a new item to that list:
info.getActionList().add(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityAction.ACTION_CLICK, "select");
The above code should change "Double-tap to activate" to "Double-tap to select". I say should because I'm just writing that code from memory... I haven't verified it's 100% correct, but it should be something along those lines.
There are two ways to utilize that class, and the one you choose is going to depend on your situation.
Method 1: Subclass your view:
If you create a subclass of the view you are using (in the case of the OP it would be a subclass of Button) then you can override the onInitializeAccessibilityNodeInfo() method and put the code there.
Documentation: https://developer.android.com/reference/android/view/View.html#onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo)
Method 2: Create a view accessibility delegate
This can be a bit more tricky and involved, but it does offer a ton of flexibility because you don't have to subclass the views you are working with.
Every view has a method that allows you to set an accessibility delegate, which acts like a man-in-the-middle and you can tweak things for accessibility purposes before the info goes to TalkBack.
Documentation: https://developer.android.com/reference/android/view/View.html#setAccessibilityDelegate(android.view.View.AccessibilityDelegate)
So basically you create a subclass of View.AccessibilityDelegate and override it's onInitializeAccessibilityNodeInfo() method with the code I posted above.
Documentation: https://developer.android.com/reference/android/view/View.AccessibilityDelegate.html#onInitializeAccessibilityNodeInfo(android.view.View,%20android.view.accessibility.AccessibilityNodeInfo)
Last but not least...
I did come across a way to stop the "Double tap to activate" text from being spoken out by Talkback. This should only be used when it really does make sense to remove it.
I repeat... this is not normally something you want to do.
I did recently come across a case where it made sense. I was using a TabLayout, and I noticed that Talkback would always read out "Double-tap to select" when the focus was on the selected tab (yes, I had used the method described above to change the text). Well... we don't want to tell the user to select a tab that is already selected, especially when the action results in a no-op. So, I used this little trick to get rid of that, but only for the currently selected tab. I left the unselected tabs alone so that Talkback would still give them the interaction text.
In your onInitializeAccessibilityNodeInfo() method, you can put the following code to remove that text:
info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
Again, I'm writing this code from memory, so I don't know if that's 100% there, but it gives you the gist of what to do.
Try to uncheck the setting in TalkBack -> verbosity -> speak element type -> uncheck. Now talkback will not announce class type of view at end of content description.
What you want to do is employ android:hint to provide information on inputting information (instead of adding it to the label).
Your label would be "Next" (either using labelFor with an onscreen label or android:contentDescription for hidden labeling)
Then your hint would be "Double tap to select" (using android:hint)
I'm trying provide a Android Service that makes possible to do some actions when user make selection on any TextView (messages,books etc). But I don't know how to get this events outside my Activity.
I can add listener for specific TextView
mTextView.setCustomSelectionActionModeCallback
But I want get event (like setCustomSelectionActionModeCallback) from all TextViews.
I hope for your help!
I'm trying provide a Android Service that makes possible to do some actions when user make selection on any TextView (messages,books etc).
This is not possible. Each application handles its own action modes, context menus, etc. when text is selected.
My Android app contains a custom slider control based on the SeekBar, and I want to attach a custom text phrase to my control to explain its use for Accessibility.
I have done this successfully using View.setContentDescription(text), and TalkBack correctly speaks the phrase when I request focus on my slider control from Activity.onCreate.
So far, so good. However, when I touch the control, which I believe sets the AccessibilityFocus on my Android API 16 test device, extra words are being added to the spoken phrase, i.e. '...seek control. 0 per cent'. I want to remove these additional words.
I have tried to eliminate them using event.getText().clear() in View.onInitializeAccessibilityEvent(event) without success. Echoing the event to LogCat reports the correct phrase in event.contentDescription and no entries in event.text, but the extra words appear both in the audio output from the device hardware and in the on-screen debug text displayed by Menu->Settings->Accessibility->TalkBack->Settings->Developer Settings->Display Speech Output.
Please can anyone suggest where the extra words are being added, and how to eliminate them?
Any constructive suggestions would be welcomed. Thanks.
Update
I can see that some Explore By Touch (initial single-tap) event on my custom control does not pass through either its onInitializeAccessibilityEvent or dispatchPopulateAccessibilityEvent methods as I am deliberately calling event.setContentDescription(null). Despite this, there is an AccessibilityEvent being generated with my custom control's ContentDescription, set in Activity.onCreate in code, plus the extra words I'm trying to eliminate.
I've also set an AccessibilityDelegate on my custom control's parent ViewGroup to give visibility of its onRequestSendAccessibilityEvent calls. This confirms that no event containing my ContentDescription is passing through.
This is very puzzling, and happens on both the emulator and real hardware with API 16. Any ideas?
You also need to override http://developer.android.com/reference/android/view/View.html#onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo)
and set the contentDescription there.
If you want to remove the 0%, I would try to change the class in AccessibilityNodeInfo/AccessibilityEvent:
http://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo.html#setClassName(java.lang.CharSequence)
I believe that this is a bug in TalkBack, and have raised Google Eyes-Free issue #375, including example code.
Update: Google have now archived this. Link moved to: http://code.google.com/archive/p/eyes-free/issues/375
Pretty new to android so excuse me if this is a really obvious question.
Say my application has a bunch of TextViews, each one showing the attributes of a certain product (name, price, etc). I have a button next to each of these TextViews labeled "modify".
How do I make it so that when I press the modify button next to a certain attribute, a popup window with a space to enter text into comes up so that the user can enter text into this box and then have the actual attribute listing on the original page change? Actually I just need a push in the right direction with creating this popup text field... not sure if there is already some built in functionality for this or if not, what would be the best way to create this kind of thing.
Thanks.
Why not have the modify button set TextEdit.setEnabled(true); and then change focus with TextEdit.setFocus? Note that both of these are inherited from view
If you really want a dialog you might want to looking into the AlertDialog.Builder. I know you can use it with buttons and radio buttons, but I'm not sure you can get it to work with a TextView.
Use a code like this for the input popup: Android dialog input text
In the positive button handler, set your edittext content programmatically like this:
myEditText.setText(value).
As simple as that. The only difference with a standard GUI framework is that you don't retrieve the value as a result of the popup function. Instead, you must provide an action handler.