React Native: Getting the position of an element
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 frommeasure(...)
, then wrapping it in asetTimeout
should solve the problem, i.e.:setTimeout( myComponent.measure(...), 0 )
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.
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: 15608-24 11:15:36.838 3727 27838 I ReactNativeJS: Component height is: 20608-24 11:15:36.838 3727 27838 I ReactNativeJS: X offset to page: 18808-24 11:15:36.838 3727 27838 I ReactNativeJS: Y offset to page: 870