在 React Native 中获取视图的大小

问题描述 投票:0回答:10

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

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

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

ios react-native
10个回答
511
投票

从 React Native 0.4.2 开始,View 组件有一个

onLayout
prop。传入一个接受事件对象的函数。事件的
nativeEvent
包含视图的布局。

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

每当调整视图大小时,也会调用

onLayout
处理程序。

主要需要注意的是,

onLayout
处理程序在组件安装后的一帧内首先被调用,因此您可能需要隐藏 UI,直到计算出布局。


42
投票

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

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

32
投票

您可以通过

View
props
轻松获取onLayout的大小。

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,直到计算出布局。


18
投票

基本上,如果您想设置大小并使其更改,则将其设置为布局状态,如下所示:

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 更新状态。


13
投票

也许你可以使用

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

3
投票

我创建了这个简单的组件

import React, {Dispatch, SetStateAction} from 'react';
import {View, ViewProps} from 'react-native';

interface GetDimensionsProps {
  children: React.ReactNode | React.ReactNode[];
  onDimensions: Dispatch<SetStateAction<{height: number; width: number}>>;
  viewProps?: ViewProps;
}

export const GetDimensions: React.FC<GetDimensionsProps> = ({
  children,
  onDimensions,
  ...viewProps
}: GetDimensionsProps) => {
  return (
    <View
      onLayout={event =>
        onDimensions({
          width: Math.round(event.nativeEvent.layout.width),
          height: Math.round(event.nativeEvent.layout.height),
        })
      }
      {...viewProps}>
      {children}
    </View>
  );
};

// ────────────────────────────────────────────────────────────────────────────────
// usage

// const [dimensions, setDimensions] = useState<{
//   height: number;
//   width: number;
// }>({width: 0, height: 0});
//
// <GetDimensions onDimensions={setDimensions}>
//  {children}
// </GetDimensions>

1
投票

是的,你可以通过 onLayout prop 来实现这一点

const [progress, setProgress] = useState(0.5); // Example progress value
  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
  const progressBarRef = useRef(null);

  const onLayout = event => {
    const { width, height } = event.nativeEvent.layout;
    setDimensions({ width, height });
  };

那么你的观点应该是这样的

 <View style={styles.container}>
      <View
        ref={progressBarRef}
        style={[styles.progressBar, { flex: progress }]}
        onLayout={onLayout}
      />
      <Text>Progress Bar Width: {dimensions.width}</Text>
      <Text>Progress Bar Height: {dimensions.height}</Text>
    </View>

还有这样的风格

container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  progressBar: {
    backgroundColor: 'red',
    height: 20,
    alignSelf: 'stretch',
  },

您也可以在expo零食中查看完整代码

展会链接


-9
投票

对我来说,将尺寸设置为使用%对我有用

width:'100%'


-10
投票

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

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

像这样使用它:

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


-11
投票

您可以直接使用

Dimensions
模块并计算视图尺寸。 实际上,
Dimensions
为您提供了主窗口尺寸。

import { Dimensions } from 'Dimensions';

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

希望能帮到你!

更新:今天使用本机

StyleSheet
Flex排列您的视图有助于在广泛的情况下使用优雅的布局解决方案编写干净的代码,而不是计算视图大小...

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

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