React-native: Measuring a view without an onLayout returns an empty set of coordinates

Created on 6 Jun 2018  路  6Comments  路  Source: facebook/react-native

Description

Measuring an Android View using ref.measureInWindow returns an empty set of coordinates if the onLayout prop of the View is not set.
The issue arises only when the View wraps some specific component like TouchableWithoutFeedback, TouchableNativeFeedback and TouchableOpacity.

Environment

Environment:

  • OS: macOS High Sierra 10.13.4
  • Node: 9.9.0
  • Yarn: 1.5.1
  • npm: 6.0.1
  • Watchman: 4.6.0
  • Xcode: Xcode 9.3.1 Build version 9E501
  • Android Studio: 2.3 AI-162.4069837

Packages: (wanted => installed)

  • react: 16.3.1 => 16.3.1
  • react-native: ~0.55.2 => 0.55.4

Steps to Reproduce

Create a new app using CRNA/Expo and change App.js like this:

/* @flow */
import * as React from "react";
import { StyleSheet, TouchableNativeFeedback, View } from "react-native";

class AndroidMeasureTester extends React.Component<{}> {
  boxRef: ?View = null;

  handleButtonPress = () => {
    if (this.boxRef) {
      this.boxRef.measureInWindow((x, y, width, height) => {
        console.debug("RED BOX LAYOUT:");
        console.debug("x", x);
        console.debug("y", y);
        console.debug("width", width);
        console.debug("height", height);
      });
    }
  };

  render() {
    return (
      <View style={styles.container}>
        <View ref={ref => (this.boxRef = ref)} onLayout={undefined}>
          <TouchableNativeFeedback onPress={this.handleButtonPress}>
            <View style={styles.box} />
          </TouchableNativeFeedback>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    height: "100%",
    width: "100%",
    alignItems: "center",
    justifyContent: "center"
  },
  box: {
    width: 80,
    height: 80,
    backgroundColor: "red"
  }
});

export default AndroidMeasureTester;

I also created an Expo Snack.

Expected Behavior

Pressing the red square should always print the correct measures on consoles, even when its onLayout prop is undefined like in the example.
The correct printed layout should be something like:

06:25:31: RED BOX LAYOUT:
06:25:31: x 140
06:25:31: y 232
06:25:31: width 80
06:25:31: height 80

Actual Behavior

Pressing the red square prints the correct measures on consoles only when you set an onLayout (try setting onLayout={() => null} and you will see that it will works correctly).
If you don't se the onLayout, the result will be the following:

06:25:22: RED BOX LAYOUT:
06:25:22: x undefined
06:25:22: y undefined
06:25:22: width undefined
06:25:22: height undefined

## Image recap
touch-measrure-issue

Bug Locked

Most helpful comment

This is expected behaviour (tho maybe it's possible to print a warning to make it more explicit?). On Android, Views that are only used for layout are removed from the hierarchy to save memory and speed. You need to set collapsable prop to false in order to make it stay in the layout hierarchy and be measurable.

Setting onLayout (even empty callback) automatically disables this operation too.

All 6 comments

This is also happening in my end using react-native 0.56

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as "For Discussion" or "Good first issue" and I will leave it open. Thank you for your contributions.

It's still happening on [email protected]

@mmazzarolo Its not exactly that case, but I have similar problem. Is it possible to set onLayout directly through ref, and not with property in JSX?

I want to get ref to external component and show popup menu tied up / stick to external component. And update position of popup whenever position of external component changes.

Reproducible on [email protected] with or without onLayout!

This is expected behaviour (tho maybe it's possible to print a warning to make it more explicit?). On Android, Views that are only used for layout are removed from the hierarchy to save memory and speed. You need to set collapsable prop to false in order to make it stay in the layout hierarchy and be measurable.

Setting onLayout (even empty callback) automatically disables this operation too.

Was this page helpful?
0 / 5 - 0 ratings