React Native: Getting the position of an element

前端 未结 6 527
太阳男子
太阳男子 2020-11-28 03:08

I am styling an Image component with flexbox to be in the center of the screen which works pretty well. Now I want a second Image component to be d

相关标签:
6条回答
  • 2020-11-28 03:38

    This seems to have changed in the latest version of React Native when using refs to calculate.

    Declare refs this way.

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

    And find the value this way.

      _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)
        })
      }
    
    0 讨论(0)
  • 2020-11-28 03:40

    I needed to find the position of an element inside a ListView and used this snippet that works kind of like .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);
      });
    

    This assumes I had a ref='myElement' on my component.

    0 讨论(0)
  • 2020-11-28 03:45

    If you use function components and don't want to use a forwardRef to measure your component's absolute layout, you can get a reference to it from the LayoutChangeEvent in the onLayout callback.

    This way, you can get the absolute position of the element:

    <MyFunctionComp
      onLayout={(event) => {
        event.target.measure(
          (x, y, width, height, pageX, pageX) => {
            doSomethingWithAbsolutePosition({
              x: x + pageX, 
              y: y + pageY,
            });
          },
        );
      }}
    />
    

    Tested with React Native 0.63.3.

    0 讨论(0)
  • 2020-11-28 03:56

    I had a similar problem and solved it by combining the answers above

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

    Now I can see the position of my feedPost element in the logs:

    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
    
    0 讨论(0)
  • 2020-11-28 03:58

    React Native provides a .measure(...) method which takes a callback and calls it with the offsets and width/height of a component:

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

    Example...

    The following calculates the layout of a custom component after it is rendered:

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

    Bug notes

    • Note that sometimes the component does not finish rendering before componentDidMount() is called. If you are getting zeros as a result from measure(...), then wrapping it in a setTimeout should solve the problem, i.e.:

      setTimeout( myComponent.measure(...), 0 )
      
    0 讨论(0)
  • 2020-11-28 03:58

    You can use onLayout to get the width, height, and relative-to-parent position of a component at the earliest moment that they're available:

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

    Compared to using .measure() as shown in the accepted answer, this has the advantage that you'll never have to fiddle around deferring your .measure() calls with setTimeout to make sure that the measurements are available, but the disadvantage that it doesn't give you offsets relative to the entire page, only ones relative to the element's parent.

    0 讨论(0)
提交回复
热议问题