【问题标题】:iOS Adaptive Layout with React Native带有 React Native 的 iOS 自适应布局
【发布时间】:2016-05-11 05:56:32
【问题描述】:

我已经用 react-native 工作了几个星期了,我已经到了需要同时支持这两个方向的地步。据称 flex-box 应该发挥它的魔力并自动调整布局以适应新的屏幕尺寸。然而 flex-box 并没有像我希望的那样处理这些变化,我并不是说它没有做应该做的事情,我只是说我对它不满意。

更具体地说,我发现this example online 基本上描述了我要解决的问题(只有他们使用本机视图和自动布局来解决)。我想在设备旋转(或更一般地在尺寸变化上)实现布局更改,类似于应用于我链接的“迷你 Instagram”示例的布局更改。

如何使用 react-native 和 flex-box 做到这一点?我应该为不同的屏幕尺寸使用不同的组件还是有适当的方法来实现?

【问题讨论】:

    标签: ios flexbox react-native ios-autolayout


    【解决方案1】:

    我认为 RN 目前没有从原生向 JS 发送任何旋转事件,但您会收到一个布局回调,因此您可以更新布局指标来响应它。例如:

    getInitialState(): {
      return {isPortrait: true}; // You could use Dimensions to get this right initially?
    },
    
    render(): {
      // return a different layout depending on this.state.isPortrait
      return <View onLayout={this.onLayout} />
    },
    
    onLayout(e): {
      var isPortrait = e.nativeEvent.layout.height > e.nativeEvent.layout.width;
      if (isPortrait != this.state.isPortrait) {
        this.setState({isPortrait});
      }
    }
    

    注意:由于 JS 视图更新和布局都是异步发生的,因此很难匹配实际设备旋转变化的时间。

    【讨论】:

    • 我知道如何识别尺寸变化(正如您建议提供 onLayout 回调)。问题是处理它的正确方法是什么?如果我需要像我附加的示例那样更改布局,渲染方法应该会发生很大变化,所以也许我应该在同一个组件中有 2 个渲染方法,或者我应该有 2 个不同的组件?
    • 这真的取决于你的视图树的复杂性。在您链接的示例中,它可能就像在纵向而不是横向使用不同的样式表一样简单,但在其他情况下,2 渲染方法可能是更好的方法。 React 本身并不真正关心这些方法之间的区别。
    【解决方案2】:

    使用 react native 实现这一目标并没有太多工作要做。在这里,我尝试演示与您所要求的类似的视觉布局。

    我们只需要监听视图的 onLayout 事件,只要方向发生变化就会调用该事件。

    通过比较 Dimension.get('window') 中的高度和宽度,我们可以确定设备是处于纵向还是横向模式。这是这个的简单代码

    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));
        var imagel = this.props.list[0].src;
        var landscapeView =
                            <View style={{marginTop:20, flexDirection:'row'}}>
                              <Image source={require('./flower.jpg')} style={{height:this.state.layout.height-50, width:this.state.layout.width/2}}/>
                              <View>
                                <Text style={{backgroundColor:'gray', margin:5}}> header this is landscape view </Text>
                                <Text style={{backgroundColor:'gray',margin:5}}> footer this is portrait view  </Text>
                              </View>
    
    
                            </View>
        var portraitView = <View style={{marginTop:20}}>
                            <Text style={{backgroundColor:'gray', margin:5}}> header this is landscape view </Text>
                              <Image source={require('./flower.jpg')} style={{height:200, width:this.state.layout.width}}/>
                              <Text style={{backgroundColor:'gray',margin:5}}> footer this is portrait view  </Text>
                            </View>
    
        var cview =null;
        if (this.state.layout.height>this.state.layout.width) {
          cview = portraitView
        }else{
          cview = landscapeView;
        }
        return(
          <View style={{backgroundColor:'red', flex:1}}   onLayout={this._onLayout}>
          {cview}
          </View>
        );
      }
    }
    

    这里发生的是我们正在监听事件onLayout,当方向改变时触发。然后我们有状态变量,它保存屏幕的实际高度和宽度以反映方向变化。我们正在使用这个状态的高度和宽度进行视图设计。

    这里发生了两件事。

    1. onLayout 在方向改变时被调用。
    2. 更改状态值后,视图将再次呈现。

    【讨论】:

    • 谢谢。我熟悉 onLayout 事件。你的建议基本上相当于有两个不同的组件 - 一个用于纵向,一个用于横向。
    • 是的,正确的。这是因为布局在两个方向上完全不同。
    • 如何将此值传递给我的style.js 文件(另一个单独的文件),在该文件中我需要不同方向的宽度和高度来进行样式设置?
    猜你喜欢
    • 2017-07-28
    • 1970-01-01
    • 2018-09-20
    • 2023-03-06
    • 2019-04-28
    • 2021-01-28
    • 2015-01-28
    • 1970-01-01
    • 2022-06-10
    相关资源
    最近更新 更多