在React Native中获取视图的大小


147

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

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

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

Answers:


315

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

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

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

主要警告是,在onLayout安装组件后一帧首先调用处理程序,因此您可能希望隐藏UI,直到计算出布局为止。


2
这种方法的问题是当设备旋转/改变视图大小时,我不会再次调用onLayout。
马修2015年

4
当视图的框架更改时,将调用onLayout。也许您的视图不会改变其大小或旋转位置。查看UIExplorer中的onLayout示例,该示例在旋转时调用onLayout。
ide 2015年

2
假设我要View根据尺寸显示不同的内容。我不明白如何使用View的onLayout功能来更改View的显示方式。这不是导致无限循环吗?
Lane Rettig

2
@LaneRettig是的,如果确实要执行此操作,则应以达到静态平衡的方式编写代码。但这听起来好像您可能只想根据屏幕尺寸自定义视图,在这种情况下onLayout是不相关的。
ide 2016年

7
@ide在计算布局之前,如何隐藏UI?
Irfanlone

27

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

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

14

基本上,如果您要设置尺寸并进行更改,则将其设置为如下所示的布局状态:

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回调,从而将触摸事件的位置传递到状态中,然后将其传递给子组件,从而创建更多的修改方式。作为属性,可以通过放置{[styles.View2, this.state.view2LayoutProps, this.props.touchEventTopLeft]}等方式覆盖onLayout更新后的状态。


11

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

import { Dimensions } from 'Dimensions';

Dimensions.get('window').height;
Dimensions.get('window').width;

希望对您有所帮助!

更新:今天StyleSheetFlex中使用本机,可以在很大的情况下使用优雅的布局解决方案来编写清晰的代码,而不用计算视图大小...

尽管构建响应主窗口调整大小事件的自定义网格组件,可以在简单的窗口小部件组件中产生良好的解决方案


3
Gah,为什么没有对此做更清晰的记录!?!我试图“宽度”与代替“高度”(“窗口”)的宽度等。

272
您提供的示例提供的是窗口的尺寸,而不是给定视图的尺寸。这有什么关系?
Mark Amery 2015年

1
@MarkAmery具有窗口尺寸,您可以规划视图的外观
Bruno Guerra

2
@BrunoGuerra您可以显示代码以按尺寸获取特定视图(而非窗口)大小吗?
Spark.Bao

4
旋转设备时,许多设备上的尺寸不会得到更新。这是一个已知的问题,从react-native 0.32.0-rc.0起似乎没有得到解决
Glenn Lawrence

10

也许您可以使用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始终是不确定的。有指针吗?
chandlervdw

2
您不需要使用NativeMethodsMixin仅在某些元素上可用的功能。例如,TouchableWithFeedback确实具有测量功能,而常规则Touchable没有。尝试更改View您正在使用的类型,获取参考并检查measure元素是否可用。我也偶然发现了这一点。
n0rm

-3

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


-4

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

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

像这样使用它:

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


可以,但是不能回答问题。
Moso Akinyemi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.