React Native Accessibility TalkBack not working on inner screens in Android 6How to know if Android TalkBack is active?Android: using marquee with TalkBack (Accessibility)Android - Set TalkBack accessibility focus to a specific viewHide keyboard in react-nativeHow to do logging in React Native?What is the difference between using constructor vs getInitialState in React / React Native?React Native android build failed. SDK location not foundWhat is the difference between React Native and React?React Native FlatList horizontal paging TouchableOpacity scrollToIndex infinite loopNot able to navigate to other page in react native
Mage Armor with Defense fighting style (for Adventurers League bladeslinger)
What are these boxed doors outside store fronts in New York?
How is the claim "I am in New York only if I am in America" the same as "If I am in New York, then I am in America?
Arthur Somervell: 1000 Exercises - Meaning of this notation
can i play a electric guitar through a bass amp?
Why are 150k or 200k jobs considered good when there are 300k+ births a month?
Finding angle with pure Geometry.
Font hinting is lost in Chrome-like browsers (for some languages )
Is it unprofessional to ask if a job posting on GlassDoor is real?
What typically incentivizes a professor to change jobs to a lower ranking university?
Mathematical cryptic clues
Why Is Death Allowed In the Matrix?
How much RAM could one put in a typical 80386 setup?
A newer friend of my brother's gave him a load of baseball cards that are supposedly extremely valuable. Is this a scam?
Is this a crack on the carbon frame?
What is the offset in a seaplane's hull?
Accidentally leaked the solution to an assignment, what to do now? (I'm the prof)
What do you call a Matrix-like slowdown and camera movement effect?
Modeling an IPv4 Address
How to write a macro that is braces sensitive?
What do the dots in this tr command do: tr .............A-Z A-ZA-Z <<< "JVPQBOV" (with 13 dots)
Today is the Center
How did the USSR manage to innovate in an environment characterized by government censorship and high bureaucracy?
Why, historically, did Gödel think CH was false?
React Native Accessibility TalkBack not working on inner screens in Android 6
How to know if Android TalkBack is active?Android: using marquee with TalkBack (Accessibility)Android - Set TalkBack accessibility focus to a specific viewHide keyboard in react-nativeHow to do logging in React Native?What is the difference between using constructor vs getInitialState in React / React Native?React Native android build failed. SDK location not foundWhat is the difference between React Native and React?React Native FlatList horizontal paging TouchableOpacity scrollToIndex infinite loopNot able to navigate to other page in react native
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I am using ReactNative
with Expo
, and I have noticed that on Android 6 the TalkBack Accessibility feature is not properly working. On first screen It is working, but on next screens it is not working (which also load FlatList dynamically). I do checked on latest Android 7, 8 version and there the TalkBack feature is working pretty Ok on all screens.
Here is my sample code:
Package.json
"main": "node_modules/expo/AppEntry.js",
"scripts":
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"eject": "expo eject",
"test": "node ./node_modules/jest/bin/jest.js --watchAll"
,
"jest":
"preset": "jest-expo"
,
"dependencies":
"@expo/samples": "2.1.1",
"expo": "^32.0.0",
"react": "16.5.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
"react-native-cheerio": "^1.0.0-rc.4",
"react-native-xml2js": "^1.0.3",
"react-navigation": "^3.0.9"
,
"devDependencies":
"babel-preset-expo": "^5.0.0",
"jest-expo": "^32.0.0"
,
"private": true
HomeScreen
import React from 'react';
import
Image,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View, FlatList, ToastAndroid
from 'react-native';
import NEWS_SOURCES from '../libraries/loader';
export const Toast = (props) =>
if (props.visible)
ToastAndroid.showWithGravityAndOffset(props.message, ToastAndroid.LONG, ToastAndroid.BOTTOM, 25, 50);
return null;
return null;
;
export default class HomeScreen extends React.Component
static navigationOptions =
header: null,
;
constructor(props)
super(props);
this._renderItem = this._renderItem.bind(this);
this._handleItemClick = this._handleItemClick.bind(this);
render()
console.log('nnavigation props: ', this.props.navigation);
return (
<ScrollView style=styles.container accessibilityLiveRegion="polite">
<View style=flex:1, flexDirection: 'column', marginTop:50>
<Text style=styles.app_name accessibilityLabel="Select 1 of "+NEWS_SOURCES.length+" News Channels, from the list - given on screen">News Assistant</Text>
</View>
<View style=flex:5, flexDirection: 'column'>
<FlatList
style=padding:8
data=NEWS_SOURCES
renderItem=this._renderItem
keyExtractor=this._keyExtractor
/>
</View>
<Toast visible=true message='Welcome, to news assistant. We got '+NEWS_SOURCES.length+' news channels loaded for you. Tap to know their names. And double tap to read headlines, on next screen.' />
</ScrollView>
);
_handleItemClick(source_index)
var selectedSource = NEWS_SOURCES[source_index];
console.log('Channel Selected: '+source_index, selectedSource);
this.props.navigation.navigate('HeadlinesStack', channel_data: NEWS_SOURCES[source_index]);
_renderItem(obj)
console.log(obj);
return (
<View key=obj.index style=styles.row >
<TouchableOpacity style= onPress=()=>this._handleItemClick(obj.index) accessible=true accessibilityRole="button" accessibilityLabel=obj.item.id+'. '+obj.item.title>
<Text style=[styles.lightTxt, styles.rowTxt]>obj.item.title</Text>
</TouchableOpacity>
</View>
);
_keyExtractor = (item, index) => 'key'+item.id;
const styles = StyleSheet.create(
container:
flex: 1,
backgroundColor: '#000',
,
app_name:
color: '#fff', textAlign: 'center', fontSize:18
,
lightTxt:
color: '#fff'
,
rowTxt:
padding:25
,
row:
borderBottomWidth: 1, borderBottomColor: '#333', borderStyle: 'solid'
,
);
HeadlinesScreen.js
import React from 'react';
import ScrollView, View, Text, FlatList, TouchableOpacity, Modal, Alert, StyleSheet, ActivityIndicator, Button, ToastAndroid, TouchableHighlight, UIManager, findNodeHandle from 'react-native';
import NEWS_SOURCES, fetch_newsByCountry, fetch_newsBySourceID, fetch_newsFullStory from '../libraries/loader';
export const Toast=(props)=>
if (props.visible)
ToastAndroid.showWithGravityAndOffset(props.message, ToastAndroid.LONG, ToastAndroid.BOTTOM, 25, 50);
return null;
return null;
;
export default class HeadlinesScreen extends React.Component
static navigationOptions=
title: 'Headlines',
;
constructor(props)
super(props);
this.state = channelSource: this.props.navigation.getParam('channel_data', 'none'), // default value 'none'
dataList: [], modalVisible: false, selectedItemId: null, selectedItem_desc: null ;
this._renderItem = this._renderItem.bind(this);
this._handleItemClick = this._handleItemClick.bind(this);
this._displayItemDetails = this._displayItemDetails.bind(this);
this._setModalVisible = this._setModalVisible.bind(this);
this._onFetchComplete = this._onFetchComplete.bind(this);
this._forceTriggerSpeak = this._forceTriggerSpeak.bind(this);
render()
console.log('nthis.props.navigation:', this.props.navigation);
console.log('nnSelected Channel state.params Data: ', this.props.navigation.state.params);
console.log('nnSelected Channel param Data: ', this.props.navigation.getParam('channel_data'));
console.log('nnSelected Channel state Data: ', this.state.channelSource);
//return (<View></View>) ;
//console.log('nnRender: n',this.state);
console.log('nnRender - modal state: n',this.state.modalVisible);
return (
<ScrollView style=styles.container accessibilityLiveRegion="polite" importantForAccessibility=this.state.modalVisible==false ? 'yes' : 'no-hide-descendants'>
(this.state.dataList.length ==0? <ActivityIndicator size="large" Accessible=true accessibilityLabel="Loading news, please wait." /> :
this.state.dataList.map(this._renderItem)
)
<Toast visible=this.state.dataList.length ==0 && this.state.modalVisible==false ? true: false message="Loading news, please wait." />
<Toast visible=this.state.dataList.length > 0 && this.state.modalVisible==false ? true: false message=this.state.dataList.length+' news loaded. Tap to read headline. And double tap to read details.' />
<Toast visible=this.state.dataList.length > 0 && this.state.modalVisible==true ? true: false message='Loading full story, please wait.' />
<Toast visible=this.state.dataList.length > 0 && this.state.modalVisible==true && this.state.selectedItem_desc != null? true: false message='Story loaded, please tap on screen to read. And scroll bottom of screen and hit Close button, to close this story.' />
(this.state.modalVisible ? this._displayItemDetails() : null)
</ScrollView>
);
async componentDidMount()
console.log("nnn", this.props.navigation.getParam('channel_data'));
var newsList = await fetch_newsBySourceID(this.state.channelSource, this._onFetchComplete); // external api call
_onFetchComplete(payload, payloadType) story
console.log('nn onFetchComplete list: n', payload);
if(Array.isArray(payload) && payloadType == 'list')
console.log('nn onFetchComplete list: n'+payload.length);
this.setState(previousState =>
return dataList: payload;
);
else
this.setState(previousState =>
return selectedItem_desc: payload;
);
_renderItem(obj, index)
return (
<View key=index style= borderBottomWidth: 1, borderBottomColor: '#ccc', borderStyle: 'solid', padding:10 >
<TouchableOpacity style=flexDirection: 'row', onPress=()=>this._handleItemClick(index) accessible=true accessibilityLiveRegion="polite" accessibilityLabel=(index-1+2)+". "+obj.title accessibilityHint="Double tap to read full news on next screen.">
<Text style=[styles.lightTxt, styles.rowTxt] >obj.title</Text>
</TouchableOpacity>
</View>
);
async _handleItemClick(itemIndex)
console.log('showModal for item: '+itemIndex);
fetch_newsFullStory(this.state.dataList[itemIndex].story_url, this.state.channelSource, this._onFetchComplete);
_forceTriggerSpeak()
UIManager.sendAccessibilityEvent( findNodeHandle(this), UIManager.AccessibilityEventTypes.typeViewClicked);
// usually item details in a Popup Modal View
_displayItemDetails() // this.state.dataList[this.state.selectedItemId].content
console.log('nnDisplay Modal:n', this.state.modalVisible);
// usually used to hide Popup Modal
const styles = StyleSheet.create(
container:
flex: 1,
paddingTop: 15,
backgroundColor: '#000',
,
lightTxt:
color: '#fff'
,
rowTxt:
padding:25
,
);
react-native accessibility expo android-6.0-marshmallow talkback
add a comment |
I am using ReactNative
with Expo
, and I have noticed that on Android 6 the TalkBack Accessibility feature is not properly working. On first screen It is working, but on next screens it is not working (which also load FlatList dynamically). I do checked on latest Android 7, 8 version and there the TalkBack feature is working pretty Ok on all screens.
Here is my sample code:
Package.json
"main": "node_modules/expo/AppEntry.js",
"scripts":
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"eject": "expo eject",
"test": "node ./node_modules/jest/bin/jest.js --watchAll"
,
"jest":
"preset": "jest-expo"
,
"dependencies":
"@expo/samples": "2.1.1",
"expo": "^32.0.0",
"react": "16.5.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
"react-native-cheerio": "^1.0.0-rc.4",
"react-native-xml2js": "^1.0.3",
"react-navigation": "^3.0.9"
,
"devDependencies":
"babel-preset-expo": "^5.0.0",
"jest-expo": "^32.0.0"
,
"private": true
HomeScreen
import React from 'react';
import
Image,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View, FlatList, ToastAndroid
from 'react-native';
import NEWS_SOURCES from '../libraries/loader';
export const Toast = (props) =>
if (props.visible)
ToastAndroid.showWithGravityAndOffset(props.message, ToastAndroid.LONG, ToastAndroid.BOTTOM, 25, 50);
return null;
return null;
;
export default class HomeScreen extends React.Component
static navigationOptions =
header: null,
;
constructor(props)
super(props);
this._renderItem = this._renderItem.bind(this);
this._handleItemClick = this._handleItemClick.bind(this);
render()
console.log('nnavigation props: ', this.props.navigation);
return (
<ScrollView style=styles.container accessibilityLiveRegion="polite">
<View style=flex:1, flexDirection: 'column', marginTop:50>
<Text style=styles.app_name accessibilityLabel="Select 1 of "+NEWS_SOURCES.length+" News Channels, from the list - given on screen">News Assistant</Text>
</View>
<View style=flex:5, flexDirection: 'column'>
<FlatList
style=padding:8
data=NEWS_SOURCES
renderItem=this._renderItem
keyExtractor=this._keyExtractor
/>
</View>
<Toast visible=true message='Welcome, to news assistant. We got '+NEWS_SOURCES.length+' news channels loaded for you. Tap to know their names. And double tap to read headlines, on next screen.' />
</ScrollView>
);
_handleItemClick(source_index)
var selectedSource = NEWS_SOURCES[source_index];
console.log('Channel Selected: '+source_index, selectedSource);
this.props.navigation.navigate('HeadlinesStack', channel_data: NEWS_SOURCES[source_index]);
_renderItem(obj)
console.log(obj);
return (
<View key=obj.index style=styles.row >
<TouchableOpacity style= onPress=()=>this._handleItemClick(obj.index) accessible=true accessibilityRole="button" accessibilityLabel=obj.item.id+'. '+obj.item.title>
<Text style=[styles.lightTxt, styles.rowTxt]>obj.item.title</Text>
</TouchableOpacity>
</View>
);
_keyExtractor = (item, index) => 'key'+item.id;
const styles = StyleSheet.create(
container:
flex: 1,
backgroundColor: '#000',
,
app_name:
color: '#fff', textAlign: 'center', fontSize:18
,
lightTxt:
color: '#fff'
,
rowTxt:
padding:25
,
row:
borderBottomWidth: 1, borderBottomColor: '#333', borderStyle: 'solid'
,
);
HeadlinesScreen.js
import React from 'react';
import ScrollView, View, Text, FlatList, TouchableOpacity, Modal, Alert, StyleSheet, ActivityIndicator, Button, ToastAndroid, TouchableHighlight, UIManager, findNodeHandle from 'react-native';
import NEWS_SOURCES, fetch_newsByCountry, fetch_newsBySourceID, fetch_newsFullStory from '../libraries/loader';
export const Toast=(props)=>
if (props.visible)
ToastAndroid.showWithGravityAndOffset(props.message, ToastAndroid.LONG, ToastAndroid.BOTTOM, 25, 50);
return null;
return null;
;
export default class HeadlinesScreen extends React.Component
static navigationOptions=
title: 'Headlines',
;
constructor(props)
super(props);
this.state = channelSource: this.props.navigation.getParam('channel_data', 'none'), // default value 'none'
dataList: [], modalVisible: false, selectedItemId: null, selectedItem_desc: null ;
this._renderItem = this._renderItem.bind(this);
this._handleItemClick = this._handleItemClick.bind(this);
this._displayItemDetails = this._displayItemDetails.bind(this);
this._setModalVisible = this._setModalVisible.bind(this);
this._onFetchComplete = this._onFetchComplete.bind(this);
this._forceTriggerSpeak = this._forceTriggerSpeak.bind(this);
render()
console.log('nthis.props.navigation:', this.props.navigation);
console.log('nnSelected Channel state.params Data: ', this.props.navigation.state.params);
console.log('nnSelected Channel param Data: ', this.props.navigation.getParam('channel_data'));
console.log('nnSelected Channel state Data: ', this.state.channelSource);
//return (<View></View>) ;
//console.log('nnRender: n',this.state);
console.log('nnRender - modal state: n',this.state.modalVisible);
return (
<ScrollView style=styles.container accessibilityLiveRegion="polite" importantForAccessibility=this.state.modalVisible==false ? 'yes' : 'no-hide-descendants'>
(this.state.dataList.length ==0? <ActivityIndicator size="large" Accessible=true accessibilityLabel="Loading news, please wait." /> :
this.state.dataList.map(this._renderItem)
)
<Toast visible=this.state.dataList.length ==0 && this.state.modalVisible==false ? true: false message="Loading news, please wait." />
<Toast visible=this.state.dataList.length > 0 && this.state.modalVisible==false ? true: false message=this.state.dataList.length+' news loaded. Tap to read headline. And double tap to read details.' />
<Toast visible=this.state.dataList.length > 0 && this.state.modalVisible==true ? true: false message='Loading full story, please wait.' />
<Toast visible=this.state.dataList.length > 0 && this.state.modalVisible==true && this.state.selectedItem_desc != null? true: false message='Story loaded, please tap on screen to read. And scroll bottom of screen and hit Close button, to close this story.' />
(this.state.modalVisible ? this._displayItemDetails() : null)
</ScrollView>
);
async componentDidMount()
console.log("nnn", this.props.navigation.getParam('channel_data'));
var newsList = await fetch_newsBySourceID(this.state.channelSource, this._onFetchComplete); // external api call
_onFetchComplete(payload, payloadType) story
console.log('nn onFetchComplete list: n', payload);
if(Array.isArray(payload) && payloadType == 'list')
console.log('nn onFetchComplete list: n'+payload.length);
this.setState(previousState =>
return dataList: payload;
);
else
this.setState(previousState =>
return selectedItem_desc: payload;
);
_renderItem(obj, index)
return (
<View key=index style= borderBottomWidth: 1, borderBottomColor: '#ccc', borderStyle: 'solid', padding:10 >
<TouchableOpacity style=flexDirection: 'row', onPress=()=>this._handleItemClick(index) accessible=true accessibilityLiveRegion="polite" accessibilityLabel=(index-1+2)+". "+obj.title accessibilityHint="Double tap to read full news on next screen.">
<Text style=[styles.lightTxt, styles.rowTxt] >obj.title</Text>
</TouchableOpacity>
</View>
);
async _handleItemClick(itemIndex)
console.log('showModal for item: '+itemIndex);
fetch_newsFullStory(this.state.dataList[itemIndex].story_url, this.state.channelSource, this._onFetchComplete);
_forceTriggerSpeak()
UIManager.sendAccessibilityEvent( findNodeHandle(this), UIManager.AccessibilityEventTypes.typeViewClicked);
// usually item details in a Popup Modal View
_displayItemDetails() // this.state.dataList[this.state.selectedItemId].content
console.log('nnDisplay Modal:n', this.state.modalVisible);
// usually used to hide Popup Modal
const styles = StyleSheet.create(
container:
flex: 1,
paddingTop: 15,
backgroundColor: '#000',
,
lightTxt:
color: '#fff'
,
rowTxt:
padding:25
,
);
react-native accessibility expo android-6.0-marshmallow talkback
add a comment |
I am using ReactNative
with Expo
, and I have noticed that on Android 6 the TalkBack Accessibility feature is not properly working. On first screen It is working, but on next screens it is not working (which also load FlatList dynamically). I do checked on latest Android 7, 8 version and there the TalkBack feature is working pretty Ok on all screens.
Here is my sample code:
Package.json
"main": "node_modules/expo/AppEntry.js",
"scripts":
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"eject": "expo eject",
"test": "node ./node_modules/jest/bin/jest.js --watchAll"
,
"jest":
"preset": "jest-expo"
,
"dependencies":
"@expo/samples": "2.1.1",
"expo": "^32.0.0",
"react": "16.5.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
"react-native-cheerio": "^1.0.0-rc.4",
"react-native-xml2js": "^1.0.3",
"react-navigation": "^3.0.9"
,
"devDependencies":
"babel-preset-expo": "^5.0.0",
"jest-expo": "^32.0.0"
,
"private": true
HomeScreen
import React from 'react';
import
Image,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View, FlatList, ToastAndroid
from 'react-native';
import NEWS_SOURCES from '../libraries/loader';
export const Toast = (props) =>
if (props.visible)
ToastAndroid.showWithGravityAndOffset(props.message, ToastAndroid.LONG, ToastAndroid.BOTTOM, 25, 50);
return null;
return null;
;
export default class HomeScreen extends React.Component
static navigationOptions =
header: null,
;
constructor(props)
super(props);
this._renderItem = this._renderItem.bind(this);
this._handleItemClick = this._handleItemClick.bind(this);
render()
console.log('nnavigation props: ', this.props.navigation);
return (
<ScrollView style=styles.container accessibilityLiveRegion="polite">
<View style=flex:1, flexDirection: 'column', marginTop:50>
<Text style=styles.app_name accessibilityLabel="Select 1 of "+NEWS_SOURCES.length+" News Channels, from the list - given on screen">News Assistant</Text>
</View>
<View style=flex:5, flexDirection: 'column'>
<FlatList
style=padding:8
data=NEWS_SOURCES
renderItem=this._renderItem
keyExtractor=this._keyExtractor
/>
</View>
<Toast visible=true message='Welcome, to news assistant. We got '+NEWS_SOURCES.length+' news channels loaded for you. Tap to know their names. And double tap to read headlines, on next screen.' />
</ScrollView>
);
_handleItemClick(source_index)
var selectedSource = NEWS_SOURCES[source_index];
console.log('Channel Selected: '+source_index, selectedSource);
this.props.navigation.navigate('HeadlinesStack', channel_data: NEWS_SOURCES[source_index]);
_renderItem(obj)
console.log(obj);
return (
<View key=obj.index style=styles.row >
<TouchableOpacity style= onPress=()=>this._handleItemClick(obj.index) accessible=true accessibilityRole="button" accessibilityLabel=obj.item.id+'. '+obj.item.title>
<Text style=[styles.lightTxt, styles.rowTxt]>obj.item.title</Text>
</TouchableOpacity>
</View>
);
_keyExtractor = (item, index) => 'key'+item.id;
const styles = StyleSheet.create(
container:
flex: 1,
backgroundColor: '#000',
,
app_name:
color: '#fff', textAlign: 'center', fontSize:18
,
lightTxt:
color: '#fff'
,
rowTxt:
padding:25
,
row:
borderBottomWidth: 1, borderBottomColor: '#333', borderStyle: 'solid'
,
);
HeadlinesScreen.js
import React from 'react';
import ScrollView, View, Text, FlatList, TouchableOpacity, Modal, Alert, StyleSheet, ActivityIndicator, Button, ToastAndroid, TouchableHighlight, UIManager, findNodeHandle from 'react-native';
import NEWS_SOURCES, fetch_newsByCountry, fetch_newsBySourceID, fetch_newsFullStory from '../libraries/loader';
export const Toast=(props)=>
if (props.visible)
ToastAndroid.showWithGravityAndOffset(props.message, ToastAndroid.LONG, ToastAndroid.BOTTOM, 25, 50);
return null;
return null;
;
export default class HeadlinesScreen extends React.Component
static navigationOptions=
title: 'Headlines',
;
constructor(props)
super(props);
this.state = channelSource: this.props.navigation.getParam('channel_data', 'none'), // default value 'none'
dataList: [], modalVisible: false, selectedItemId: null, selectedItem_desc: null ;
this._renderItem = this._renderItem.bind(this);
this._handleItemClick = this._handleItemClick.bind(this);
this._displayItemDetails = this._displayItemDetails.bind(this);
this._setModalVisible = this._setModalVisible.bind(this);
this._onFetchComplete = this._onFetchComplete.bind(this);
this._forceTriggerSpeak = this._forceTriggerSpeak.bind(this);
render()
console.log('nthis.props.navigation:', this.props.navigation);
console.log('nnSelected Channel state.params Data: ', this.props.navigation.state.params);
console.log('nnSelected Channel param Data: ', this.props.navigation.getParam('channel_data'));
console.log('nnSelected Channel state Data: ', this.state.channelSource);
//return (<View></View>) ;
//console.log('nnRender: n',this.state);
console.log('nnRender - modal state: n',this.state.modalVisible);
return (
<ScrollView style=styles.container accessibilityLiveRegion="polite" importantForAccessibility=this.state.modalVisible==false ? 'yes' : 'no-hide-descendants'>
(this.state.dataList.length ==0? <ActivityIndicator size="large" Accessible=true accessibilityLabel="Loading news, please wait." /> :
this.state.dataList.map(this._renderItem)
)
<Toast visible=this.state.dataList.length ==0 && this.state.modalVisible==false ? true: false message="Loading news, please wait." />
<Toast visible=this.state.dataList.length > 0 && this.state.modalVisible==false ? true: false message=this.state.dataList.length+' news loaded. Tap to read headline. And double tap to read details.' />
<Toast visible=this.state.dataList.length > 0 && this.state.modalVisible==true ? true: false message='Loading full story, please wait.' />
<Toast visible=this.state.dataList.length > 0 && this.state.modalVisible==true && this.state.selectedItem_desc != null? true: false message='Story loaded, please tap on screen to read. And scroll bottom of screen and hit Close button, to close this story.' />
(this.state.modalVisible ? this._displayItemDetails() : null)
</ScrollView>
);
async componentDidMount()
console.log("nnn", this.props.navigation.getParam('channel_data'));
var newsList = await fetch_newsBySourceID(this.state.channelSource, this._onFetchComplete); // external api call
_onFetchComplete(payload, payloadType) story
console.log('nn onFetchComplete list: n', payload);
if(Array.isArray(payload) && payloadType == 'list')
console.log('nn onFetchComplete list: n'+payload.length);
this.setState(previousState =>
return dataList: payload;
);
else
this.setState(previousState =>
return selectedItem_desc: payload;
);
_renderItem(obj, index)
return (
<View key=index style= borderBottomWidth: 1, borderBottomColor: '#ccc', borderStyle: 'solid', padding:10 >
<TouchableOpacity style=flexDirection: 'row', onPress=()=>this._handleItemClick(index) accessible=true accessibilityLiveRegion="polite" accessibilityLabel=(index-1+2)+". "+obj.title accessibilityHint="Double tap to read full news on next screen.">
<Text style=[styles.lightTxt, styles.rowTxt] >obj.title</Text>
</TouchableOpacity>
</View>
);
async _handleItemClick(itemIndex)
console.log('showModal for item: '+itemIndex);
fetch_newsFullStory(this.state.dataList[itemIndex].story_url, this.state.channelSource, this._onFetchComplete);
_forceTriggerSpeak()
UIManager.sendAccessibilityEvent( findNodeHandle(this), UIManager.AccessibilityEventTypes.typeViewClicked);
// usually item details in a Popup Modal View
_displayItemDetails() // this.state.dataList[this.state.selectedItemId].content
console.log('nnDisplay Modal:n', this.state.modalVisible);
// usually used to hide Popup Modal
const styles = StyleSheet.create(
container:
flex: 1,
paddingTop: 15,
backgroundColor: '#000',
,
lightTxt:
color: '#fff'
,
rowTxt:
padding:25
,
);
react-native accessibility expo android-6.0-marshmallow talkback
I am using ReactNative
with Expo
, and I have noticed that on Android 6 the TalkBack Accessibility feature is not properly working. On first screen It is working, but on next screens it is not working (which also load FlatList dynamically). I do checked on latest Android 7, 8 version and there the TalkBack feature is working pretty Ok on all screens.
Here is my sample code:
Package.json
"main": "node_modules/expo/AppEntry.js",
"scripts":
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"eject": "expo eject",
"test": "node ./node_modules/jest/bin/jest.js --watchAll"
,
"jest":
"preset": "jest-expo"
,
"dependencies":
"@expo/samples": "2.1.1",
"expo": "^32.0.0",
"react": "16.5.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
"react-native-cheerio": "^1.0.0-rc.4",
"react-native-xml2js": "^1.0.3",
"react-navigation": "^3.0.9"
,
"devDependencies":
"babel-preset-expo": "^5.0.0",
"jest-expo": "^32.0.0"
,
"private": true
HomeScreen
import React from 'react';
import
Image,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View, FlatList, ToastAndroid
from 'react-native';
import NEWS_SOURCES from '../libraries/loader';
export const Toast = (props) =>
if (props.visible)
ToastAndroid.showWithGravityAndOffset(props.message, ToastAndroid.LONG, ToastAndroid.BOTTOM, 25, 50);
return null;
return null;
;
export default class HomeScreen extends React.Component
static navigationOptions =
header: null,
;
constructor(props)
super(props);
this._renderItem = this._renderItem.bind(this);
this._handleItemClick = this._handleItemClick.bind(this);
render()
console.log('nnavigation props: ', this.props.navigation);
return (
<ScrollView style=styles.container accessibilityLiveRegion="polite">
<View style=flex:1, flexDirection: 'column', marginTop:50>
<Text style=styles.app_name accessibilityLabel="Select 1 of "+NEWS_SOURCES.length+" News Channels, from the list - given on screen">News Assistant</Text>
</View>
<View style=flex:5, flexDirection: 'column'>
<FlatList
style=padding:8
data=NEWS_SOURCES
renderItem=this._renderItem
keyExtractor=this._keyExtractor
/>
</View>
<Toast visible=true message='Welcome, to news assistant. We got '+NEWS_SOURCES.length+' news channels loaded for you. Tap to know their names. And double tap to read headlines, on next screen.' />
</ScrollView>
);
_handleItemClick(source_index)
var selectedSource = NEWS_SOURCES[source_index];
console.log('Channel Selected: '+source_index, selectedSource);
this.props.navigation.navigate('HeadlinesStack', channel_data: NEWS_SOURCES[source_index]);
_renderItem(obj)
console.log(obj);
return (
<View key=obj.index style=styles.row >
<TouchableOpacity style= onPress=()=>this._handleItemClick(obj.index) accessible=true accessibilityRole="button" accessibilityLabel=obj.item.id+'. '+obj.item.title>
<Text style=[styles.lightTxt, styles.rowTxt]>obj.item.title</Text>
</TouchableOpacity>
</View>
);
_keyExtractor = (item, index) => 'key'+item.id;
const styles = StyleSheet.create(
container:
flex: 1,
backgroundColor: '#000',
,
app_name:
color: '#fff', textAlign: 'center', fontSize:18
,
lightTxt:
color: '#fff'
,
rowTxt:
padding:25
,
row:
borderBottomWidth: 1, borderBottomColor: '#333', borderStyle: 'solid'
,
);
HeadlinesScreen.js
import React from 'react';
import ScrollView, View, Text, FlatList, TouchableOpacity, Modal, Alert, StyleSheet, ActivityIndicator, Button, ToastAndroid, TouchableHighlight, UIManager, findNodeHandle from 'react-native';
import NEWS_SOURCES, fetch_newsByCountry, fetch_newsBySourceID, fetch_newsFullStory from '../libraries/loader';
export const Toast=(props)=>
if (props.visible)
ToastAndroid.showWithGravityAndOffset(props.message, ToastAndroid.LONG, ToastAndroid.BOTTOM, 25, 50);
return null;
return null;
;
export default class HeadlinesScreen extends React.Component
static navigationOptions=
title: 'Headlines',
;
constructor(props)
super(props);
this.state = channelSource: this.props.navigation.getParam('channel_data', 'none'), // default value 'none'
dataList: [], modalVisible: false, selectedItemId: null, selectedItem_desc: null ;
this._renderItem = this._renderItem.bind(this);
this._handleItemClick = this._handleItemClick.bind(this);
this._displayItemDetails = this._displayItemDetails.bind(this);
this._setModalVisible = this._setModalVisible.bind(this);
this._onFetchComplete = this._onFetchComplete.bind(this);
this._forceTriggerSpeak = this._forceTriggerSpeak.bind(this);
render()
console.log('nthis.props.navigation:', this.props.navigation);
console.log('nnSelected Channel state.params Data: ', this.props.navigation.state.params);
console.log('nnSelected Channel param Data: ', this.props.navigation.getParam('channel_data'));
console.log('nnSelected Channel state Data: ', this.state.channelSource);
//return (<View></View>) ;
//console.log('nnRender: n',this.state);
console.log('nnRender - modal state: n',this.state.modalVisible);
return (
<ScrollView style=styles.container accessibilityLiveRegion="polite" importantForAccessibility=this.state.modalVisible==false ? 'yes' : 'no-hide-descendants'>
(this.state.dataList.length ==0? <ActivityIndicator size="large" Accessible=true accessibilityLabel="Loading news, please wait." /> :
this.state.dataList.map(this._renderItem)
)
<Toast visible=this.state.dataList.length ==0 && this.state.modalVisible==false ? true: false message="Loading news, please wait." />
<Toast visible=this.state.dataList.length > 0 && this.state.modalVisible==false ? true: false message=this.state.dataList.length+' news loaded. Tap to read headline. And double tap to read details.' />
<Toast visible=this.state.dataList.length > 0 && this.state.modalVisible==true ? true: false message='Loading full story, please wait.' />
<Toast visible=this.state.dataList.length > 0 && this.state.modalVisible==true && this.state.selectedItem_desc != null? true: false message='Story loaded, please tap on screen to read. And scroll bottom of screen and hit Close button, to close this story.' />
(this.state.modalVisible ? this._displayItemDetails() : null)
</ScrollView>
);
async componentDidMount()
console.log("nnn", this.props.navigation.getParam('channel_data'));
var newsList = await fetch_newsBySourceID(this.state.channelSource, this._onFetchComplete); // external api call
_onFetchComplete(payload, payloadType) story
console.log('nn onFetchComplete list: n', payload);
if(Array.isArray(payload) && payloadType == 'list')
console.log('nn onFetchComplete list: n'+payload.length);
this.setState(previousState =>
return dataList: payload;
);
else
this.setState(previousState =>
return selectedItem_desc: payload;
);
_renderItem(obj, index)
return (
<View key=index style= borderBottomWidth: 1, borderBottomColor: '#ccc', borderStyle: 'solid', padding:10 >
<TouchableOpacity style=flexDirection: 'row', onPress=()=>this._handleItemClick(index) accessible=true accessibilityLiveRegion="polite" accessibilityLabel=(index-1+2)+". "+obj.title accessibilityHint="Double tap to read full news on next screen.">
<Text style=[styles.lightTxt, styles.rowTxt] >obj.title</Text>
</TouchableOpacity>
</View>
);
async _handleItemClick(itemIndex)
console.log('showModal for item: '+itemIndex);
fetch_newsFullStory(this.state.dataList[itemIndex].story_url, this.state.channelSource, this._onFetchComplete);
_forceTriggerSpeak()
UIManager.sendAccessibilityEvent( findNodeHandle(this), UIManager.AccessibilityEventTypes.typeViewClicked);
// usually item details in a Popup Modal View
_displayItemDetails() // this.state.dataList[this.state.selectedItemId].content
console.log('nnDisplay Modal:n', this.state.modalVisible);
// usually used to hide Popup Modal
const styles = StyleSheet.create(
container:
flex: 1,
paddingTop: 15,
backgroundColor: '#000',
,
lightTxt:
color: '#fff'
,
rowTxt:
padding:25
,
);
react-native accessibility expo android-6.0-marshmallow talkback
react-native accessibility expo android-6.0-marshmallow talkback
asked Mar 8 at 4:07
Muhammad HannanMuhammad Hannan
6631030
6631030
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55056578%2freact-native-accessibility-talkback-not-working-on-inner-screens-in-android-6%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55056578%2freact-native-accessibility-talkback-not-working-on-inner-screens-in-android-6%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown