web-dev-qa-db-fra.com

React-Native + Flex ne répond pas au changement d'orientation

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): Portrait

Cependant lorsque l'appareil est tourné. La vue rouge ne tourne pas en conséquence. Landscape

16
Priyank

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>
    );
  }
}
19
Pablo Darde

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.

enter image description here

 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>
    );
}
}
14
Rajan Twanabashu

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.

9
Tom Clarkson

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...

5
Harish Pathak

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.

1
Magne

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

0
Priyank

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
};
0
Anubhav Gupta

Pour toute personne utilisant Exposant il vous suffit de supprimer la clé orientation de votre exp.json.

0
Liron Yahdav