web-dev-qa-db-ja.com

React Native:要素の位置を取得する

Imageコンポーネントをflexboxでスタイリングして、画面の中央に配置します。ここで、2番目のImageコンポーネントを最初のコンポーネントの上に直接表示する必要があります。 2番目の画像は絶対配置を使用しています。現在、私はピクセルが収まるように推測していますが、もちろんこれは正確ではなく、メンテナンスの手間がかかりすぎます。

JQueryの.offset()と同等のReact Nativeを探しています。そのようなことはありますか、そしてこれを達成するための最良の方法が何もないのですか?

53
Johannes Stein

React Nativeは .measure(...) メソッドを提供します。このメソッドはコールバックを取得し、コンポーネントのオフセットと幅/高さで呼び出します:

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

例...

以下は、レンダリング後のカスタムコンポーネントのレイアウトを計算します。

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

バグノート

  • componentDidMount()が呼び出される前に、コンポーネントがレンダリングを完了しない場合があることに注意してください。 measure(...)の結果としてゼロを取得している場合、それをsetTimeoutでラップすると問題が解決します。

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

onLayout を使用して、コンポーネントの幅、高さ、およびrelative-to-parent位置を取得することができますそれらが利用可能であること:

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

受け入れられた答えに示されているように.measure()を使用 と比較すると、これにはsetTimeoutを使用して.measure()呼び出しを延期する必要がないという利点がありますが、ページ全体に対するオフセットは提供されず、要素の親に対するオフセットのみが提供されます。

28
Mark Amery

ListView内の要素の位置を見つける必要があり、.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);
  });

これは、コンポーネントにref='myElement'があることを前提としています。

18
Mr Speaker

同様の問題があり、上記の回答を組み合わせて解決しました

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

これで、ログでfeedPost要素の位置を確認できます。

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

Refを使用して計算する場合、これはReact Nativeの最新バージョンで変更されたようです。

この方法でrefを宣言します。

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

そして、この方法で値を見つけます。

  _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