【问题标题】:Get size of a View in React Native在 React Native 中获取视图的大小
【发布时间】:2015-07-24 01:14:53
【问题描述】:

是否可以获取某个视图的大小(宽度和高度)?例如,我有一个显示进度的视图:

<View ref='progressBar' style={{backgroundColor:'red',flex:this.state.progress}} /> 

我需要知道视图的实际宽度才能正确对齐其他视图。这可能吗?

【问题讨论】:

    标签: ios react-native


    【解决方案1】:

    从 React Native 0.4.2 开始,View 组件有一个onLayout prop。传入一个接受事件对象的函数。事件的nativeEvent 包含视图的布局。

    <View onLayout={(event) => {
      var {x, y, width, height} = event.nativeEvent.layout;
    }} />
    

    每当调整视图大小时,也会调用onLayout 处理程序。

    主要需要注意的是,onLayout 处理程序是在组件安装后的一帧首先调用的,因此您可能希望隐藏 UI,直到计算完布局。

    【讨论】:

    • 这种方法的问题是当设备旋转/视图大小改变时,我没有再次调用 onLayout。
    • onLayout 在视图的框架改变时被调用。也许您的视图在旋转时不会改变其大小或位置。查看 UIExplorer 中的 onLayout 示例,其中 onLayout 在旋转时被调用。
    • 假设我想根据尺寸不同地显示View。我不明白如何使用视图的onLayout 函数来更改视图的显示方式。这不会导致无限循环吗?
    • @LaneRettig 是的,如果这确实是您想要做的,那么您应该以达到静态平衡的方式编写代码。但听起来您可能只想根据屏幕尺寸自定义视图,在这种情况下 onLayout 是不相关的。
    • @ide 在计算布局之前如何隐藏 UI?
    【解决方案2】:

    这是唯一对我有用的东西:

    import React, { Component } from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Text,
      View,
      Image
    } from 'react-native';
    
    export default class Comp extends Component {
    
      find_dimesions(layout){
        const {x, y, width, height} = layout;
        console.warn(x);
        console.warn(y);
        console.warn(width);
        console.warn(height);
      }
      render() {
        return (
          <View onLayout={(event) => { this.find_dimesions(event.nativeEvent.layout) }} style={styles.container}>
            <Text style={styles.welcome}>
              Welcome to React Native!
            </Text>
            <Text style={styles.instructions}>
              To get started, edit index.android.js
            </Text>
            <Text style={styles.instructions}>
              Double tap R on your keyboard to reload,{'\n'}
              Shake or press menu button for dev menu
            </Text>
          </View>
        );
      }
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
      },
      welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
      },
      instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
      },
    });
    
    AppRegistry.registerComponent('Comp', () => Comp);
    

    【讨论】:

      【解决方案3】:

      基本上,如果您想设置大小并使其更改,然后将其设置为这样的布局状态:

      import React, { Component } from 'react';
      import { AppRegistry, StyleSheet, View } from 'react-native';
      
      const styles = StyleSheet.create({
        container: {
          flex: 1,
          backgroundColor: 'yellow',
        },
        View1: {
          flex: 2,
          margin: 10,
          backgroundColor: 'red',
          elevation: 1,
        },
        View2: {
          position: 'absolute',
          backgroundColor: 'orange',
          zIndex: 3,
          elevation: 3,
        },
        View3: {
          flex: 3,
          backgroundColor: 'green',
          elevation: 2,
        },
        Text: {
          fontSize: 25,
          margin: 20,
          color: 'white',
        },
      });
      
      class Example extends Component {
      
        constructor(props) {
          super(props);
      
          this.state = {
            view2LayoutProps: {
              left: 0,
              top: 0,
              width: 50,
              height: 50,
            }
          };
        }
      
        onLayout(event) {
          const {x, y, height, width} = event.nativeEvent.layout;
          const newHeight = this.state.view2LayoutProps.height + 1;
          const newLayout = {
              height: newHeight ,
              width: width,
              left: x,
              top: y,
            };
      
          this.setState({ view2LayoutProps: newLayout });
        }
      
        render() {
          return (
            <View style={styles.container}>
              <View style={styles.View1}>
                <Text>{this.state.view2LayoutProps.height}</Text>
              </View>
              <View onLayout={(event) => this.onLayout(event)} 
                    style={[styles.View2, this.state.view2LayoutProps]} />
              <View style={styles.View3} />
            </View>
          );
        }
      
      }
      
      
      AppRegistry.registerComponent(Example);
      

      您可以创建更多修改方式的变体,方法是在另一个组件中使用它,该组件具有另一个视图作为包装器,并创建一个 onResponderRelease 回调,它可以将触摸事件位置传递给状态,然后可以传递将子组件作为属性,可以覆盖 onLayout 更新状态,通过放置{[styles.View2, this.state.view2LayoutProps, this.props.touchEventTopLeft]} 等等。

      【讨论】:

        【解决方案4】:

        也许你可以使用measure:

        measureProgressBar() {
            this.refs.welcome.measure(this.logProgressBarLayout);
        },
        
        logProgressBarLayout(ox, oy, width, height, px, py) {
          console.log("ox: " + ox);
          console.log("oy: " + oy);
          console.log("width: " + width);
          console.log("height: " + height);
          console.log("px: " + px);
          console.log("py: " + py);
        }
        

        【讨论】:

        • 我这辈子都不知道如何正确使用NativeMethodsMixin。不管我做什么,measure 总是未定义的。有什么指点吗?
        • 您不需要使用NativeMethodsMixin,该功能仅在某些元素上可用。例如TouchableWithFeedback 确实具有测量功能,但普通的Touchable 没有。尝试更改您正在使用的 View 的类型,获取 ref 并检查 measure 元素是否可用。我也偶然发现了这一点。
        【解决方案5】:

        您可以通过onLayoutprops轻松获取View的大小。

        import React from 'react'
        import { View } from 'react-native'
        
        export default function index() {
          const onLayout=(event)=> {
            const {x, y, height, width} = event.nativeEvent.layout;
            
          }
          return (
            <View onLayout={onLayout}>
              <OtherComponent />
            </View>
          )
        }
        
        

        每当调整视图大小时,也会调用onLayout 处理程序。

        主要需要注意的是,onLayout 处理程序会在您的组件安装后的一帧中首先调用,因此您可能希望在计算完布局之前隐藏您的 UI。

        【讨论】:

          【解决方案6】:

          您可以直接使用Dimensions 模块并计算您的视图大小。 实际上,Dimensions 提供了主窗口大小。

          import { Dimensions } from 'Dimensions';
          
          Dimensions.get('window').height;
          Dimensions.get('window').width;
          

          希望能帮到你!

          更新:今天使用原生 StyleSheetFlex 在您的视图上排列有助于编写简洁的代码,并在广泛的情况下使用优雅的布局解决方案,而不是计算您的视图大小。 .

          虽然构建一个自定义网格组件,它响应主窗口调整大小事件,但可以在简单的小部件组件中产生一个很好的解决方案

          【讨论】:

          • 这就是我要找的。谢谢!
          • 呸,为什么没有更清楚地记录下来!?!我正在尝试使用 'width' 和 'height' 而不是 ('window').width 等。
          • @MarkAmery 带有窗口尺寸,您可以规划视图的外观
          • @BrunoGuerra 你能显示代码以按维度获取特定视图(而不是窗口)大小吗?
          • 旋转设备时,许多设备上的尺寸不会更新。这是一个已知的issue,似乎从 react-native 0.32.0-rc.0 开始没有修复
          【解决方案7】:

          对我来说,将尺寸设置为使用 % 对我有用 width:'100%'

          【讨论】:

            【解决方案8】:

            这里是获取设备完整视图尺寸的代码。

            var windowSize = Dimensions.get("window");

            像这样使用它:

            width=windowSize.width,heigth=windowSize.width/0.565

            【讨论】:

            • 这没关系,但它不能回答问题。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-08-11
            • 2015-10-14
            • 1970-01-01
            • 2015-06-11
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多