web-dev-qa-db-fra.com

React Natif: Obtenir la position d'un élément

Je suis en train de styler un composant Image avec flexbox pour le placer au centre de l'écran, ce qui fonctionne plutôt bien. Maintenant, je veux qu'un deuxième composant Image soit affiché directement au-dessus du premier. La deuxième image utilise le positionnement absolu. Actuellement, je ne fais que deviner les pixels pour les adapter, mais bien sûr, cela n’est pas précis et demande beaucoup trop de maintenabilité.

Je cherche à peu près l'équivalent React natif de .offset() de jQuery. Existe-t-il une telle chose et s'il n'y en a pas, quel est le meilleur moyen d'y parvenir?

53
Johannes Stein

React Native fournit une méthode .measure(...) qui prend un rappel et l'appelle avec les décalages et la largeur/hauteur d'un composant:

myComponent.measure( (fx, fy, width, height, px, py) => {

    console.log('Component width is: ' + width)
    console.log('Component height is: ' + height)
    console.log('X offset to frame: ' + fx)
    console.log('Y offset to frame: ' + fy)
    console.log('X offset to page: ' + px)
    console.log('Y offset to page: ' + py)
})

Exemple...

Ce qui suit calcule la mise en page d'un composant personnalisé après son rendu:

class MyComponent extends React.Component {
    render() {
        return <View ref={view => { this.myComponent = view; }} />
    }
    componentDidMount() {
        // Print component dimensions to console
        this.myComponent.measure( (fx, fy, width, height, px, py) => {
            console.log('Component width is: ' + width)
            console.log('Component height is: ' + height)
            console.log('X offset to frame: ' + fx)
            console.log('Y offset to frame: ' + fy)
            console.log('X offset to page: ' + px)
            console.log('Y offset to page: ' + py)
        })        
    }
}

Notes de bogue

  • Notez que parfois le composant ne termine pas le rendu avant que componentDidMount() ne soit appelé. Si vous obtenez des zéros à la suite de measure(...), alors le placer dans un setTimeout devrait résoudre le problème, à savoir:

    setTimeout( myComponent.measure(...), 0 )
    
72
tohster

Vous pouvez utiliser onLayout pour obtenir la largeur, la hauteur et la position relative à parent d'un composant au premier moment où ils sont disponibles:

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

Comparé à en utilisant .measure() comme indiqué dans la réponse acceptée , cela présente l’avantage que vous n’aurez jamais à vous occuper de reporter vos appels .measure() avec setTimeout pour vous assurer que les mesures sont disponibles, mais le désavantage est que cela ne vous donne pas de décalage par rapport à la page entière, mais par rapport au parent de l'élément.

28
Mark Amery

Je devais trouver la position d'un élément à l'intérieur d'un ListView et utiliser cet extrait qui fonctionne un peu comme .offset:

const UIManager = require('NativeModules').UIManager;
const handle = React.findNodeHandle(this.refs.myElement);
UIManager.measureLayoutRelativeToParent(
  handle, 
  (e) => {console.error(e)}, 
  (x, y, w, h) => {
    console.log('offset', x, y, w, h);
  });

Cela suppose que j'ai eu un ref='myElement' sur mon composant.

18
Mr Speaker

J'ai eu un problème similaire et l'ai résolu en combinant les réponses ci-dessus

class FeedPost extends React.Component {
  constructor(props) {
    ...
    this.handleLayoutChange = this.handleLayoutChange.bind(this);
  }


handleLayoutChange() {
    this.feedPost.measure( (fx, fy, width, height, px, py) => {
      console.log('Component width is: ' + width)
      console.log('Component height is: ' + height)
      console.log('X offset to page: ' + px)
      console.log('Y offset to page: ' + py)
    })
  }

  render {
    return(
      <View onLayout={(event) => {this.handleLayoutChange(event) }} 
      ref={view => { this.feedPost = view; }} >
...

Maintenant, je peux voir la position de mon élément feedPost dans les journaux:

08-24 11:15:36.838  3727 27838 I ReactNativeJS: Component width is: 156
08-24 11:15:36.838  3727 27838 I ReactNativeJS: Component height is: 206
08-24 11:15:36.838  3727 27838 I ReactNativeJS: X offset to page: 188
08-24 11:15:36.838  3727 27838 I ReactNativeJS: Y offset to page: 870
8
Mislavoo7

Cela semble avoir changé dans la dernière version de React Natif lorsque vous utilisez des références pour calculer.

Déclarez les arbitres de cette façon.

  <View
    ref={(image) => {
    this._image = image
  }}>

Et trouver la valeur de cette façon.

  _measure = () => {
    this._image._component.measure((width, height, px, py, fx, fy) => {
      const location = {
        fx: fx,
        fy: fy,
        px: px,
        py: py,
        width: width,
        height: height
      }
      console.log(location)
    })
  }
2
Brian F