import React, { useState, useEffect, useRef } from "react";
import { View, Text, Image, StyleSheet, Button, TouchableOpacity, TextInput, findNodeHandle, AccessibilityInfo, Switch, TouchableHighlight, Linking } from 'react-native';
import Modal from 'react-native-translucent-modal';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { ScrollView } from 'react-native-gesture-handler';
import Tts from 'react-native-tts';
import Slider from '@react-native-community/slider';
import Sound from 'react-native-sound';
import FocusOrder from './FocusOrder';
import AccessibilityFocus from './AccessibilityFocus';
import AccessibilityRN from './AccessibilityRN';
import { NativeEventEmitter, NativeModules } from 'react-native';
function ScreenReaderAPI({ navigation }) {
return (
Accessibility Focus { navigation.navigate('API1') }}>
1. Specify which views should receive the accessibility focus { navigation.navigate('API2') }}>
2. Specify the accessibility focus order { navigation.navigate('API3') }}>
3. Assign the accessibility focus to a view { navigation.navigate('API4') }}>
4. Specify actions associated to accessibility focus-related events (e.g., a view acquires or loses the focus) { navigation.navigate('API5') }}>
5. Determine whether a view has the accessibility focus or which view has the accessibility focusText to Announce { navigation.navigate('API6') }}>
6. Specify attributes that contribute to form the text-to-announce7. Programmatically define the text-to-announceNot available on this platform { navigation.navigate('API8') }}>
8. Use one view to describe another one { navigation.navigate('API9') }}>
9. Specify that a view should be announced when changed, even without user interaction10. Specify in which language the text-to-annouce should be readNot available on this platformExplicit TTS { navigation.navigate('API11') }}>
11. Read a text with the screen-reader TTS12. Be informed when the screen-reader finishes reading an explicitly provided text.Not available on this platform13. Customize screen-reader TTS speech features, like pitch, speed, etc...Not available on this platform { navigation.navigate('API14') }}>
14. Read a text with non-screen-reader TTS (also works when screen-reader is not active)15. Detect whether the non-screen-reader TTS is readingNot available on this platform16. Pause the non-screen-reader TTSNot available on this platform { navigation.navigate('API17') }}>
17. Customize non-screen-reader TTS speech features, like pitch, speed, etc...Accessibility Tree { navigation.navigate('API18') }}>
18. Aggregate multiple views into a single accessible element19. Decompose a view into multiple accessibility elementsNot available on this platform { navigation.navigate('API20') }}>
20. Get the parent accessible elementMiscellaneous { navigation.navigate('API21') }}>
21. Detect whether screen-reader is active { navigation.navigate('API22') }}>
22. Support navigation by specifying which views are headers or panes { navigation.navigate('API23') }}>
23. Define how to respond to user actions that are only available when the screen reader is active { navigation.navigate('API24') }}>
24. Perform actions on user's behalf25. Associate arbitrary accessibility-related information to a viewNot available on this platform
)
}
function API1() {
const [accessible, setAccessible] = useState(true)
function setForkAccessibility() {
if (accessible) {
setAccessible(false)
} else {
setAccessible(true)
}
}
return (
<>
Press the switch to change{"\n"}the accessibility of the image
>
)
}
function API2() {
const [topDown, setTopDown] = useState(true)
const [text, setText] = useState('CHANGE FOCUS ORDER TO LEFT-RIGHT')
const ref1 = React.useRef()
const ref2 = React.useRef()
const ref3 = React.useRef()
const ref4 = React.useRef()
function changeOrder() {
if (topDown) {
setTopDown(false)
setText('CHANGE FOCUS ORDER TO TOP-DOWN')
FocusOrder.setOrder([
findNodeHandle(ref1.current),
findNodeHandle(ref3.current),
findNodeHandle(ref2.current),
findNodeHandle(ref4.current)
])
} else {
setTopDown(true)
setText('CHANGE FOCUS ORDER TO LEFT-RIGHT')
FocusOrder.setOrder([
findNodeHandle(ref1.current),
findNodeHandle(ref2.current),
findNodeHandle(ref3.current),
findNodeHandle(ref4.current)
])
}
}
return (
<>
1324i: Views 1, 2, 3 and 4 are displayed in such a way that reading them from top to bottom results in 1, 2, 3, 4, while reading them from left to right is: 1, 3, 2, 4.
>
)
}
function API3() {
const ref = React.useRef()
const changeFocus = () => {
const tag = findNodeHandle(ref.current)
AccessibilityInfo.setAccessibilityFocus(tag)
}
return (
Generic view
)
}
function API4() {
const [hasFocus, setFocus] = useState(false)
function playBeep(beep) {
var beepFile = ''
switch (beep) {
case 'on':
beepFile = 'sound_beep1.mp3'
break
case 'off':
beepFile = 'sound_beep2.mp3'
break
default:
console.error('ERROR: "beep" variable can only assume the values "on" and "off"')
break
}
console.log(beepFile)
const sound = new Sound(beepFile, null, (error) => {
if (error) {
console.log('cannot play the sound file', error)
}
sound.play()
})
}
return (
{hasFocus ? 'Bell image has focus' : 'Bell image does not have focus'} { playBeep('on'), setFocus(true) }}
onFocusEnd={() => { playBeep('off'), setFocus(false) }}
>
i: This image makes a sound when it receives focus and makes a different one when it loses it. If you don't hear the sound, check the system volume.
)
}
function API5() {
const [label, setLabel] = useState("label")
const [bellHasFocus, setBellFocus] = useState(false)
const [hasId, setHasId] = useState("normal")
let eventEmitterListener = useRef(null);
useEffect(() => {
AccessibilityRN.viewLabelFocused()
const eventEmitter = new NativeEventEmitter(AccessibilityRN);
eventEmitterListener.current = eventEmitter.addListener(
'viewLabel',
event => {
const label = event.viewLabel
if (label == "") {
setLabel('this view has no id')
setHasId("italic")
} else {
setLabel(label)
setHasId("normal")
}
if (label == "bell") {
setBellFocus(true)
} else {
setBellFocus(false)
}
},
);
return () => {
eventEmitterListener.current.remove();
};
}, []);
return (
<>
Name of view with focus: {label}Does bell image have focus?{bellHasFocus ? 'YES' : 'NO'}
>
)
}
function API6() {
const [value, onChangeText] = useState('')
return (
<>
Image Alternative Text onChangeText(text)}
value={value}
/>
>
)
}
function API8() {
const ref1 = React.useRef()
const ref2 = React.useRef()
useEffect(() => {
AccessibilityRN.setLabelFor(findNodeHandle(ref1.current), findNodeHandle(ref2.current))
})
return (
Textfield Descriptioni: The textfield is described by the text above it.
)
}
function API9() {
const [counter, setCounter] = useState(0)
return (
{counter}
)
}
function API11() {
const text = "The text to speech will be read by the screen reader."
return (
{text}
)
}
function API14() {
const textTTS = 'Text1: This is text number one'
return (
{textTTS}i: In case you don't hear the text read aloud, please check the system volume
)
}
function API17() {
const textTTS = 'This is an example text.'
const [rate, setrate] = useState(1)
Tts.setDefaultRate(rate, true);
return (
Tts.speak(textTTS, { rate: rate })}>
{textTTS}Change The Reading SpeedSLOW setrate(value)}
/>
FASTi: To use the slider, press the volume up and the volume down buttons.
)
}
function API18() {
return (
View number 1View number 2This three different texts (views) have been grouped together, and will be handled by talkback as a single element.
)
}
function API20() {
const ref = React.useRef()
return (
)
}
function API21() {
const [screenReaderEnabled, setScreenReaderEnabled] = useState(false)
useEffect(() => {
AccessibilityInfo.addEventListener(
"screenReaderChanged",
handleScreenReaderToggled
)
AccessibilityInfo.isScreenReaderEnabled().then(screenReaderEnabled => {
setScreenReaderEnabled(screenReaderEnabled)
})
return () => {
AccessibilityInfo.removeEventListener(
"screenReaderChanged",
handleScreenReaderToggled
)
}
}, [])
const handleScreenReaderToggled = screenReaderEnabled => {
setScreenReaderEnabled(screenReaderEnabled)
}
return (
Is screen reader active?{screenReaderEnabled ? 'YES' : 'NO'}
)
}
function API22() {
return (
This text is treated as a headerThis text is treated as a buttonThis text is treated as an imageThis is a normal text
)
}
function API23() {
const [value, setValue] = useState('')
const [backgroundColor, setBackgroundColor] = useState('')
function action(event) {
console.log(event.nativeEvent.actionName)
switch (event.nativeEvent.actionName) {
case 'activate':
setBackgroundColor("#bb0000")
setValue('activate')
break
case 'increment':
setBackgroundColor("#bb0000")
setValue('increment')
break
case 'decrement':
setBackgroundColor("#bb0000")
setValue('decrement')
break
case 'longpress':
setBackgroundColor("#bb0000")
setValue('longpress')
break
}
}
return (
action(event)}
style={{ flex: 1, justifyContent: 'flex-start', padding: 20, backgroundColor: backgroundColor }}
>
Change background color with one of the following actions with the screen reader:'activate' - Double tap with the screen reader.'increment' - Press the volume up button.'decrement' - Press the volume down button.Action performed: {value}
)
}
function API24() {
const [visibility, setVisibility] = useState('none')
const ref = React.useRef()
function changeVisibility() {
if (visibility == 'none') {
setVisibility('flex')
} else {
setVisibility('none')
}
}
return (
<>
>
)
}
const Stack = createStackNavigator()
function App() {
const [modalVisible, setModalVisible] = useState(false)
return (
(
setModalVisible(true)}>
{}}
>
Developed at EveryWare lab (Università degli Studi di Milano) by Antonio Pugliese
),
}}
/>
)
}
export default App
const styles = StyleSheet.create({
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22,
backgroundColor: 'rgba(0, 0, 0, 0.5)'
},
modalView: {
margin: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
openButton: {
backgroundColor: "#F194FF",
borderRadius: 20,
padding: 10,
elevation: 2,
marginTop: 10,
},
textStyle: {
color: "white",
fontWeight: "bold",
textAlign: "center"
},
modalText: {
marginTop: 10,
marginBottom: 15,
textAlign: "center"
},
logo: {
alignSelf: 'center',
width: 160,
height: 120,
},
img_container: {
flex: 1,
flexDirection: 'row',
alignContent: 'flex-start',
alignItems:'center',
},
about_img: {
width:'50%',
height: '50%',
marginRight: 20
},
line: {
marginHorizontal: 10,
marginVertical: 1,
zIndex: 200,
borderBottomWidth: StyleSheet.hairlineWidth,
},
header: {
fontSize: 20,
padding: 10,
fontWeight: 'bold'
},
api: {
margin: 5,
paddingHorizontal: 5,
},
not_aviable: {
margin: 5,
paddingHorizontal: 5,
textDecorationLine: 'line-through',
color: 'grey',
},
platform: {
alignSelf: 'flex-end',
color: 'grey',
margin: 5,
paddingHorizontal: 5,
},
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
switch: {
flexDirection: 'row',
justifyContent: 'space-around',
margin: 10,
},
fork: {
width: '75%',
height: '75%',
resizeMode: 'contain',
alignSelf: 'center',
marginTop: 20,
marginBottom: 20,
},
bell: {
width: 150,
height: 150,
alignSelf: 'center',
margin: 10,
},
counter: {
fontSize: 50,
alignSelf: 'center',
marginBottom: 100
},
focusOrder: {
flexDirection: 'row',
justifyContent: 'space-around',
marginTop: 30,
marginBottom: 50,
paddingHorizontal: 20,
},
orderButton: {
backgroundColor: '#FFFFFF',
width: 40,
height: 40,
borderColor: 'black',
borderWidth: 1,
alignItems: 'center',
justifyContent: 'center',
borderRadius: 5
},
position2: {
marginTop: 60
},
position3: {
marginTop: 120
},
position4: {
marginTop: 180
},
footer: {
position: 'absolute',
left: 20,
right: 20,
bottom: 20
},
textInput: {
height: 40,
margin: 10,
borderWidth: 1.0
},
button: {
width: '75%',
alignSelf: 'center',
margin: 10
},
img: {
flex: 1,
width: 100,
height: 100,
marginLeft: 10,
marginRight: 20,
},
multipleText: {
marginBottom: 10,
flexDirection: 'row',
},
increment: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
}
})