I'm calculating snap points for React Native Bottom Sheet and facing an issue in Android devices. The calculation doesn't work universally to find sheetEndSnap. The StatusBar.currentHeight value needs to be considered for some devices. For others, it does not need to be considered. I can't figure out what is causing this issue and how to differentiate the sheetEndSnap calculation based on devices.
The current implementation is like this.
import React, {useMemo, useRef} from 'react';
import {Dimensions, View, StatusBar, Platform} from 'react-native';
import BottomSheet from '#gorhom/bottom-sheet';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
const {height: windowHeight} = Dimensions.get('window');
const statusBarHeight = Platform.OS === 'android' ? StatusBar.currentHeight : 0;
const sheetStartSnap = 200;
const Screen = () => {
const {top, bottom} = useSafeAreaInsets();
const ref = useRef < BottomSheet > null;
const sheetEndSnap = windowHeight - (top + bottom + statusBarHeight); // For some devices this works fine
// const sheetEndSnap = windowHeight - (top + bottom); // For other devices this works fine
const snapPoints = useMemo(() => [sheetStartSnap, sheetEndSnap], [sheetEndSnap]);
return (
<View style={{flex: 1}}>
<BottomSheet ref={ref} index={0} snapPoints={snapPoints}>
<View style={{flex: 1}} />
</BottomSheet>
</View>
);
};
Related
I want to create a View bigger than the screen with react native directly to works in android and ios, why do i want to create it? because i want to create a swipe at the item on the list
import React from "react";
import { View, Text } from "react-native";
const ViewBoxesWithColorAndText = () => {
return (
<View>
<View style={{ backgroundColor: "red", flex: 0.5 }} />
<Text>Hello World!</Text>
</View>
);
};
export default ViewBoxesWithColorAndText;
Here are the screen dimensions.
import { Dimensions } from 'react-native'
const Window = Dimensions.get('window')
const Screen = Dimensions.get('screen')
const WIDTH = Screen.width
const HEIGHT = Screen.height
const FONT_SCALE = Window.fontScale
const SCREEN_SCALE = Window.scale
I hope, these what you wanted.
I'm trying to setup a minor project for Android using Babylon React Native and use the device orientation as the camera input. When I try to use a DeviceOrientationCamera, the library throws the below error.
[TypeError: undefined is not an object (evaluating 'window.screen.orientation')]
which seems to be coming from this line
When I use an ArcRotateCamera or a FreeCamera instead, the scene loads fine. The code I am using is reproduced below
import React, {useState, useEffect} from 'react';
import {SafeAreaView, useWindowDimensions, View} from 'react-native';
import {EngineView, useEngine} from '#babylonjs/react-native';
import {Scene, SceneLoader, DeviceOrientationCamera, Vector3, FreeCamera} from '#babylonjs/core';
import '#babylonjs/loaders/glTF';
const EngineScreen = (props) => {
const engine = useEngine();
const [camera, setCamera] = useState();
useEffect(() => {
if (engine) {
const scene = new Scene(engine)
const url =
'https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/Duck/glTF-Binary/Duck.glb?raw=true';
SceneLoader.Append("", url, scene, (sc => {
let cam;
try {
// When FreeCamera is used, the scene renders fine
// cam = new FreeCamera('FreeCamera', new Vector3(0, 0, 0), sc);
// When DeviceOrientationCamera is used, it throws an error
cam = new DeviceOrientationCamera('DeviceOrientationCamera', new Vector3(0, 0, 0), sc);
} catch (err) {
console.log(err);
throw err;
}
const canvas = engine.getRenderingCanvas();
cam.attachControl(canvas, true);
setCamera(sc.activeCamera);
}));
}
}, [engine]);
return (
<>
<View style={props.style}>
<View style={{flex: 1}}>
<EngineView camera={camera} displayFrameRate={true} />
</View>
</View>
</>
);
};
const App = () => {
const {width, height} = useWindowDimensions();
return (
<>
<SafeAreaView
style={{
flex: 1,
backgroundColor: 'red',
height,
width,
}}>
<EngineScreen style={{flex: 1}} />
</SafeAreaView>
</>
);
};
export default App;
How can I fix this issue? On a broader level, I want to allow the user to 'look around'(rotate) and 'walk around'(translate) the scene by moving their mobile. How can I achieve that?
Apparently only touch input is currently supported in babylon native. More details in the discussion below
https://forum.babylonjs.com/t/error-using-deviceorientationcamera-in-babylon-react-native/31454/2?u=ketan_bhokray
It works very normally when I use React Hooks or when I use react-native's Component, Hooks.
But when I call a function or Component from external packages such as Axios from my code, the app seems to be broken in that state. (or an empty screen)
I used react-native-cli.
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow strict-local
*/
import React, {useState, useEffect} from 'react';
import type {Node} from 'react';
import {
SafeAreaView,
ScrollView,
StatusBar,
Text,
useColorScheme,
View,
Center,
} from 'react-native';
import Axios from 'axios';
import {
Colors,
Header,
} from 'react-native/Libraries/NewAppScreen';
const App: () => Node = () => {
const isDarkMode = useColorScheme() === 'dark';
const [text, setText] = useState("");
const backgroundStyle = {
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
};
useEffect(() => {
const fetch = async () => {
const {data} = await Axios.get(...); // broken
setText(data.result);
};
fetch();
}, []);
return (
<SafeAreaView style={backgroundStyle}>
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={backgroundStyle}>
<Header />
<View
style={{
backgroundColor: isDarkMode ? Colors.black : Colors.white,
}}>
<Text>{text}</Text>
{/*
this Text Component is still empty.
*/}
</View>
</ScrollView>
</SafeAreaView>
);
};
export default App;
How can I solve this problem?
I Have started learning React Native. By following the documentation of React Native Paper I want a outlined Input box. I am using my QR code to test the app on my android phone. It displays the simple input element not the styled one
my App.js
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-
native';
import Contants from 'expo-constants'
import Home from "./screens/Home";
import CreateContact from "./screens/CreateContact";
export default function App() {
return (
<View style={styles.container}>
{/* <Home /> */}
<CreateContact />
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ebebeb',
marginTop: Contants.statusBarHeight,
},
});
My CreateContact.js
import React, { useState } from 'react';
import { StyleSheet, Text, View, TextInput, } from 'react-native';
const CreateContact = () => {
const [Name, setName] = useState("");
const [Phone, setPhone] = useState("");
const [Email, setEmail] = useState("");
const [Salary, setSalary] = useState("");
const [Picture, setPicture] = useState("");
const [Modal, setModal] = useState(false);
return (
<View style={styles.root}>
<View>
<TextInput
mode="outlined"
selectionColor="green"
label="Name"
placeholder="Name"
value={Name}
onChangeText={(text) => setName(text)}
/>
</View>
</View>
)
}
const styles = StyleSheet.create({
root: {
flex: 1, //take compelete height
}
})
export default CreateContact;
Output in Browser :
my app in mobile screen is same like how it is displaying browser
Im learing React native but i dont understand how to get everything to not overlap with the status bar.
I have tried
translucent={true/flase}
hidden
This is expected behaviour, one solution is to add a padding to your top level view equal to current height of status bar or have a StatusBarView that has same height as the status bar.
Refer to this plugin https://github.com/jgkim/react-native-status-bar-size for listening to status bar height changes.
For e.g
import _ from 'lodash';
import React, { Component } from 'react';
import { View, StatusBar} from 'react-native';
import StatusBarSizeIOS from 'react-native-status-bar-size';
const STATUS_BAR_EXTRA_PADDING = 2;
const DEFAULT_STATUS_BAR_HEIGHT = 10;
class StatusBarView extends Component {
state = {
statusBarHeight: _.get(StatusBarSizeIOS, 'currentHeight', DEFAULT_STATUS_BAR_HEIGHT);
}
_handleStatusBarSizeDidChange = (statusBarHeight) => this.setState({ statusBarHeight })
componentDidMount() {
StatusBarSizeIOS.addEventListener('didChange', this._handleStatusBarSizeDidChange);
}
render() {
return (
<View
style={{
height: this.state.statusBarHeight + STATUS_BAR_EXTRA_PADDING,
}}
>
<StatusBar {...this.props} />
</View>
);
}
}
export default StatusBarView;
Now inside your screens you could do something like
import StatusBarView from '{view_path}';
...
render() {
return (
<View>
<StatusBarView barStyle="default" />
<View>{rest of the view}</View>
</View>
);
}