[Android] measure not returning values unless element has onLayout property
oblador opened this issue · comments
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.
@oblador what happens if, instead of logging arguments
, you log ox
, oy
etc.?
@foghina: they log as undefined
, logging arguments
is just shorter to write.
@foghina: in case you don't know of arguments
: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments
@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);
});
});
@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.
@ide that does not explain why it works on iOS :-/
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
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 haven't tried, but don't really understand why it would make a difference. handleSomething
is supposed to be a Touchable* callback.
Yeah you're probably right.
I'm also experiencing this. Along with onLayout
, I've found that setting renderToHardwareTextureAndroid={true}
on the view also makes measure return values.
@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
I have same problem and can confirm that using onLayout
or collapsable={false}
helps
@facebook-github-bot close
@chirag04 tells me to close this issue. If you think it should still be opened let us know why.
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.
I am having trouble with this on iOS as well.
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?
@chirag04 you closed this but it's actually not resolved.
- There are no docs
- 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.
I can confirm the bug is still here
Also still seeing this issue, will report back with any findings.
this bug still exists
@zoharlevin @MattFoley @julien-rodrigues Do you guys see this even after setting collapsable:false
on your view?
confirm that [v0.35.0]
Can be closed. collapsable: false
fixes that one, just ran into it.
I still see the issue of y coming through as 0 for Android, even after setting collapsable={false}
on the View. Again, working fine in iOS.
@JAStanton I also tried setting collapsable={false}
on the ScrollView up the tree, but that still did not help.
@grabbou I have a situation that is not resolved with collapsable
.
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
setting collapsable={false}
on a View
solved this problem for me. I'm on 0.39.2
I was still experiencing the issue with collapsable={false}.
What fixed it for me was adding onLayout={() => {}} instead.
Using measureLayout
(relative to specific node) seemed to solve this for me.
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.
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?
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.
@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.
@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?
@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"]];
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.
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>
);
}
Still hitting this issue when using measureInWindow()
with React Native 0.54.2.