Search code examples
androidaccessibilitytalkback

PagerTabStrip TalkBack accessibility


I'm currently struggling to create PagerTabStrip with more TalkBack vocalization. The context is:

  • I want to add "Tab [tab name] not selected, click twice to select" on left and right tabs and "Tab [tab name] selected" to the center one for TalkBack user.
  • I also want to add a vocalization when a tab is clicked to warn user its content changed and tell TalkBack to focus the center tab.

I already succeeded partially doing it by rewriting all the needed classes (for instance: PagerTitleStrip, ViewPager, FragmentPagerAdapter) and adding the right contentDescription directly on the tab TextView. It works rather well but i'm not satisfied. The maintenance of those classes need to be updated for each new versions of the Android main classes (or i will keep the old design) and i find dirty to copy paste all the class content each time (and what about the next developers ?). So, I tried another approches:

  • Using AccessibilityEvent in a subclass of PagerTabStrip to give more context to vocalization. It did not work because getText() and getContentDescription methods in AccessibilityEvent are not used for vocalization.
  • Work on AccessibilityNodeInfo from ViewPager to see if i could work it out. But I have not identify the source of the vocalization (is it tabs or content) nor what must be changed in AccessiblityNodeInfo to change vocalization.

So, i wonder whether it is possible or not to use a subclass to solve my problem or if i have no choice but copying the main classes. Thanks in advance for your help.


Solution

  • This is actually pretty simple. What you want to do is create a subclass of PagerTabStrip. In this subclass, augment the propagation of accessibility events to add the information that you wish! Below is my implementation.

    public class A11yPagerTabStrip extends PagerTabStrip {
    
        public A11yPagerTabStrip(Context context) {
            super(context);
        }
    
        public A11yPagerTabStrip(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
    
        @Override
        public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
            Log.wtf(LOG_TAG, "onRequestSendAccessibilityEvent: " + event.toString());
    
            final String textViewTitle = ((TextView) child).getText().toString();
            final ViewPager viewPager = (ViewPager) this.getParent();
            final int itemIndex = viewPager.getCurrentItem();
    
            String title = viewPager.getAdapter().getPageTitle(itemIndex).toString();
    
            if (textViewTitle.equalsIgnoreCase(title)) {
                child.setContentDescription("Tab " + textViewTitle + "selected.");
            } else {
                child.setContentDescription("Tab " + textViewTitle + "not selected.");
            }
    
            return super.onRequestSendAccessibilityEvent(child, event);
        }
    
    }
    

    Notice that I override the content description. In this way we don't change any of the visual representation of the application, just what talk back reads out.

    NOTE: Talkback users are use to the "double tap to select" portion. I would leave this off, as I have done in my code.