17

I have a view that has a long press action handler. I use the content description to set the message Talkback speaks when the view gets focus.

Currently it says my content description right after getting a focus, and after a short pause says:

Double tap to activate, double tap and hold for long press

I want to change this message into something like

Double tap to "action 1", double tap and hold for "action 2"

Is there a way to do so?

I looked into onPopulateAccessibilityEvent(), it gets TYPE_VIEW_ACCESSIBILITY_FOCUSED event, but I wasn't able to change the desired message.

Am I missing something simple?

Paul
  • 1,879
  • 1
  • 23
  • 44

5 Answers5

22

It seems AccessibilityAction has changed slightly since alanv posted his answer. Here is a working solution using ViewCompat:

ViewCompat.setAccessibilityDelegate(view, new AccessibilityDelegateCompat() {
    @Override
    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
        super.onInitializeAccessibilityNodeInfo(host, info);
        // A custom action description. For example, you could use "pause"
        // to have TalkBack speak "double-tap to pause."
        CharSequence description = host.getResources().getText(R.string.my_click_desc);
        AccessibilityActionCompat customClick = new AccessibilityActionCompat(
                    AccessibilityNodeInfoCompat.ACTION_CLICK, description);
        info.addAction(customClick);
    }
});
JustinMorris
  • 7,259
  • 3
  • 30
  • 36
12

In API 21+, you can customize the action names by setting up custom actions on your View's AccessibilityNodeInfo. There are two approaches to this: 1) set an AccessibilityDelegate and override the onInitializeAccessibilityNodeInfo delegate method or 2) extend the view's class and override onInitializeAccessibilityNodeInfo.

Either way, you will be constructing a new AccessibilityAction and setting it on the node using AccessibilityNodeInfo.addAction.

If you chose to use a delegate, you would set a custom description for the click action as follows:

view.setAccessibilityDelegate(new AccessibilityDelegate() {
  @Override
  public void onInitializeAccessibilityNodeInfo(
      View v, AccessibilityNodeInfo info) {
    super.onInitializeAccessibilityNodeInfo(v, info);

    // A custom action description. For example, you could use "pause"
    // to have TalkBack speak "double-tap to pause."
    CharSequence description = getResources().getText(R.string.my_click_desc);
    AccessibilityAction customClick = new AccessibilityAction(
            AccessibilityAction.ACTION_CLICK, description);
    info.addAction(customClick);
  }
});

If you application targets API < 21, substitute the appropriate *Compat support library methods. The feature is not backported, so you won't get custom descriptions on API < 21, but you will be able to avoid explicit version checks in your application code.

Community
  • 1
  • 1
alanv
  • 23,966
  • 4
  • 93
  • 80
  • Applying the *Compat to this - could you post an example? setAccessibilityDelegate doesn't take a compat nor is there a setter for the compat version. – fobbymaster Dec 22 '16 at 20:43
  • @fobbymaster use ViewCompat.setAccessibilityDelegate(View v, AccessibilityDelegateCompat delegate) – qtyq Feb 02 '17 at 01:52
  • @alanv, this will only add to the existing list right? It will still speak 'double tap to activate' followed by your 'double tap to pause'? – user3030130 Feb 22 '17 at 02:30
  • @user3030130 No, it will replace the existing description of the action. – alanv Feb 22 '17 at 18:05
  • Right, but if there are other actions for the view, especially the default ones that you don't add, this action is being spoken along with the other actions. Do you know how to remove all actions and just add yours? – user3030130 Feb 23 '17 at 02:50
  • Post a new question. This is outside the scope of the original question. – alanv Feb 23 '17 at 17:21
  • 3
    This is only replacing the last word for me. the first part of the sentence "double tap to" is still available. Is it possible to replace the whole sentence? – Red M May 18 '17 at 01:34
  • Replacing the whole sentence wouldn't make sense because you can't know what the accessibility service's user interface is like. – j__m Oct 06 '18 at 06:28
  • @RedM Where you able to figure out how to prevent talkback from saying "Double tap to ___" – LoveMeSomeFood Jul 25 '19 at 21:04
  • How to do the same for RemoteView used to make widget? – Ajay Singh Jun 04 '21 at 16:43
8

Use the code below for those who want to remove the all phrase ie. "double tap to activate", "double tap and hold for long press".

mSubTitleText = (TextView) view.findViewById(R.id.txt_subtitle);

 ViewCompat.setAccessibilityDelegate(mSubTitleText, new AccessibilityDelegateCompat() {
            @Override
            public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
                host.setClickable(false);
                host.setLongClickable(false);
            }
        });
Azeela
  • 213
  • 3
  • 8
1

Here is one sample:

ViewCompat.setAccessibilityDelegate(set_actions_button, object : AccessibilityDelegateCompat() {
    override fun onInitializeAccessibilityNodeInfo(v: View, info: AccessibilityNodeInfoCompat) {
        super.onInitializeAccessibilityNodeInfo(v, info)
        info.addAction(AccessibilityActionCompat(
            AccessibilityNodeInfoCompat.ACTION_CLICK, "Edit note"))
        info.addAction(AccessibilityActionCompat(
            AccessibilityNodeInfoCompat.ACTION_LONG_CLICK, "Copy note"))
    }
})

Take a look at this article which explains very well.

Thiago
  • 12,778
  • 14
  • 93
  • 110
0

Use the code below for those who want to remove the all phrase ie. "double tap to".

ViewCompat.setAccessibilityDelegate(view, new AccessibilityDelegateCompat() {
        @Override
        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
            super.onInitializeAccessibilityNodeInfo(host, info);
            info.addAction(AccessibilityNodeInfoCompat.ACTION_FOCUS);
        }
});

This is basically calling the below code and requestFocus does not have any default talkback announcement associated with it.

case AccessibilityNodeInfo.ACTION_FOCUS: {
                if (!hasFocus()) {
                    // Get out of touch mode since accessibility
                    // wants to move focus around.
                    getViewRootImpl().ensureTouchMode(false);
                    return requestFocus();
                }
            }
Rubin Yoo
  • 2,674
  • 2
  • 24
  • 32