Ionic/Angular: 无法使用屏幕关注 HTMLElement Reader
Ionic/Angular: Can't Focus on HTMLElement with Screen Reader
我试图在 Ionic 5 中强制屏幕 reader 聚焦并宣布一个元素。
我的模板元素:
<ion-title tabindex="-1" #title id="title" role="heading" aria-level="1" class="title">My Title</ion-title>
我试图通过文档访问元素并作为 Viewchild:
@ViewChild('title', { read: ElementRef }) title: ElementRef;
const title: any = document.getElementById('title');
我尝试在这个测试延迟后集中注意力:
ionViewWillEnter(): void {
setTimeout(() => {
const title: any = document.getElementById('title');
if (title) {
title.focus();
}
}, 3000);
setTimeout(() => {
this.title.nativeElement.focus();
}, 5000);
}
然而,这些都不是重点。屏幕 reader 没有在 Android 和 iOS 中宣布标题。
更新
澄清一下,我需要屏幕 reader 位置才能移动到指定元素。如上所述聚焦于元素不会移动屏幕 reader 位置。
如有任何帮助,我们将不胜感激,这是我的 Ionic 信息:
Ionic CLI : 5.4.16
Ionic Framework : @ionic/angular 5.5.3
@angular-devkit/build-angular : 0.901.15
@angular-devkit/schematics : 9.1.15
@angular/cli : 9.1.15
@ionic/angular-toolkit : 2.3.3
Capacitor:
Capacitor CLI : 2.4.2
@capacitor/core : 2.4.0
我创建了 stackblitz。一切都按预期工作。为了让它更显眼,我添加了样式
:focus {
outline: 3px solid orange;
}
此外,我建议您添加 aria-label
,因为 ion-title
是内部带有 div 的元素,我不确定是否所有读者都在处理
<ion-title tabindex="-1" #title id="title" role="heading" aria-level="1" class="title" role="heading"
aria-label="What you want to read">My Title
</ion-title>
最后,由于您在 ionic 应用程序中使用 angular,您可以查看 material 库,其中包含 live announcer
@Component({...})
export class MyComponent {
constructor(liveAnnouncer: LiveAnnouncer) {
liveAnnouncer.announce("Hey Google");
}
}
我为所有要扩展的 Ionic 页面创建了一个 BasePage。它在点击和焦点事件上捕获活动元素,并在页面再次进入时聚焦该元素。
它还会自动尝试查找 ion-title 并在没有以前活动的元素要聚焦的情况下聚焦于此。
这应该能满足基本需求。您可以调整向焦点方法添加超时
import { Component, ElementRef, HostListener } from '@angular/core';
import { ViewDidEnter } from '@ionic/angular';
import { isNullOrUndefined } from 'util';
@Component({
template: ''
})
export class BasePage implements ViewDidEnter {
private _previouslyActiveElement: HTMLElement;
constructor(protected elementRef: ElementRef) {}
ionViewDidEnter() {
if (!isNullOrUndefined(this._previouslyActiveElement)) {
this.focusOnElement(this._previouslyActiveElement);
} else {
if (
!isNullOrUndefined(this.elementRef.nativeElement) &&
this.elementRef.nativeElement.querySelectorAll('[autofocus]').length === 0) {
const initialFocusElement: HTMLElement = <HTMLElement>this.elementRef.nativeElement.getElementsByTagName('ion-title')[0];
if (!isNullOrUndefined(initialFocusElement)) {
this.focusOnElement(initialFocusElement);
}
}
}
}
@HostListener('focusin', ['$event.target'])
@HostListener('click', ['$event.target'])
capturePreviouslyActiveElement(element: HTMLElement) {
this._previouslyActiveElement = element;
}
focusOnElement(element: HTMLElement): void {
if (isNullOrUndefined(element)) {
return;
}
try {
// Make sure it's focusable
if (isNullOrUndefined(element.getAttribute('tabindex'))) {
element.setAttribute('tabindex', '-1');
}
element.focus();
} catch (err) {
console.log('error handling aria focus ' + err);
}
}
}
我试图在 Ionic 5 中强制屏幕 reader 聚焦并宣布一个元素。
我的模板元素:
<ion-title tabindex="-1" #title id="title" role="heading" aria-level="1" class="title">My Title</ion-title>
我试图通过文档访问元素并作为 Viewchild:
@ViewChild('title', { read: ElementRef }) title: ElementRef;
const title: any = document.getElementById('title');
我尝试在这个测试延迟后集中注意力:
ionViewWillEnter(): void {
setTimeout(() => {
const title: any = document.getElementById('title');
if (title) {
title.focus();
}
}, 3000);
setTimeout(() => {
this.title.nativeElement.focus();
}, 5000);
}
然而,这些都不是重点。屏幕 reader 没有在 Android 和 iOS 中宣布标题。
更新
澄清一下,我需要屏幕 reader 位置才能移动到指定元素。如上所述聚焦于元素不会移动屏幕 reader 位置。
如有任何帮助,我们将不胜感激,这是我的 Ionic 信息:
Ionic CLI : 5.4.16
Ionic Framework : @ionic/angular 5.5.3
@angular-devkit/build-angular : 0.901.15
@angular-devkit/schematics : 9.1.15
@angular/cli : 9.1.15
@ionic/angular-toolkit : 2.3.3
Capacitor:
Capacitor CLI : 2.4.2
@capacitor/core : 2.4.0
我创建了 stackblitz。一切都按预期工作。为了让它更显眼,我添加了样式
:focus {
outline: 3px solid orange;
}
此外,我建议您添加 aria-label
,因为 ion-title
是内部带有 div 的元素,我不确定是否所有读者都在处理
<ion-title tabindex="-1" #title id="title" role="heading" aria-level="1" class="title" role="heading"
aria-label="What you want to read">My Title
</ion-title>
最后,由于您在 ionic 应用程序中使用 angular,您可以查看 material 库,其中包含 live announcer
@Component({...})
export class MyComponent {
constructor(liveAnnouncer: LiveAnnouncer) {
liveAnnouncer.announce("Hey Google");
}
}
我为所有要扩展的 Ionic 页面创建了一个 BasePage。它在点击和焦点事件上捕获活动元素,并在页面再次进入时聚焦该元素。
它还会自动尝试查找 ion-title 并在没有以前活动的元素要聚焦的情况下聚焦于此。
这应该能满足基本需求。您可以调整向焦点方法添加超时
import { Component, ElementRef, HostListener } from '@angular/core';
import { ViewDidEnter } from '@ionic/angular';
import { isNullOrUndefined } from 'util';
@Component({
template: ''
})
export class BasePage implements ViewDidEnter {
private _previouslyActiveElement: HTMLElement;
constructor(protected elementRef: ElementRef) {}
ionViewDidEnter() {
if (!isNullOrUndefined(this._previouslyActiveElement)) {
this.focusOnElement(this._previouslyActiveElement);
} else {
if (
!isNullOrUndefined(this.elementRef.nativeElement) &&
this.elementRef.nativeElement.querySelectorAll('[autofocus]').length === 0) {
const initialFocusElement: HTMLElement = <HTMLElement>this.elementRef.nativeElement.getElementsByTagName('ion-title')[0];
if (!isNullOrUndefined(initialFocusElement)) {
this.focusOnElement(initialFocusElement);
}
}
}
}
@HostListener('focusin', ['$event.target'])
@HostListener('click', ['$event.target'])
capturePreviouslyActiveElement(element: HTMLElement) {
this._previouslyActiveElement = element;
}
focusOnElement(element: HTMLElement): void {
if (isNullOrUndefined(element)) {
return;
}
try {
// Make sure it's focusable
if (isNullOrUndefined(element.getAttribute('tabindex'))) {
element.setAttribute('tabindex', '-1');
}
element.focus();
} catch (err) {
console.log('error handling aria focus ' + err);
}
}
}