如何正确设置 RN AccessibilityInfo setAccessibilityFocus
Posted
技术标签:
【中文标题】如何正确设置 RN AccessibilityInfo setAccessibilityFocus【英文标题】:How to set properly RN AccessibilityInfo setAccessibilityFocus 【发布时间】:2019-08-01 22:56:20 【问题描述】:React Native App,ios 测试。 期望的行为: 在 TextInput 中输入无效值并单击提交按钮。屏幕阅读器外壳发音错误,焦点外壳返回到 textInput。设置焦点外壳不打开键盘。
实施中的问题: 焦点返回到 textInput 似乎是在可访问性标签更新为错误消息之前。旧无障碍标签的屏幕阅读器发音。 如果在 Voice Over 的发音后触摸 textInput,则带有错误消息的更新的辅助功能标签是发音。
该代码也可在世博小吃中找到, snack
import * as React from 'react';
import AccessibilityInfo, TextInput, Button, Text, View, StyleSheet from 'react-native';
import Constants from 'expo-constants';
import AssetExample from './components/AssetExample';
import Card from 'react-native-paper';
const errorBtn = "Click to simulate invalid text input";
const clearBtn = "Click to clear the error";
const errorLabel = "Wrong Number has being typed, try again";
const clearLabel = "Phone Number";
const description =
"Enable Voice Over, If Error hapens on textInput, screen reader shell pronounce the error message and set focus to the textInput where the error happend"
const placeholder = "Type 10 digit phone number"
export default class App extends React.Component
state =
error: false,
text: "",
buttonTitle: errorBtn
errorMsg= () => this.setState(error: true)
clearMsg= () => this.setState(error: false)
onPress = () =>
const TextInputNativeTag =
this
.textOInputRef
._inputRef
._nativeTag
if (this.state.buttonTitle == errorBtn)
this.errorMsg();
if (this.state.buttonTitle == clearBtn)
this.clearMsg();
if (this.textOInputRef)
AccessibilityInfo
.setAccessibilityFocus(TextInputNativeTag);
this.state.buttonTitle == errorBtn &&
this.setState(buttonTitle:clearBtn);
this.state.buttonTitle == clearBtn &&
this.setState(buttonTitle:errorBtn) ;
render()
return (
<View>
<View >
<Text accessibilityRole='header'
style=styles.header
>
Accessabiity Focuse Tester
</Text>
<Text style=styles.paragraph>
description
</Text>
</View>
<View style=styles.body>
<View style=styles.sectionContainer >
<Text
accessibilityRole='header'
style=styles.sectionTitle
>
Accessability Label
</Text>
<Text style=
styles.sectionDescription
>
this.state.error
? errorLabel
: clearLabel
</Text>
</View>
<View style=
styles.sectionContainer
>
<TextInput
ref=r =>
this.textOInputRef = r
style=
height: 40,
borderColor: 'gray',
borderWidth: 1
accessibilityLabel=
this.state.error
? errorLabel
: clearLabel
underlineColorandroid=
"transparent"
keyboardType="numeric"
returnKeyType="done"
onChangeText=
text =>
this.setState(text)
placeholder=placeholder
placeholderTextColor=
"rgb(143,143,143)"
value=this.state.text
/>
</View>
<View style=styles.sectionContainer>
<Button
onPress=this.onPress
title=this.state.buttonTitle
color="#841584"
accessibilityLabel=this
.state
.buttonTitle
/>
</View>
</View>
</View>
);
const styles = StyleSheet.create(
header:
margin: 24,
fontSize: 18,
textAlign: 'center',
fontWeight: 'bold',
,
paragraph:
margin: 24,
fontSize: 18,
textAlign: 'center',
,
body:
backgroundColor: '#fff',
,
sectionContainer:
marginTop: 32,
paddingHorizontal: 24,
,
sectionTitle:
fontSize: 24,
fontWeight: '600',
color: '#000',
,
sectionDescription:
marginTop: 8,
fontSize: 18,
fontWeight: '400',
,
);
【问题讨论】:
【参考方案1】:当按下按钮时,屏幕阅读器会在 onPress 方法的操作过程中读取按钮标签。因此,需要提前安排渲染时间。 此外,需要在标签更新为新值后将 setfocus 调度到 textInput。 以下是代码和snack
import * as React from 'react';
import AccessibilityInfo, TextInput, TouchableWithoutFeedback, Text, View, StyleSheet from 'react-native';
const errorBtn = "Click to simulate invalid text input";
const clearBtn = "Click to clear the error";
const errorLabel = "Wrong Number has being typed, try again";
const clearLabel = "Phone Number";
const description =
"Enable Voice Over, If Error hapens on textInput, screen reader shell pronounce the error message and set focus to the textInput where the error happend"
const placeholder = "Type 10 digit phone number"
export default class App extends React.Component
state =
error: false,
text: "",
buttonTitle: errorBtn
label=clearLabel;
accessabilityMsg=null;
textInputRef=null;
onPress = () =>
const textInput = this.textInputRef && this.textInputRef._inputRef._nativeTag;
if (this.state.buttonTitle == errorBtn)
console.log('onPress set label & state to error');
setTimeout(()=>
this.setState(error: true,buttonTitle:clearBtn);
setTimeout(()=>textInput && AccessibilityInfo.setAccessibilityFocus(textInput),500);
,6000);
this.label=errorLabel;
else
console.log('onPress set label & state to normal')
this.setState(error: false,buttonTitle:errorBtn);
this.label=clearLabel;
render()
return (
<View >
<View >
<Text accessibilityRole='header'
style=styles.header
>
Accessabiity Focus Tester
</Text>
<Text style=styles.paragraph>
description
</Text>
</View>
<View style=styles.body>
<View style=styles.sectionContainer >
<Text
accessibilityRole='header'
style=styles.sectionTitle
>
Accessability Label
</Text>
<Text style=
styles.sectionDescription
>
this.label
</Text>
</View>
<View style=
styles.sectionContainer
>
<TextInput
ref=r =>
this.textInputRef = r
style=
height: 40,
borderColor: 'gray',
borderWidth: 1
accessibilityLabel=this.label
underlineColorAndroid=
"transparent"
keyboardType="numeric"
returnKeyType="done"
onChangeText=
text =>
this.setState(text)
placeholder=placeholder
placeholderTextColor=
"rgb(143,143,143)"
value=this.state.text
/>
</View>
<View style=styles.button>
<TouchableWithoutFeedback
accessible
accessibilityRole='button'
accessibilityLabel=this.state.buttonTitle
onPress=this.onPress
>
<Text> this.state.buttonTitle </Text>
</TouchableWithoutFeedback>
</View>
</View>
</View>
);
const styles = StyleSheet.create(
header:
margin: 24,
fontSize: 18,
textAlign: 'center',
fontWeight: 'bold',
,
paragraph:
margin: 24,
fontSize: 18,
textAlign: 'center',
,
body:
backgroundColor: '#fff',
,
sectionContainer:
marginTop: 32,
paddingHorizontal: 24,
,
sectionTitle:
fontSize: 24,
fontWeight: '600',
color: '#000',
,
sectionDescription:
marginTop: 8,
fontSize: 18,
fontWeight: '400',
,
button:
margin: 24,
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
borderColor: '#000',
borderWidth: 1
,
);
最后,还是没有完成任务。 我们不能设计基于 setTimout 的应用程序。 仍然需要找到更好的方法。 感谢您的任何评论和帖子。
【讨论】:
您找到更好的解决方案了吗?我也最终使用了 setTimeout,但如果组件在事件触发之前卸载,则会导致一系列问题。以上是关于如何正确设置 RN AccessibilityInfo setAccessibilityFocus的主要内容,如果未能解决你的问题,请参考以下文章