Android PagerTabStrip对讲可访问性

Android PagerTabStrip对讲可访问性,android,accessibility,talkback,Android,Accessibility,Talkback,我目前正努力用更多的TalkBack发声来创建PagerTabStrip。 背景是: 我想为对讲用户在左右选项卡上添加“未选择选项卡[选项卡名称],单击两次以选择”和“已选择选项卡[选项卡名称]”到中间位置 我还想在单击选项卡时添加一个发声,以警告用户其内容已更改,并告诉TalkBack聚焦中心选项卡 通过重写所有需要的类(例如:PagerTitleStrip,ViewPager,FragmentPagerAdapter),并直接在选项卡TextView上添加右侧的contentDescri

我目前正努力用更多的
TalkBack
发声来创建
PagerTabStrip
。 背景是:

  • 我想为
    对讲
    用户在左右选项卡上添加“未选择选项卡[选项卡名称],单击两次以选择”和“已选择选项卡[选项卡名称]”到中间位置
  • 我还想在单击选项卡时添加一个发声,以警告用户其内容已更改,并告诉
    TalkBack
    聚焦中心选项卡
通过重写所有需要的类(例如:
PagerTitleStrip
ViewPager
FragmentPagerAdapter
),并直接在选项卡
TextView
上添加右侧的
contentDescription
,我已经部分成功地完成了这项工作。它运行得相当好,但我不满意。这些类的维护需要针对Android主类的每个新版本进行更新(或者我将保留旧的设计),并且我发现每次复制粘贴所有类内容都是肮脏的(下一个开发人员呢?)。 因此,我尝试了另一种方法:

  • PagerTabStrip
    的子类中使用
    AccessibilityEvent
    ,为发声提供更多上下文。它不起作用,因为
    AccessibilityEvent
    中的
    getText()
    getContentDescription
    方法不用于发声
  • ViewPager
    查看
    AccessibilityNodeInfo
    ,看看我是否能解决这个问题。但是我还没有确定发声的来源(是标签还是内容),也没有确定必须在
    AccessiblityNodeInfo
    中更改什么才能更改发声
因此,我想知道是否可以使用子类来解决我的问题,或者我除了复制主类之外是否别无选择。
提前感谢您的帮助。

这其实很简单。您要做的是创建PagerTabStrip的子类。在这个子类中,增加可访问性事件的传播以添加所需的信息!下面是我的实现

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

}
请注意,我覆盖了内容描述。通过这种方式,我们不改变应用程序的任何可视化表示,只改变talk back读取的内容


注:对讲用户使用“双击选择”部分。正如我在代码中所做的那样,我将关闭此选项。

对于选项卡本身,如果您负责扩大视图,则可以使用自定义TextView,根据其激活(或选定)状态修改其内容描述:

其中,
R.string.tab_selected
%1$s selected

这预先假定您(或)在选中时正在使用
setActivated(true)/setSelected(true)
标记选项卡视图(以及使用
setActivated(false)/setSelected(false)
标记所有其他选项卡)


向用户宣布内容已更改的最简单方法是添加一个
ViewPager.OnPageChangeListener
,在页面更改时宣布:

viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {

    @Override
    public void onPageSelected(int position) {
        // TODO: format correctly with String resource to support translation
        viewPager.announceForAccessibility("Showing " + viewPager.getAdapter().getPageTitle(position));
    }

});

我知道Android TalkBack用户已经习惯了这种行为,而不知道什么是可点击的

(默认情况下)在可点击的元素上有一个指示,如@ChrisCM所述-TalkBack将在带有
视图的视图上附加“双击激活”(以前的“双击选择”)。OnClickListener
附加

您可以通过重写initializeAccessibilityNodeInfo(查看主机、AccessibilityNodeInfoCompat信息)方法,修改TalkBack通过辅助功能委托大声朗读的操作:

class TabAccessibilityDelegate extends AccessibilityDelegateCompat {

    @Override
    public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfoCompat info) {
        super.onInitializeAccessibilityNodeInfo(host, info);
        info.addAction(
                new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
                        AccessibilityNodeInfoCompat.ACTION_CLICK,
                        "select tab"
                )
        );
    }

}
并在每个选项卡视图上设置它:

ViewCompat.setAccessibilityDelegate(tabView, new TabAccessibilityDelegate());
这样,现在的对讲将显示:
“…双击以选择选项卡”


中给出了定制使用提示的其他方法。

Thansk很多,很有效!我使用我的OnPageChangeListener来选择带有Talkback的当前选项卡,而不是上次单击的选项卡。我知道Android TalkBack用户已经习惯了这种行为,但没有说明什么是可点击的,我想我会等待用户测试;-)
ViewCompat.setAccessibilityDelegate(tabView, new TabAccessibilityDelegate());