Ottieni le dimensioni di una vista in React Native


147

È possibile ottenere le dimensioni (larghezza e altezza) di una determinata vista? Ad esempio, ho una vista che mostra l'avanzamento:

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

Devo conoscere la larghezza effettiva della vista per allineare correttamente le altre viste. È possibile?

Risposte:


315

A partire da React Native 0.4.2, i componenti di visualizzazione hanno un onLayoutprop . Passa una funzione che accetta un oggetto evento. L'evento nativeEventcontiene il layout della vista.

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

Il onLayoutgestore verrà inoltre richiamato ogni volta che la vista viene ridimensionata.

L'avvertenza principale è che il onLayoutgestore viene prima invocato un frame dopo che il componente è stato montato, quindi potresti voler nascondere la tua interfaccia utente fino a quando non hai calcolato il layout.


2
Il problema di questo approccio è quando il dispositivo ruota / visualizza le modifiche alle dimensioni, non riesco a richiamare.
Matteo,

4
onLayout viene richiamato quando cambia il frame della vista. Forse la tua vista non cambia le sue dimensioni o posizione sulla rotazione. Guarda l'esempio onLayout in UIExplorer, dove onLayout viene invocato al momento della rotazione.
ide

2
Diciamo che voglio visualizzare un Viewdiverso in base alle dimensioni. Non capisco come posso usare la onLayoutfunzione della vista per cambiare la modalità di visualizzazione della vista. Ciò non porta a un ciclo infinito?
Lane Rettig,

2
@LaneRettig Sì, lo fa se questo è davvero ciò che vuoi fare, allora dovresti scrivere il tuo codice in modo da raggiungere l'equilibrio statico. Ma sembra che potresti voler personalizzare la vista in base alle dimensioni dello schermo, nel qual caso onLayoutnon è correlato.
ide

7
@ide come nasconderesti l'interfaccia utente fino al calcolo del layout?
Irfanlone,

27

Questa è l'unica cosa che ha funzionato per me:

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

Fondamentalmente se si desidera impostare le dimensioni e modificarlo, impostarlo in modo che sia come segue:

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

È possibile creare molte più varianti di come dovrebbe essere modificato, utilizzandolo in un altro componente che ha un'altra vista come wrapper e creare un callback onResponderRelease, che potrebbe passare la posizione dell'evento touch nello stato, che potrebbe quindi essere passata al componente figlio come proprietà, che potrebbe sovrascrivere lo stato aggiornato di onLayout, posizionando {[styles.View2, this.state.view2LayoutProps, this.props.touchEventTopLeft]}e così via.


11

È possibile utilizzare direttamente il Dimensionsmodulo e calcolare le dimensioni delle visualizzazioni. In realtà, ti Dimensionsdarò le dimensioni della finestra principale.

import { Dimensions } from 'Dimensions';

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

Spero di aiutarti!

Aggiornamento : oggi l'utilizzo nativo StyleSheetcon Flex che organizza le tue viste aiuta a scrivere codice pulito con eleganti soluzioni di layout in grandi casi invece di calcolare le dimensioni delle tue viste ...

Sebbene la creazione di una griglia personalizzata componenti , che risponde agli eventi di ridimensionamento della finestra principale, possa produrre una buona soluzione in semplici componenti widget


3
Gah, perché questo non è documentato più chiaramente!?! Stavo provando 'larghezza' e 'altezza' invece di ('finestra'). Larghezza ecc.

272
L'esempio che hai fornito fornisce le dimensioni della finestra , non di una data vista; come è rilevante?
Mark Amery,

1
@MarkAmery con dimensioni della finestra puoi pianificare come appariranno le tue opinioni
Bruno Guerra,

2
@BrunoGuerra puoi mostrare il codice per ottenere una certa dimensione della vista (non una finestra) per Dimensioni?
Spark.Bao,

4
Le dimensioni non vengono aggiornate su molti dispositivi quando il dispositivo viene ruotato. Questo è un problema noto e non sembra essere stato risolto con la reazione nativa 0.32.0-rc.0
Glenn Lawrence

10

Forse puoi usare 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);
}

Per la mia vita non riesco a capire come usare correttamente NativeMethodsMixin. Non importa quello che faccio, measureè sempre indefinito. Qualche puntatore?
chandlervdw,

2
Non è necessario utilizzare NativeMethodsMixinla funzione è disponibile solo su alcuni elementi. Ad esempio TouchableWithFeedbackha la funzione di misura, ma un normale Touchableno. Prova a cambiare il tipo di dispositivo Viewche stai utilizzando, ottieni il riferimento e controlla se l'elemento misura è disponibile. Mi sono imbattuto anche in questo.
n.

-3

per me impostare le dimensioni per usare% è ciò che ha funzionato per me width:'100%'


-4

Ecco il codice per ottenere le dimensioni della vista completa del dispositivo.

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

Usalo in questo modo:

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


Va bene, ma non risponde alla domanda.
Moso Akinyemi,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.