react-native icon indicating copy to clipboard operation
react-native copied to clipboard

.measure returns undefined on Android unless collapsable=false or onLayout are specified

Open evelant opened this issue 5 years ago • 28 comments
trafficstars

Description

If you call .measure on a ref to a View on Android but you don't also have onLayout or collapsable={false} specified then .measure will call its success callback with undefined.

This issue got closed but it was never fixed https://github.com/facebook/react-native/issues/3282 Seems it got reported again and was also closed without a fix https://github.com/facebook/react-native/issues/19103

The issue here is identical, a 5 year old bug! I suspect it's due to android removing "unnecessary" views when it shouldn't. If there's a ref the view should essentially have collapsable={false} automatically.

React Native version:

System:
    OS: Windows 10 10.0.20190
    CPU: (16) x64 AMD Ryzen 7 3700X 8-Core Processor
    Memory: 33.48 GB / 63.93 GB
  Binaries:
    Node: 10.18.1 - C:\dev\tools\nodejs\node.EXE
    Yarn: 1.22.4 - C:\dev\tools\nodejs\yarn.CMD
    npm: 6.14.7 - C:\dev\TaskHero\node_modules\.bin\npm.CMD
    Watchman: 4.9.4 - C:\dev\tools\watchman\watchman.EXE
  SDKs:
    Android SDK:
      API Levels: 28, 29
      Build Tools: 28.0.3, 29.0.3, 30.0.1
      System Images: android-24 | Google Play Intel x86 Atom, android-25 | Google APIs ARM EABI v7a, android-25 | Google APIs Intel x86 Atom_64, android-28 | Google Play Intel x86 Atom_64, android-29 | Google Play Intel x86 Atom_64, android-30 | Google APIs Intel x86 Atom_64, androi
d-R | Google Play Intel x86 Atom_64
      Android NDK: 21.0.6113669
  IDEs:
    Android Studio: Not Found
  Languages:
    Java: 12.0.2
    Python: 3.8.4
  npmPackages:
    @react-native-community/cli: ^4.10.1 => 4.10.1
    react: 16.13.1 => 16.13.1
    react-native: 0.63.2 => 0.63.2
  npmGlobalPackages:
    *react-native*: Not Found

Steps To Reproduce

Provide a detailed list of steps that reproduce the issue.

  1. Add a ref to a view on Android
  2. Call .measure on that ref, values returned are undefined

Expected Results

It should return the measurement results

Snack, code example, screenshot, or link to a repository:

Not needed, can be reproduced immediately on any react native android project of any version

evelant avatar Aug 20 '20 14:08 evelant

Thank you so much for this! I was looking for a solution, and setting collapsable={false} fixed it for me!

LogicAnalysis avatar Nov 07 '20 20:11 LogicAnalysis

collapsable={false} was a great workaround for me after upgrading to react-native 0.64.0, thank you @AndrewMorsillo

rrr3da avatar Mar 30 '21 10:03 rrr3da

Same issue here. Another quick solution that work : bind a noop function to the onLayout

JevFR avatar Jul 20 '21 09:07 JevFR

collapsable={false} worked for me too! Pity this is needed though. I agree with this:

If there's a ref the view should essentially have collapsable={false} automatically.

markymc avatar Oct 08 '21 07:10 markymc

Thank you @AndrewMorsillo. collapsable={false} worked for me.

ghost avatar Nov 03 '21 18:11 ghost

Thanks man. collapsable={false} worked for me.

xhirazi avatar Dec 17 '21 23:12 xhirazi

Thanks! collapsable={false} is working.

rrain0 avatar Mar 12 '22 05:03 rrain0

And instead of measure() better use onLayout={} View attribute (it works without collapsable={false}).

const onLayout = ({nativeEvent: {layout: { x, y, width:w, height:h }}}: LayoutChangeEvent) => {
    console.log('onLayout: ',x,y,w,h)
}
return <View onLayout={onLayout}></View>

rrain0 avatar Mar 12 '22 06:03 rrain0

And instead of measure() better use onLayout={} View attribute (it works without collapsable={false}).

const onLayout = ({nativeEvent: {layout: { x, y, width:w, height:h }}}: LayoutChangeEvent) => {
    console.log('onLayout: ',x,y,w,h)
}
return <View onLayout={onLayout}></View>

However onLayout doesn't provide pageX and pageY, so it's not a direct replacement. https://reactnative.dev/docs/direct-manipulation#measurecallback

markymc avatar Mar 12 '22 08:03 markymc

Hey, any updates on this issue? I got similar problem, but collapsible and empty onLayout are doing nothing. Still getting 0 and 0 for x and y values on android, but on ios works perfectly.

endlessqt avatar Apr 02 '22 01:04 endlessqt

Thank you very much! collapsable={false} work for me.

nguyenhoanglam avatar Jul 29 '22 03:07 nguyenhoanglam

Just going to bump this up - collapsable={false} works as expected, but seems like an unnecessary hack.

alexborton avatar Sep 26 '22 14:09 alexborton

Thank you for documenting this. Adding collapsable={false} has worked for me too.

lukearndt avatar Oct 04 '22 22:10 lukearndt

use pageX and pageY instead of x and y

bozaigao avatar Oct 29 '22 02:10 bozaigao

@bozaigao pageY will be undefined in these cases as well

iway1 avatar Nov 07 '22 15:11 iway1

pageX and x serves a bit different purposes, and I don't think I can replace it with pageX in my use-case. I'm also having the same issue as #4753 and collapsable=false didn't help.

BasixKOR avatar Dec 08 '22 05:12 BasixKOR

Tried different solutions (collapsible, requestAnimationFrame, etc), and it doesn't work for me Work around by wrapping measure with setTimeout 500ms now but I think it's not a proper fix

In my case:

  • I have a horizontal flat list
  • the component I want to measure in the renderItem

Only the first component measure has values in (x, y, width, height, pageX, pageY) The other components measure are undefined

The issue only occur on Android. IOS work fine

tranquan avatar Jan 17 '23 15:01 tranquan

any updates on this one?

ororsatti avatar Feb 19 '23 17:02 ororsatti

I've taken a closer look into this issue, and I'm assuming Yoga wasn't able to find the shadow node in case if the view has been flattened out (unsure about the word choice): https://github.com/facebook/react-native/blob/76bf71e2cc12cf0ca3d3e04ac898c4a62a9df400/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp#L584

BasixKOR avatar Jul 21 '23 01:07 BasixKOR

In my case the view was not visible on the screen when measure was called (the second page of a swiper). It worked after I move the view to the first page. Not totally satisfied with the solution though :/

quockhanhz176 avatar Aug 01 '23 18:08 quockhanhz176

Tried different solutions (collapsible, requestAnimationFrame, etc), and it doesn't work for me Work around by wrapping measure with setTimeout 500ms now but I think it's not a proper fix

In my case:

  • I have a horizontal flat list
  • the component I want to measure in the renderItem

Only the first component measure has values in (x, y, width, height, pageX, pageY) The other components measure are undefined

The issue only occur on Android. IOS work fine

Hey @tranquan did you find the solution for this if yes then please share with me

najil-12 avatar Sep 28 '23 09:09 najil-12

@najil-12 I just wait some timeout before call measure

tranquan avatar Sep 29 '23 13:09 tranquan

Tried different solutions (collapsible, requestAnimationFrame, etc), and it doesn't work for me Work around by wrapping measure with setTimeout 500ms now but I think it's not a proper fix

In my case:

  • I have a horizontal flat list
  • the component I want to measure in the renderItem

Only the first component measure has values in (x, y, width, height, pageX, pageY) The other components measure are undefined

The issue only occur on Android. IOS work fine

Try adding removeClippedSubviews={false} to the FlatList. RN defaults this to true for android.

rsmutch avatar Nov 17 '23 10:11 rsmutch

Thank you so much for this! I was looking for a solution, and setting collapsable={false} fixed it for me!

Here on december 2023, thanks, it worked for me, a View ref was giving me an undefined using .measure

FabianMontoya avatar Dec 19 '23 03:12 FabianMontoya

collapsable={false} does not work for me so I used onLayout as a trigger for the .measure

Xavier-Charles avatar Apr 23 '24 16:04 Xavier-Charles

Have other people's workarounds had success in getting x and y values to be anything other than 0?

Mookiies avatar May 16 '24 20:05 Mookiies