React 原生应用程序,在 IOS 中测试。 期望的行为: 在 TextInput 中输入无效值并单击提交按钮。屏幕阅读器 shell 发出错误提示,焦点 shell 返回到 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',
},
});
最佳答案
按下按钮时,屏幕阅读器会在 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 的应用程序。 仍然需要找到更好的方法。 感谢您的任何评论和帖子。
关于ios - 如何正确设置 RN AccessibilityInfo setAccessibilityFocus,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57317960/