React Native:获取元素的位置


78

我正在Image用flexbox设置组件的样式,使其位于屏幕中央,效果很好。现在,我希望第二个Image组件直接显示在第一个组件的顶部。第二个图像使用绝对定位。目前,我只是在猜测像素是否适合它,但是当然这是不准确的,并且在可维护性方面付出了太多努力。

我正在寻找与jQuery等效的React Native .offset()。有这样的事情吗?如果没有,实现这一目标的最佳方法是什么?

Answers:


100

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 )
    

4
这种调用方式measure对我不起作用。必须通过元素句柄:const handle = findNodeHandle(this.refs.dropdown); UIManager.measure(handle, (x, y, ...) ...)
布罗克

现在存在setImmediate(...)来代替setTimeout(...,0)。它具有相同的行为,但在您的通话时间方面提供了一些语义。
JesusTheHun

@tohster第一次滚动到正确位置。但是之后,Y偏移到页面值是不正确的。你知道为什么会这样吗?
Balasubramanian

onLayout是执行此操作的首选方法
hakazvaka

在Android上可以使用吗?我试图获得相对于父母的位置(fy)并获得0。在ios上工作正常。
维克多·莫利纳

57

您可以用来在最早可用时获取组件onLayout的宽度,高度和相对父位置:

<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()已接受的答案中所示的方法相比,这样做的好处是您不必费力地推迟.measure()呼叫setTimeout以确保测量值可用,但是缺点是它不会给您相对于测量值的偏移量。整个页面,只有相对于元素父级的页面。


16
您可以将答案-在onLayout通话措施()
约扎斯Kontvainis

这比玩超时更简洁!
Night Warrier

22

我需要在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'我的组件上有一个。


3
请注意,与接受的答案一样,如果要在呈现组件之前从组件生命周期中的某个时刻执行此代码,则可能需要将该调用包装到UIManager.measureLayoutRelativeToParent一个setTimeout调用中,以防止其出错。还要注意,对于现代的React Native,您将想要做的import { UIManager, findNodeHandler } from 'react-native'而不是此处显示的要求。
Mark Amery

1
UIManager并且findNodeHandle现在可以直接从“ react-native”中导入。即import { UIManager, findNodeHandle} from "react-native"
HBSKan

19

我有一个类似的问题,并通过结合上面的答案解决了

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

1
this.feedPost变量从何而来?你在某处初始化它吗?运行我的应用程序时,我立即无法定义this.feedPost.measure函数
jsparks,

在返回部分的render方法中,我具有根视图: <View onLayout {(event) => {this.handleLayoutChange(event) }} ref={view => { this.feedPost = view; }} > .... 该主视图是this.feedPost。
Mislavoo19年

@jsparks feedPost是类名称:class FeedPost
Rickard

这是使用钩子时的效果,也是我发现获得页面或屏幕x / y位置的唯一方法
Kerkness,

3

使用引用进行计算时,这在最新版本的React Native中似乎已经改变。

以这种方式声明引用。

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

1
-1; 我无法满足需要._component在React Native 0.51中使用的要求(当前最新版本,发布此答案前三天发布)。不知道从哪里得到的?对我来说,ref回调的第一个参数带有.measure方法的组件。
Mark Amery

2
@MarkAmery你,如果你正在使用需要它Animated.View来代替View,例如。
elzi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.