React Native: получение позиции элемента

Я создаю компонент Image с flexbox, чтобы быть в центре экрана, который работает очень хорошо. Теперь я хочу, чтобы второй компонент Image отображался непосредственно в верхней части первой. На втором изображении используется абсолютное позиционирование. В настоящее время я просто угадываю пиксели так, чтобы он соответствовал, но, конечно, это неточно и слишком много усилий по поддержке.

Я в значительной степени искал коренной эквивалент React для jQuery .offset(). Есть ли такая вещь, и нет ли лучшего способа достичь этого?

Ответ 1

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 )
    

Ответ 2

Мне нужно было найти позицию элемента внутри 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

Это, похоже, изменилось в последней версии React Native при использовании refs для вычисления.

Объявлять ссылки таким образом.

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

Ответ 4

Вы можете использовать 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, чтобы убедиться, что измерения доступны, но недостаток, заключающийся в том, что он не дает вам относительных смещений по страницам, только относительные к кадру.

Ответ 5

Чтобы получить информацию о любом элементе, вы можете просто показать инспектора.

Откройте режим отладки (на симуляторе iOS в разделе "Аппаратное обеспечение" ) "Встряхните жест":

Реальный режим отладки

Это похоже на веб-DOM-инспектор, вы можете выбирать слои и видеть свойства стиля, а также позиции.

Реагировать с инсайдером