最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to get the position of a component on screen in react native? - Stack Overflow

programmeradmin0浏览0评论

I am working on a react native app and I want to handle touches on screen.

One use case is when the user "press" on screen, I want to be able to get the position (x,y) of a specific component on screen to know if it matches the (x,y) of the touch.

I've searched already on stack overflow, but none of the given solutions worked...

In my root component:

_onPress = () => {
    // How can I get the position of my component ?
    this._myComponent.xxx();
};

render() {
    return (
        <View><MyComponent ref={(r) => this._myComponent = r;} /></View>
    );
}

EDIT: After trying this solution (React Native: Getting the position of an element) I made it work as follow:

In MyComponent.js:

getPosition () => {
    this._ref._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)
    });
};

render() {
    return (
        <View ref={(r) => { this._ref = r;} } />
    );
}

Thanks for your help!

I am working on a react native app and I want to handle touches on screen.

One use case is when the user "press" on screen, I want to be able to get the position (x,y) of a specific component on screen to know if it matches the (x,y) of the touch.

I've searched already on stack overflow, but none of the given solutions worked...

In my root component:

_onPress = () => {
    // How can I get the position of my component ?
    this._myComponent.xxx();
};

render() {
    return (
        <View><MyComponent ref={(r) => this._myComponent = r;} /></View>
    );
}

EDIT: After trying this solution (React Native: Getting the position of an element) I made it work as follow:

In MyComponent.js:

getPosition () => {
    this._ref._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)
    });
};

render() {
    return (
        <View ref={(r) => { this._ref = r;} } />
    );
}

Thanks for your help!

Share Improve this question edited Nov 24, 2017 at 11:01 Alexis Santini asked Nov 24, 2017 at 10:31 Alexis SantiniAlexis Santini 3311 gold badge3 silver badges17 bronze badges 2
  • stackoverflow.com/a/32751446/1287643 – rishat Commented Nov 24, 2017 at 10:37
  • I've tried this solution and it doesn't work in my app for some reason, I don't really know why... – Alexis Santini Commented Nov 24, 2017 at 10:56
Add a comment  | 

4 Answers 4

Reset to default 5

For an example in a functional component using useRef in React Native:

const BoardSquare = props => {
  const squareRef = useRef(null);

  console.log('squareRef', squareRef);

  const doMeasure = square => {
    squareRef.current.measure((width, height, px, py, fx, fy) => {
      const location = {
        fx: fx,
        fy: fy,
        px: px,
        py: py,
        width: width,
        height: height,
      };
      console.log('location', location);
      square.x = fx;
      square.y = fy;
      square.xMax = fx + px;
      square.yMax = fy + py;
    });
  };

  return (
    <Square
      {...props}
      ref={squareRef}
      filled={props.square.filled}
      onLayout={() => doMeasure(props.square)}
    />
  );
};

React Native

You can use .measure():

this._myComponent._component.measure((width, height, px, py, fx, fy) => {
  // do positioning checks here
}

Determines the location on screen, width, and height of the given view and returns the values via an async callback. If successful, the callback will be called with the following arguments: x, y, width, height, pageX, pageY.

Docs: https://facebook.github.io/react-native/docs/direct-manipulation.html#other-native-methods


Web API (no React Native)

If you're working with a DOM node, you can use Element.getBoundingClientRect():

let domRect = this._myComponent.getBoundingClientRect();
let { x, y } = domRect;

The result is the smallest rectangle which contains the entire element, with read-only left, top, right, bottom, x, y, width, and height properties describing the overall border-box in pixels. Properties other than width and height are relative to the top-left of the viewport.

Docs: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect

I tend to use both onLayout and the react native Dimensions to get the latest layout, dimensions or positions across web and mobile, especially with web having the ability to resize the window.

import { useRef, useState, useCallback, useEffect } from 'react'
import { View, Dimensions } from 'react-native'

const viewRef = useRef<View>(null)
const [layout, setLayout] = useState<any>(null)

const measureLayout = useCallback(() => {
    viewRef.current?.measure((
        x, y,
        width, height,
        pageX, pageY
    ) => {
       setLayout({
           x, y,
           width, height,
           pageX, pageY
       })
    })
}, [])

useEffect(() => {
    const sub = Dimensions.addEventListener(
        'change',
        ({window,screen}) => {
            measureLayout()
        }
    )
    return () => sub?.remove()
}, [])

return (
    <View
        ref={viewRef}
        onLayout={measureLayout}
    />
)

Another option is to use onLayout. Example

const [viewHeight, setViewHeight] = React.useState(0);
return (
  <View
    onLayout={e => {
      e.persist();
      setViewHeight(e && e.nativeEvent ? e.nativeEvent.layout.height : 0);
    }}
  />
);

A more in-depth example

Documentation of LayoutEvent

发布评论

评论列表(0)

  1. 暂无评论