J'écris une application Universal iPhone/iPad en utilisant React-Native. Cependant, j'ai du mal à rendre ma vue correctement lorsque l'orientation change. Voici le code source du fichier js:
'use strict';
var React = require('react-native');
var {
Text,
View
} = React;
var CardView = require('./CardView');
var styles = React.StyleSheet.create({
container:{
flex:1,
backgroundColor: 'red'
}
});
class MySimpleApp extends React.Component {
render() {
return <View style={styles.container}/>;
}
}
React.AppRegistry.registerComponent('SimpleApp', () => MySimpleApp);
Voici comment il s'affiche dans Portrait (ce qui est correct):
Cependant lorsque l'appareil est tourné. La vue rouge ne tourne pas en conséquence.
La manière la plus simple est:
import React, { Component } from 'react';
import { Dimensions, View, Text } from 'react-native';
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
}
this.onLayout = this.onLayout.bind(this);
}
onLayout(e) {
this.setState({
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
});
}
render() {
return(
<View
onLayout={this.onLayout}
style={{width: this.state.width}}
>
<Text>Layout width: {this.state.width}</Text>
</View>
);
}
}
Il est assez simple de répondre au changement d'orientation dans React Native. Chaque vue dans react native a un écouteur appelé onLayout qui est invoqué lors d'un changement d'orientation. Nous avons juste besoin de mettre cela en œuvre. Il est préférable de stocker la dimension dans la variable d'état et de la mettre à jour à chaque changement d'orientation afin que le nouveau rendu se produise après le changement. Sinon, nous devons recharger la vue pour répondre au changement d'orientation.
import React, { Component } from "react";
import { StyleSheet, Text, View, Image, Dimensions } from "react-native";
var { height, width } = Dimensions.get("window");
export default class Com extends Component {
constructor() {
console.log("constructor");
super();
this.state = {
layout: {
height: height,
width: width
}
};
}
_onLayout = event => {
console.log(
"------------------------------------------------" +
JSON.stringify(event.nativeEvent.layout)
);
this.setState({
layout: {
height: event.nativeEvent.layout.height,
width: event.nativeEvent.layout.width
}
});
};
render() {
console.log(JSON.stringify(this.props));
return (
<View
style={{ backgroundColor: "red", flex: 1 }}
onLayout={this._onLayout}
>
<View
style={{
backgroundColor: "green",
height: this.state.layout.height - 10,
width: this.state.layout.width - 10,
margin: 5
}}
/>
</View>
);
}
}
Pour les versions plus récentes de React Native, le changement d'orientation ne se déclenche pas nécessairement onLayout, mais Dimensions
fournit un événement plus directement pertinent:
class App extends Component {
constructor() {
super();
this.state = {
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
};
Dimensions.addEventListener("change", (e) => {
this.setState(e.window);
});
}
render() {
return (
<View
style={{
width: this.state.width,
height: this.state.height,
}}
>
</View>
);
}
}
Notez que ce code est destiné au composant racine d'une application. Si vous l'utilisez plus profondément dans l'application, vous devrez inclure un appel removeEventListener correspondant.
Vous pouvez utiliser React-Native-Orientation pour détecter et effectuer des changements sur le changement d'orientation.
var Orientation = require('react-native-orientation');
Utilisez également la classe Dimension qui renvoie la taille (largeur, hauteur).
Dimensions.get('window')
Utilisez ces méthodes pour jouer avec les orientations
componentDidMount() {
Orientation.lockToPortrait(); //this will lock the view to Portrait
//Orientation.lockToLandscape(); //this will lock the view to Landscape
//Orientation.unlockAllOrientations(); //this will unlock the view to all Orientations
// self = this;
console.log('componentDidMount');
Orientation.addOrientationListener(this._orientationDidChange);
}
componentWillUnmount() {
console.log('componentWillUnmount');
Orientation.getOrientation((err,orientation)=> {
console.log("Current Device Orientation: ", orientation);
});
Orientation.removeOrientationListener(this._orientationDidChange);
}
_orientationDidChange(orientation) {
console.log('Orientation changed to '+orientation);
console.log(self);
if (orientation == 'LANDSCAPE') {
//do something with landscape layout
screenWidth=Dimensions.get('window').width;
console.log('screenWidth:'+screenWidth);
} else {
//do something with portrait layout
screenWidth=Dimensions.get('window').width;
console.log('screenWidth:'+screenWidth);
}
self.setState({
screenWidth:screenWidth
});
}
J'ai également utilisé cela, mais ses performances sont trop faibles.
J'espère que cela pourra aider...
Ni onLayout
ni Dimensions.addEventListener
a fonctionné pour nous en React 16.3.
Voici un flexbox hack qui a fait redimensionner l'image lors d'un changement d'orientation. (Nous avons également utilisé le composant ImageBackground de Nice mais mal documenté pour obtenir du texte au-dessus de l'image):
<View style={styles.container}>
<View style={styles.imageRowWithResizeHack}>
<ImageBackground
style={styles.imageContainer}
imageStyle={styles.thumbnailImg}
source={{ uri: thumbnailUrl }}
>
<View style={styles.imageText}>
<Text style={styles.partnerName}>{partnerName}</Text>
<Text style={styles.title}>{title.toUpperCase()}</Text>
</View>
</ImageBackground>
<View style={styles.imageHeight} />
</View>
</View>
const styles = StyleSheet.create({
container: {
position: 'relative',
flex: 1
},
imageRowWithResizeHack: {
flex: 1,
flexDirection: 'row'
},
imageContainer: {
flex: 1
},
imageHeight: {
height: 200
},
thumbnailImg: {
resizeMode: 'cover'
},
imageText: {
position: 'absolute',
top: 30,
left: TEXT_PADDING_LEFT
},
partnerName: {
fontWeight: '800',
fontSize: 20,
color: PARTNER_NAME_COLOR
},
title: {
color: COLOR_PRIMARY_TEXT,
fontSize: 90,
fontWeight: '700',
marginTop: 10,
marginBottom: 20
},
});
Le style imageHeight
définira la hauteur du composant View (qui est invisible pour l'utilisateur), et Flexbox fléchira alors automatiquement l'image sur la même ligne pour être du même hauteur. Vous définissez donc la hauteur de l'image d'une manière indirecte. Flex s'assurera qu'il fléchit pour remplir tout le conteneur lors d'un changement d'orientation.
D'ACCORD. J'ai trouvé une réponse à cela. Besoin d'implémenter ce qui suit dans notre viewcontroller et d'appeler rafraîchir notre vue ReactNative à l'intérieur.
- (vide) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation
Contrairement à la réponse donnée par l'utilisateur Rajan Twanabashu
vous pouvez également utiliser la bibliothèque react-native-styleman pour gérer très facilement le changement d'orientation:
Voici un exemple de la façon dont vous le feriez:
import { withStyles } from 'react-native-styleman';
const styles = () => ({
container: {
// your common styles here for container node.
flex: 1,
// lets write a media query to change background color automatically based on the device's orientation
'@media': [
{
orientation: 'landscape', // for landscape
styles: { // apply following styles
// these styles would be applied when the device is in landscape
// mode.
backgroundColor: 'green'
//.... more landscape related styles here...
}
},
{
orientation: 'portrait', // for portrait
styles: { // apply folllowing styles
// these styles would be applied when the device is in portrait
// mode.
backgroundColor: 'red'
//.... more protrait related styles here...
}
}
]
}
});
let Component = ({ styles })=>(
<View style={styles.container}>
<Text>Some Text</Text>
</View>
);
// use `withStyles` Higher order Component.
Component = withStyles(styles)(Component);
export {
Component
};
Pour toute personne utilisant Exposant il vous suffit de supprimer la clé orientation
de votre exp.json
.