Commit 3ce055dc authored by Niccolò Cantù's avatar Niccolò Cantù

handle focus order also on android

parent 67e89dfd
......@@ -23,7 +23,7 @@ const AccessibilityWrapperPropTypes = {
),
};
class AccessibilityWrapperIOS extends React.Component {
class AccessibilityWrapper extends React.Component {
static propTypes = AccessibilityWrapperPropTypes;
ref = React.createRef();
......@@ -92,6 +92,6 @@ AccessibilityWrapperAndroid.propTypes = AccessibilityWrapperPropTypes;
* }
*/
export default Platform.select({
ios: AccessibilityWrapperIOS,
ios: AccessibilityWrapper,
android: AccessibilityWrapperAndroid,
});
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow strict-local
*/
import React from 'react';
import {
StyleSheet,
TouchableOpacity,
View,
Text,
findNodeHandle,
} from 'react-native';
import FocusOrder from './FocusOrder';
const AppAndroid = () => {
const ref1 = React.useRef();
const ref2 = React.useRef();
const ref3 = React.useRef();
return (
<>
<View style={styles.header}>
<Text style={styles.headerText}>RNAccessibilityOrder</Text>
</View>
<View style={styles.body}>
<TouchableOpacity
style={styles.button}
onPress={() => {
FocusOrder.setOrder([
findNodeHandle(ref3.current),
findNodeHandle(ref2.current),
findNodeHandle(ref1.current),
]);
}}>
<Text>Change accessibility focus order</Text>
</TouchableOpacity>
<View>
<TouchableOpacity ref={ref1} style={styles.button}>
<Text>Button 1</Text>
</TouchableOpacity>
<TouchableOpacity ref={ref2} style={styles.button}>
<Text>Button 2</Text>
</TouchableOpacity>
<TouchableOpacity ref={ref3} style={styles.button}>
<Text>Button 3</Text>
</TouchableOpacity>
</View>
</View>
</>
);
};
const styles = StyleSheet.create({
body: {
flex: 1,
paddingHorizontal: 10,
},
group: {
padding: 10,
},
header: {
backgroundColor: '#008577',
paddingHorizontal: 20,
paddingVertical: 20,
},
headerText: {
color: 'white',
},
button: {
padding: 10,
margin: 10,
backgroundColor: '#aaa',
},
});
export default AppAndroid;
......@@ -7,23 +7,15 @@
*/
import React from 'react';
import {
SafeAreaView,
StyleSheet,
TouchableOpacity,
View,
Text,
AccessibilityInfo,
} from 'react-native';
import {StyleSheet, TouchableOpacity, View, Text} from 'react-native';
import AccessibilityWrapper from './AccessibilityWrapper';
const App = () => {
const AppIos = () => {
const ref1 = React.useRef();
const ref2 = React.useRef();
const ref3 = React.useRef();
const [state, setState] = React.useState([ref1, ref2, ref3]);
const [changed, setChanged] = React.useState(false);
return (
<>
......@@ -32,24 +24,20 @@ const App = () => {
</View>
<View style={styles.body}>
<TouchableOpacity
style={styles.button}
onPress={() => {
if (!changed) {
setState([ref3, ref2, ref1]);
} else {
setState([ref1, ref2, ref3]);
}
setChanged(!changed);
setState([ref3, ref2, ref1]);
}}>
<Text>Change accessibility focus order</Text>
</TouchableOpacity>
<AccessibilityWrapper fieldsRefs={state}>
<TouchableOpacity ref={ref1}>
<TouchableOpacity ref={ref1} style={styles.button}>
<Text>Button 1</Text>
</TouchableOpacity>
<TouchableOpacity ref={ref2}>
<TouchableOpacity ref={ref2} style={styles.button}>
<Text>Button 2</Text>
</TouchableOpacity>
<TouchableOpacity ref={ref3}>
<TouchableOpacity ref={ref3} style={styles.button}>
<Text>Button 3</Text>
</TouchableOpacity>
</AccessibilityWrapper>
......@@ -74,6 +62,11 @@ const styles = StyleSheet.create({
headerText: {
color: 'white',
},
button: {
padding: 10,
margin: 10,
backgroundColor: '#aaa',
},
});
export default App;
export default AppIos;
import {NativeModules} from 'react-native';
export default NativeModules.FocusOrder;
/**
* @format
*/
import 'react-native';
import React from 'react';
import App from '../App';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
it('renders correctly', () => {
renderer.create(<App />);
});
package com.rnaccessibilityorder;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.uimanager.UIManagerModule;
import android.util.Log;
import android.view.View;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
public class FocusOrderModule extends ReactContextBaseJavaModule {
private static ReactApplicationContext reactContext;
FocusOrderModule(ReactApplicationContext context) {
super(context);
reactContext = context;
}
@Override
public String getName() {
return "FocusOrder";
}
@ReactMethod
public void setOrder(ReadableArray order) {
Log.w("ACCESSIBILITY_FOCUS", "here");
final UIManagerModule uiManager = this.reactContext.getNativeModule(UIManagerModule.class);
ArrayList<View> viewList = new ArrayList<View>();
for (Object el : order.toArrayList()) {
viewList.add(uiManager.resolveView((int) ((double) el)));
}
for (int i = 0; i < viewList.size(); i++) {
if (i > 0) {
View current = viewList.get(i);
View prev = viewList.get(i - 1);
current.setAccessibilityTraversalAfter(prev.getId());
}
}
}
}
package com.rnaccessibilityorder;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class FocusOrderPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new FocusOrderModule(reactContext));
return modules;
}
}
......@@ -25,7 +25,7 @@ public class MainApplication extends Application implements ReactApplication {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
packages.add(new FocusOrderPackage());
return packages;
}
......
......@@ -2,8 +2,12 @@
* @format
*/
import {AppRegistry} from 'react-native';
import App from './App';
import {AppRegistry, Platform} from 'react-native';
import {name as appName} from './app.json';
const App =
Platform.OS === 'ios'
? require('./AppIos').default
: require('./AppAndroid').default;
AppRegistry.registerComponent(appName, () => App);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment