通过 WebView 以编程方式触发 Android TalkBack 文本

Triggering Android TalkBack Text Programmatically Via A WebView

所以我一直在努力制作一个 Android WebView,其中包含一些文本,以便盲人用户更容易访问,我想知道是否可以触发 Android TalkBack 来朗读一些文本自动?

我在想 link 这样的:

<a href="#" id="flubble">Flubble</a>

还有一个这样的元素:

<a href="#" id="bibble">Bibble</a>

然后使用焦点事件自动读取link中的文本:

document.getElementById("flubble").addEventListener("click", function(event) {
    event.preventDefault();
    document.getElementById("bibble").focus();
    //I want it to say "bibble" here
});

本质上,当它聚焦时,我希望它说出文字?有什么方法可以实现这个“Auto TalkBack”功能吗?

干杯 <3

简答

使用视觉上隐藏的 aria-live 区域并将相关文本复制到该区域。此外,使用 <button> 而不是 <a href="#" 用于交互式内容。

长答案

在没有明确目的的情况下扰乱用户焦点(例如在模式打开时将关闭按钮聚焦在模式中)...坏主意,你最不想做的就是让用户失去他们在页。

此外,这意味着您需要在整个页面中的任何要读出的通常不会获得焦点的元素上添加大量 tabindex="-1" 属性,从而使可维护性成为一场噩梦。

如果您想读出文本,那么我建议您使用 aria-live 区域。

元素上的

aria-live 旨在大声说出该元素中包含的任何内容。每次更新元素的内容时都会发生这种情况。

您会注意到我添加了 aria-live="polite" 以确保他们的公告不会打断页面上的其他公告。

为了完整起见,还有 aria-live="assertive"(但您应该只将其用于警告和错误/状态更新之类的事情,因为它会切断当前所说的任何句子)和 aria-live="off"(其中对于禁用您的回话功能很有用,因为它实际上与元素上没有 aria-live 相同)

我建议您将要读出的相应元素中的文本复制到视觉上隐藏的 aria-live 区域。

如果您没有意识到视觉隐藏文本是屏幕 reader 屏幕上不可见的可访问文本。尽管有许多内置 sr-only class 的库,但我鼓励您使用 visually hidden class in the fiddle below due to better compatibility and future proofing as I explained in this answer

我还演示了如何使其在您的 Web 视图中可重用的概念,对于使用 jQuery 表示歉意,这里已经晚了,我想为您快速将 fiddle 放在一起!

在屏幕中尝试以下内容 reader,我认为代码是不言自明的,但如有任何问题,请提出。最后,根据您的“详细程度”设置,如果您将第三个按钮复制到 aria-live 区域,第三个按钮会显示相同的内容(具有语义,例如“标题”和“link”)。 .如果您没有听到这些,您的设置可能需要更改。

例子

$('button').on('click', function(e){
    console.log($(this).data('target'));
    
    var targetID = $(this).data('target');
    var text = $('#' + targetID).html();
    console.log(text);
    $('.speak-aloud').html(text);
    
});
.visually-hidden { 
    border: 0;
    padding: 0;
    margin: 0;
    position: absolute !important;
    height: 1px; 
    width: 1px;
    overflow: hidden;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
    clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
    clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
    white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="visually-hidden speak-aloud" aria-live="polite"></div>

<button data-target="p2">Read text in paragraph 2</button>
<button data-target="p4">Read text in paragraph 4</button>
<button data-target="longer-text">Read the section contents</button>

<p>This is some other text</p>
<p id="p2">This is the text to be read aloud in paragraph 2</p>
<p>Some more filler text</p>
<p id="p4">paragraph 4, will be read aloud when the second button is clicked.</p>



<section id="longer-text">
<h2>Section Header</h2>
<a href="https://google.com">Go to google link for an example of more complex text</a>
</section>

根据您的示例,关于语义的最后一句话。

对于可访问性 - 语义很重要。

锚点应该用于页面更改(或者在 SPA 中 URL 更改,如果整个页面是 AJAX 供电的话),按钮应该用于同一页面上的交互式内容。所以使用 <button> 而不是 <a href="#"> 因为这样可以让屏幕 reader 用户知道会发生什么(如果我单击 link 我希望页面发生变化,如果我按按钮我期待某种形式的互动内容)。

步骤 1:创建 Javascript 界面

public class JavascriptSpeakInterface {
    private Context context;
    private TextToSpeech tts;

    public JavascriptSpeakInterface(Context context, TextToSpeech tts){
       this.context = context;
       this.tts = tts;
    }

    @JavascriptInterface
    public void speak(String msg){
       tts.speak(msg, TextToSpeech.QUEUE_FLUSH, null, null);
    }
}

第 2 步:将界面与您的 webview 连接

webView.addJavascriptInterface(new JavascriptSpeakInterface(getContext(), new TextToSpeech(getContext(), this)), "android");

第三步:在javascript

中调用speak函数
android.speak(string);

注意:Javascript 必须在您的网络视图中启用。

解释:

第 1 步,创建 class 以在 Android 和 Web 代码之间建立接口。

第2步,将Android和网页代码连接在一起,其中“android”可以用来访问接口的方法。 (你可以改成任何你喜欢的)

第三步,使用标签“android”从javascript调用接口的speak方法。