在测试了几个解决方案后,我对以下内容感到满意:
private async createIosToast(message: string, duration: number) {
const toast = await this.toastController.create({
message,
duration,
color: 'primary'
});
toast.setAttribute('role', 'alert');
toast.setAttribute('id', 'toast');
const toastElement = document.getElementById('toast') as HTMLElement;
const activeElement = this.correctActiveElement.getCorrectActiveElement();
// set focus on toast
toast.addEventListener('ionToastWillPresent', async () => {
this.focusService.focus(toastElement);
});
// reset focus
toast.onDidDismiss().then(async () => {
console.log(activeElement);
this.focusService.focus(activeElement);
}, error => {
console.log(error);
});
return toast;
}
以下方法在同时为 android 和 iOS 开发时很重要。由于 focus-method 设置了 tabindex,因此该方法避免了将其应用于错误的元素。否则,如果元素有一个 shadow-root,它会被聚焦两次(仅在 android 上)。
getCorrectActiveElement(): HTMLElement {
if (this.platform.is('android') && document.activeElement.shadowRoot != null) {
return document.activeElement.shadowRoot.childNodes[0] as HTMLElement;
} else {
return document.activeElement as HTMLElement;
}
}
这个方法只是设置焦点并应用一个tabindex:
public focus(element: HTMLElement): void {
setTimeout(() => {
element.setAttribute('tabindex', '0');
element.focus();
}, 0);
}
结论:使用这段代码,我最大程度地减少了我的问题。
在 android 上会有一些我无法消除的不必要的振动。它们是由焦点跳回 web 视图引起的。
在 iOS 上,toast 将被读取一次,然后被中断,然后完全读取。
在 Google Pixel 和 iPhone X 上测试。