React Native : 요소의 위치 얻기


79

Image꽤 잘 작동하는 화면 중앙에 플렉스 박스로 구성 요소를 스타일링하고 있습니다. 이제 두 번째 Image구성 요소를 첫 번째 구성 요소의 맨 위에 직접 표시 하고 싶습니다 . 두 번째 이미지는 절대 위치 지정을 사용합니다. 현재 저는 픽셀이 맞도록 추측하고 있지만 물론 이것은 정확하지 않고 유지 관리 작업이 너무 많습니다.

나는 jQuery의 .offset(). 그런 일이 있고 이것을 달성하는 가장 좋은 방법이 없다면?

답변:


103

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()가 호출 되기 전에 렌더링 이 완료되지 않는 경우 가 있습니다. 에서 결과로 0을 얻는 경우 a measure(...)로 래핑 setTimeout하면 문제가 해결됩니다. 즉,

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

4
이 호출 방법은 measure나를 위해 작동하지 않았습니다. 요소 핸들을 전달해야했습니다.const handle = findNodeHandle(this.refs.dropdown); UIManager.measure(handle, (x, y, ...) ...)
Brock

setImmediate (...)는 이제 setTimeout (..., 0)을 대체하기 위해 존재합니다. 동작은 동일하지만 호출 타이밍에 대한 몇 가지 의미를 제공합니다.
JesusTheHun

@tohster 처음으로 스크롤이 올바른 위치로 이동합니다. 그러나 그 이후에는 페이지 값에 대한 Y 오프셋이 올바르지 않습니다. 왜 그런지 아십니까?
Balasubramanian

onLayout이이 작업을 수행하는 데 선호되는 방법
hakazvaka

Android에서 작동합니까? 나는 부모에 대한 상대적인 위치 (fy)를 얻고 0을 얻으려고 노력했습니다. ios에서 잘 작동합니다.
Victor Molina

60

를 사용 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필요가 없다는 장점이 있지만, 상대적으로 오프셋을 제공하지 않는다는 단점이 있습니다. 전체 페이지, 요소의 부모와 관련된 페이지 만.


17
당신은 답변을 결합 할 수 있습니다-onLayout 호출 measure ()
Juozas 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.measureLayoutRelativeToParentA의 setTimeout당신이 구성 요소의 한 지점에서이 코드를 실행하는 경우 밖으로 erroring 것을 방지하기 위해 호출이 렌더링 된 이전의 라이프 사이클. 또한 최신 React Native import { UIManager, findNodeHandler } from 'react-native'의 경우 여기에 표시된 요구 사항보다 수행 하기를 원할 것입니다.
마크 Amery

1
UIManager그리고 findNodeHandle지금은 "반응 네이티브"에서 직접 가져올 수 있습니다. 즉,import { UIManager, findNodeHandle} from "react-native"
HBSKan

20

비슷한 문제가 있었고 위의 답변을 결합하여 해결했습니다.

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입니다.
Mislavoo7

@jsparks feedPost 클래스 이름은 다음과 같습니다 클래스 FeedPost
리 카드

이 후크 유일한 방법을 사용할 때 페이지 또는 화면 X / Y 위치를 얻을 것으로 효과
Kerkness

3

이것은 refs를 사용하여 계산할 때 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; ._componentReact Native 0.51 (현재 최신 릴리스,이 답변을 게시하기 3 일 전에 릴리스 됨)에서 사용할 필요성을 재현 할 수 없습니다 . 당신이 그것을 어디서 얻는 지 확실하지 않습니다. 저에게 ref콜백에 대한 첫 번째 인수 는 메서드 있는 구성 요소입니다 .measure.
마크 Amery

2
예를 들어 Animated.View대신 사용하는 경우 @MarkAmery가 필요합니다 View.
elzi

1

이 기능의 구성 요소를 사용하고를 사용하지 않는 경우 forwardRef구성 요소의 측정하는 절대 레이아웃을, 당신은에서에 대한 참조 얻을 수 LayoutChangeEvent에서 onLayout콜백을.

이렇게 하면 요소 의 절대 위치를 얻을 수 있습니다 .

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

React Native 0.63.3으로 테스트되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.