Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] measure not returning values unless element has onLayout property #3282

Closed
oblador opened this issue Oct 8, 2015 · 43 comments
Closed
Assignees
Labels
Ran Commands One of our bots successfully processed a command. Resolution: Locked This issue was locked by the bot.

Comments

@oblador
Copy link
Contributor

oblador commented Oct 8, 2015

I have something similar to this:

handleSomething: function() {
  this._root.measure((ox, oy, width, height, px, py) => {
    console.log({ox, oy, width, height, px, py});
  });
},
render: function() {
  return (<View ref={component => this._root = component}>...</View>);
}

This code works flawlessly on iOS, but on android the measure callback will always be called with undefined arguments – unless I put an empty callback on the onLayout property.

@foghina
Copy link
Contributor

foghina commented Oct 21, 2015

@oblador what happens if, instead of logging arguments, you log ox, oy etc.?

@oblador
Copy link
Contributor Author

oblador commented Oct 21, 2015

@foghina: they log as undefined, logging arguments is just shorter to write.

@oblador
Copy link
Contributor Author

oblador commented Oct 21, 2015

@foghina
Copy link
Contributor

foghina commented Oct 21, 2015

@oblador I know about arguments, we just ran into this internally and it turned out arguments was wrong for some reason, but logging the arguments by name worked.

Can you try wrapping the measure call in requestAnimationFrame? E.g.:

this.requestAnimationFrame(() => {
  this._root.measure((ox, oy, width, height, px, py) => {
    console.log(arguments);
  });
});

@ide
Copy link
Contributor

ide commented Oct 21, 2015

@foghina "arguments" in an arrow function refers to the enclosing non-arrow function's arguments (same scoping as "this"). Maybe that was the issue you were seeing.

@foghina
Copy link
Contributor

foghina commented Oct 21, 2015

@ide that does not explain why it works on iOS :-/

@ide
Copy link
Contributor

ide commented Oct 21, 2015

There was a timing change with how iOS does measurement that may have fixed this issue. Haven't really looked into it in detail, but it might be related? aa62a5e

@oblador
Copy link
Contributor Author

oblador commented Oct 21, 2015

I've updated the issue to not confuse anybody. It works as expected on iOS for all I know, but not on android. Wasn't aware of arrow functions inheriting the arguments object, but it's unrelated to this issue.

@ide
Copy link
Contributor

ide commented Oct 21, 2015

@oblador does wrapping the call in a rAF callback help?

@oblador
Copy link
Contributor Author

oblador commented Oct 21, 2015

@ide haven't tried, but don't really understand why it would make a difference. handleSomething is supposed to be a Touchable* callback.

@ide
Copy link
Contributor

ide commented Oct 21, 2015

Yeah you're probably right.

@marcshilling
Copy link

I'm also experiencing this. Along with onLayout, I've found that setting renderToHardwareTextureAndroid={true} on the view also makes measure return values.

@chirag04
Copy link
Contributor

@oblador @marcshilling can you try collapsable: false prop on your view? Android may remove the view from hierarchy for optimization purpose.

I just ran into something similar.

https://facebook.github.io/react-native/docs/view.html#content

@sodik82
Copy link

sodik82 commented Apr 27, 2016

I have same problem and can confirm that using onLayout or collapsable={false} helps

@udfalkso
Copy link

@chirag04 collapsable: false helped for me, thanks.

@chirag04
Copy link
Contributor

@facebook-github-bot close

@ghost
Copy link

ghost commented May 20, 2016

@chirag04 tells me to close this issue. If you think it should still be opened let us know why.

@ghost ghost closed this as completed May 20, 2016
@ghost ghost added the Ran Commands One of our bots successfully processed a command. label May 20, 2016
@eremzeit
Copy link
Contributor

eremzeit commented Jul 8, 2016

FYI, I'm using 0.26.3 and this was still an issue. I had to add an empty onLayout before measure would return integers instead of just undefined.

@nickmaxwell10
Copy link

I am having trouble with this on iOS as well.

@eremzeit
Copy link
Contributor

Was this fixed in a more recent version? Using the unrelated properties onLayout or collapsable to force this functionality seems to me to be a hack rather than a fix. I know there are limited resources to fix things, but at least there could be something in the docs about it?

@JAStanton
Copy link
Contributor

JAStanton commented Aug 8, 2016

@chirag04 you closed this but it's actually not resolved.

  1. There are no docs
  2. There is no actual fix.

Also the y position (second argument) is always 0 if the element you are measuring is in a scroll view (with collapsable) . Joy.

@julien-rodrigues
Copy link

I can confirm the bug is still here

@minhmera
Copy link

minhmera commented Dec 29, 2016

i am using react native version 0.36 and got this issues on Android, but on iOS it work well
here is my code ,

this.refs.field.measure((x, y, width, height, px, py) => { console.log('---------- height ',height) )}

height is undefined
??
pls help me, many thanks

@luongvm
Copy link

luongvm commented Dec 31, 2016

setting collapsable={false} on a View solved this problem for me. I'm on 0.39.2

@dragonwong
Copy link
Contributor

@chirag04 collapsable={false} Thanks, it works!

@nhatho89
Copy link

I was still experiencing the issue with collapsable={false}.

What fixed it for me was adding onLayout={() => {}} instead.

@wschurman
Copy link
Contributor

Using measureLayout (relative to specific node) seemed to solve this for me.

@Altusvdm
Copy link

I was experiencing this issue on Views and managed to work around it by adding empty onLayout as suggested.

However now I am trying to measure a ScrollView and adding onLayout did not fix the issue. I managed to work around it by wrapping all the content of my ScrollView with a View, adding an empty onLayout to that View, and then measuring that View.

magrinj added a commit to magrinj/react-native-swipeable-view that referenced this issue May 22, 2017
magrinj added a commit to magrinj/react-native-swipeable-view that referenced this issue May 22, 2017
magrinj added a commit to magrinj/react-native-swipeable-view that referenced this issue May 22, 2017
@luisfuertes
Copy link

I have the same problem, but props arent undefined.

I have a listview with this rows:

  renderRow(rowData, sectionID, rowID) {
    return (
      <View
        style={{padding: 20, backgroundColor: rowData.color, marginHorizontal: 20, marginVertical: 10, alignItems: 'center'}}
        ref={(row) => this.rows[rowID] = row}
        collapsable={false}
        {...this.customPanResponder.panHandlers}
      >
        <Text>{rowData.text}</Text>
      </View>
    )
  }

With

    _.map(this.rows, row => {
          row.measure( (ox, oy, width, height, px, py) => console.log("ox: ", ox, " oy: ", oy, " height: ", height, " px: ", px, " py: ", py))
        })

On iOS measure logs:

ox:  20  oy:  10  height:  57  px:  20  py:  74
ox:  20  oy:  87  height:  57  px:  20  py:  151
ox:  20  oy:  164  height:  57  px:  20  py:  228

On Android measure logs:

ox:  0  oy:  0  height:  59  px:  20  py:  66
ox:  0  oy:  0  height:  59  px:  20  py:  145
ox:  0  oy:  0  height:  59  px:  20  py:  224

Why my oy on android is always 0?

@SteffeyDev
Copy link

I just found that on iOS, measuring a Text component nested in another Text component results in all 0's as well. Haven't tested on Android yet. Also noted that onLayout on a nested Text component is never called, very strange.

@luongvm
Copy link

luongvm commented Jun 24, 2017

@SteffeyDev I think it have something to do with the way they render nested Text Component. Basically they used attributed text on the outermost Text element and all the nested ones are parsed to be merged into the parent as 1 large text item. That's how I think it's on iOS.

@SteffeyDev
Copy link

@joturako That makes sense, and explains why I can't get layout information. If I have a large body of text in a scrollview, how would you recommend I find the position of a smaller portion so that I can scroll there? Or is there no way to do that?

@luongvm
Copy link

luongvm commented Jun 24, 2017

@SteffeyDev I think you have to write a custom component, for iOS for example you can look for more information on how to scroll a UITextView to a selection: [textView scrollRangeToVisible:[textView.text rangeOfString:@"Lorem ipsum"]];

@hramos
Copy link
Contributor

hramos commented Aug 31, 2017

Hi there! This issue is being closed because it has been inactive for a while. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. Either way, we're automatically closing issues after a period of inactivity. Please do not take it personally!

If you think this issue should definitely remain open, please let us know. The following information is helpful when it comes to determining if the issue should be re-opened:

  • Does the issue still reproduce on the latest release candidate? Post a comment with the version you tested.
  • If so, is there any information missing from the bug report? Post a comment with all the information required by the issue template.
  • Is there a pull request that addresses this issue? Post a comment with the PR number so we can follow up.

If you would like to work on a patch to fix the issue, contributions are very welcome! Read through the contribution guide, and feel free to hop into #react-native if you need help planning your contribution.

@BrianH2
Copy link

BrianH2 commented Jun 10, 2018

I know this is closed but for anyone else who hit this when trying to get the x and y coordinates within a ScrollView, using measureLayout as @wschurman (thanks!) suggested worked for me.

For example:

import { findNodeHandle, ScrollView, View } from 'react-native'

...

this.VIEW_REF.measureLayout(
  findNodeHandle(this.SCROLLVIEW_REF),
  function(x, y) {
    console.log(x, y);
  }, 
  function(error) {
    console.log(error);
  }
);

...

render() {
  return (
    <ScrollView ref={ref => SCROLLVIEW_REF = ref}>
      <View ref={ref => VIEW_REF = ref}>
        ...
      </View>
    </ScrollView>
  );
}

@andriichernenko
Copy link

andriichernenko commented Jun 13, 2018

Still hitting this issue when using measureInWindow() with React Native 0.54.2.

zousandian added a commit to zousandian/rn-lazyload that referenced this issue Jul 22, 2018
@facebook facebook locked as resolved and limited conversation to collaborators Aug 31, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Aug 31, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Ran Commands One of our bots successfully processed a command. Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests