React-Native + Flex不响应方向更改

问题描述 投票:12回答:7

我正在使用React-Native编写通用iPhone / iPad应用程序。但是当方向改变时,我正在努力正确地渲染我的视图。以下是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);

这是它在Portrait中呈现的方式(这是正确的):

但是,当设备旋转时。红色视图不会相应旋转。

ios flexbox react-native
7个回答
13
投票

在本地反应中响应方向变化非常简单。本机中的每个视图都有一个名为onLayout的侦听器,它会在方向更改时调用。我们只需要实现这一点。最好将维度存储在状态变量中并更新每个方向更改,以便在更改后重新呈现。另外,我们需要重新加载视图以响应方向更改。

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>
    );
}
}

12
投票

最简单的方法是:

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>
    );
  }
}

6
投票

对于更新版本的React Native,方向更改不一定会触发onLayout,但Dimensions提供了更直接相关的事件:

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>
        );
    }
}

请注意,此代码适用于应用的根组件。如果在应用程序中更深入地使用它,则需要包含相应的removeEventListener调用。


3
投票

您可以使用react-native-orientation来检测并执行方向更改的更改。

var Orientation = require('react-native-orientation');

还可以使用返回大小(宽度,高度)的Dimension类。

Dimensions.get('window')

使用这些方法可以使用方向

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
     });

   }

我也用过这个,但它的性能太低了。

希望有帮助......


0
投票

好。我找到了答案。需要在我们的viewcontroller中实现以下内容并在其中调用刷新我们的ReactNative视图。

- (无效)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation


0
投票

对于任何使用Exponent的人,您只需要从orientation中删除exp.json密钥。


0
投票

onLayoutDimensions.addEventListener都没有在React 16.3中为我们工作。

这是一个flexbox hack,它使图像在方向变化时调整大小。 (我们还使用了React的漂亮但文档记录不足的ImageBackground组件来获取图像顶部的文本):

      <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
  },
});

imageHeight样式将设置View组件的高度(对用户不可见),然后Flexbox会自动将同一行上的图像弯曲到相同的高度。所以你基本上是以间接的方式设置图像的高度。 Flex将确保它弯曲以在方向更改时填充整个容器。

© www.soinside.com 2019 - 2024. All rights reserved.