Получите размер представления в React Native

156

Можно ли получить размер (ширину и высоту) определенного вида? Например, у меня есть представление, показывающее прогресс:

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

Мне нужно знать фактическую ширину представления, чтобы правильно выровнять другие представления. Это возможно?

Мэтью
источник

Ответы:

329

Начиная с React Native 0.4.2, компоненты View имеют onLayoutсвойство . Передайте функцию, которая принимает объект события. Событие nativeEventсодержит макет представления.

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

onLayoutОбработчик также будет вызываться всякий раз , когда представление изменяет размер.

Главное предостережение заключается в том, что onLayoutобработчик сначала вызывается через один кадр после того, как ваш компонент смонтирован, поэтому вы можете скрыть свой пользовательский интерфейс, пока не вычислите свой макет.

язь
источник
2
Проблема этого подхода заключается в том, что когда устройство вращается / изменяется размер просмотра, я не вызываю onLayout снова.
Мэтью
4
onLayout вызывается при изменении кадра представления. Возможно, ваш вид не меняет свой размер или положение при повороте. Посмотрите на пример onLayout в UIExplorer, где onLayout вызывается при вращении.
ide
2
Допустим, я хочу отображать по- Viewразному в зависимости от размеров. Я не понимаю, как я могу использовать onLayoutфункцию View, чтобы изменить способ отображения View. Разве это не приводит к бесконечному циклу?
Лейн Реттиг,
2
@LaneRettig Да, это так, если это действительно то, что вы хотите сделать, тогда вы должны написать свой код таким образом, чтобы достичь статического равновесия. Но похоже, что вы можете просто настроить вид на основе размеров экрана, и в этом случае onLayoutэто не имеет отношения.
ide
7
@ide, как бы вы скрыли пользовательский интерфейс, пока не будет вычислен макет?
Irfanlone
29

Это единственное, что у меня сработало:

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);
Абхишек Кумар
источник
15

В основном, если вы хотите установить размер и изменить его, установите его в состояние на макете следующим образом:

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, который может передать местоположение события касания в состояние, которое затем может быть передано дочернему компоненту as свойство, которое может переопределить обновленное состояние onLayout путем размещения {[styles.View2, this.state.view2LayoutProps, this.props.touchEventTopLeft]}и т. д.

Джуслинтек
источник
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вы используете, получите ссылку и проверьте, доступен ли элемент меры. Я тоже наткнулся на это.
n0rm
5

Вы можете напрямую использовать Dimensionsмодуль и рассчитывать размеры ваших просмотров. Собственно, Dimensionsдаю вам размеры главного окна.

import { Dimensions } from 'Dimensions';

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

Надеюсь помочь вам!

Обновление : Сегодня использование нативным StyleSheetс Flex организации на ваших взгляды помогают писать чистый код с элегантными решениями компоновок в широких случаях вместо вычислительных ваших размеров вида ...

Хотя создание настраиваемых компонентов сетки , которые реагируют на события изменения размера главного окна, может дать хорошее решение в простых компонентах виджетов.

Бруно Герра
источник
3
Ага, а почему это не документировано более четко!?! Я пробовал 'width' и 'height' вместо ('window').
300
В приведенном вами примере представлены размеры окна , а не данного представления; как это актуально?
Марк Эмери
1
@MarkAmery с размерами окон, которые вы можете спланировать, как будут выглядеть ваши взгляды,
Бруно Герра,
2
@BrunoGuerra, можете ли вы показать код, чтобы получить определенный размер представления (не окна) по размерам?
Spark.Bao,
4
Размеры не обновляются на многих устройствах при повороте устройства. Это известная проблема, и, похоже, она не исправлена ​​в react-native 0.32.0-rc.0
Гленн Лоуренс,
-4

Вот код, чтобы получить размеры полного вида устройства.

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

Используйте это так:

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

рави
источник
Это нормально, но не отвечает на вопрос.
Мосо Акиньеми
-4

для меня установка размеров для использования% - это то, что сработало для меня width:'100%'

pinchez254
источник