It can be done by using Viro React with a project that you expo eject. You can still use all your existing expo code, but you will be on an Expo Bare Workflow, not a Managed Workflow.
Here's a rough outline of the steps:
- Run
expo eject on your existing project (You can still use Expo Go to develop any views that do not use AR)
- Run
npx pod-install. You will need to re-run this command any time you add a library that has native modules.
- Plug your iOS device in via USB and build your app using
npx react-native run-ios --device to install your app (the process is similar for android devices). iOS and Android simulators do not support AR.
- The above command will start Metro (which bundles and serves your JS assets) automatically and you should get a hot-reload similar to when you use Expo Go. If you ever stop metro, you can always re-start it with
npx react-native start.
Congrats! You now have an Expo Bare Workflow. You should still be able to run expo start and open your app in Expo Go, and you should also have an installed development version of your app on your device.
Only once you have the above working should you attempt to add Viro React:
- Run
yarn add @viro-community/react-viro
- Run
npx pod-install (and remember to do this each time you add a new library with native modules)
- Create a new AR view (and a link to navigate to it) in your existing app
Your "hello, world" view should look something like the following:
import React, { FC, useState } from "react";
import { StyleSheet, Text, View } from "react-native";
import {
ViroARScene,
ViroARSceneNavigator,
ViroConstants,
ViroFlexView,
ViroImage,
} from '@viro-community/react-viro';
interface MyARViewProps {
foo: string | undefined
}
const ARView: FC<MyARViewProps> = (
props: MyARViewProps
) => {
return (
<View style={{flex: 1}}>
<ViroARSceneNavigator
autofocus={true}
initialScene={{
scene: HelloWorldSceneAR,
}}
style={styles.f1}
/>
<View style={[styles.buttons]}>
<View style={[styles.button]}>
<Text style={[styles.buttonLabel]}>A button</Text>
</View>
</View>
</View>
);
};
export default ARView;
const HelloWorldSceneAR = () => {
const [tracking, setTracking] = useState(false);
function onInitialized(state, reason) {
if (state === ViroConstants.TRACKING_NORMAL) {
setTracking(true);
} else if (state === ViroConstants.TRACKING_NONE) {
setTracking(false)
}
}
return (
<ViroARScene onTrackingUpdated={onInitialized}>
{tracking && (<ViroFlexView
style={{flexDirection: 'row', padding: 0.1}}
width={2.0}
height={.4}
position={[0, 0.25, -1]}
>
<ViroText text="hello, world" />
</ViroFlexView>)}
</ViroARScene>
);
};
let styles = StyleSheet.create({
container: {
marginHorizontal: 10,
alignItems: "center"
},
buttons: {
height: 100,
width: '100%',
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
position: 'absolute',
bottom: 0,
left: 0,
},
button: {
height: 100,
width: 100,
borderRadius: 50,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#123456',
},
buttonLabel: {
color: '#ffffff',
fontSize: 16,
},
f1: {flex: 1},
helloWorldTextStyle: {
fontFamily: 'Arial',
fontSize: 128,
color: '#ffffff',
textAlignVertical: 'center',
textAlign: 'center',
},
});