RCTUIManager.measure is not working on Android. Trying this.refs.myRef.measure() doesn't give any results either.
import { findNodeHandle } from 'react-native';
const RCTUIManager = require('NativeModules').UIManager;
RCTUIManager.measure(findNodeHandle(this.refs.myRef), (x, y, width, height, pageX, pageY) => {
// Returns valid values on iOS but undefined on Android
});
Can you show me your view with the ref? I suspect you have the issue I've previously opened in https://github.com/facebook/react-native/issues/9382
Adding style={{opacity: 1}} did the trick. Thanks a lot!
Referring to your comment in #9382, what exactly do you mean by collapsable property?
Now I always force it to be created with collapsable property.
Although an annoyance, should I just follow your lead and close out this issue?
So style={{opacity: 1}} is what I used until I understood the issue.
Collapsable property is explained in https://facebook.github.io/react-native/docs/view.html#collapsable
Views that are only used to layout their children or otherwise don't draw anything may be automatically removed from the native hierarchy as an optimization. Set this property to false to disable this optimization and ensure that this View exists in the native view hierarchy.
However, some of UIManager functions such as measure expect to find a native view; and when it can't it returns undefined values instead of throwing an error. Really it would be better to throw an error. React unfortunately is not intelligent to know you would be measuring the view in the first place.
Putting an explicit style is one way to disable the optimization; because now the view has to be created with special drawing properties. But the real fix is putting collapsable={false} on the view you will be measuring to disable the optimization by the documentation.
Makes sense. Thank you @hey99xx!
Having the same issue with Views that are rendered within ListView. For the visible first rows, RCTUIManager.measure receives valid data on Android. But on the invisible rows every value is undefined.
On IOS everything works fine and es expected. Running RN 0.42.
I also tried out style={{opacity: 1}} and collapsable={false}. Is doesn't matter if i pass those properties and styles or not.
@itinance If you post your render method I can help you out.
Thx @hey99xx , any ideas?
return (
<View ref="container"
collapsable={false}
style={s.container}
onLayout={this.onLayout}
>
<TouchableWithoutFeedback
onPress={this.onPress}
onLongPress={this.onLongPress}
accessibilityTraits="text"
collapsable={false}
>
<View style={s.row}>
{isMe ? null : (
<UserAvatar size={48} name={user.name} defaultName="?" src={user.avatar} style={s.avatar} />
) }
<View style={[s.content, isMe ? s.contentMe : null]}>
<View style={[s.meta, isMe ? s.metaMe : null]}>
<SemiBoldText style={s.metaText}>{isMe ? 'Me' : user.name}</SemiBoldText>
<LightText style={s.metaText}>{sent.format('ddd DD/MM/YYYY h:mm a')}</LightText>
</View>
</View>
</View>
</TouchableWithoutFeedback>
</View>
)
The "container" node in the Stylesheet contains also "opacity:1"
But on the invisible rows every value is undefined.
Is it possible that your list view is getting clipped before you start scrolling down? Maybe on iOS you have rendered the entire list view in the first render, while on Android that's not the case.
Can you try removeClippedSubviews={false} on your list view or its rows? Not sure if collapsable prop is applicable to TouchableWithoutFeedback btw.
Yes, removeClippedSubviews={false} fixed it. Thank you @hey99xx !
@itinance You should realize that removeClippedSubviews is a performance optimization, which you are now disabling. Related documentation:
A performance optimization for improving scroll perf of large lists, used in conjunction with overflow: 'hidden' on the row containers. This is enabled by default.
Although I am glad you are unblocked, I suggest you find a different solution to measure your views after scroll. Maybe onChangeVisibleRows can work.
Thank you very much for the hint, @hey99xx. I will look at it and try it out.
Hey @hey99xx , onChangeVisibleRows works really fine and fits all our needs. At least on iOS. On Android this event is never fired unfortunately. There was an open Pullrequest since 14 Januar (!) in the pipeline, that was closed 14 days ago without any merge "as ListView is deprecated" 👎 👎 👎
@itinance That's a shame. I was not aware it wouldn't get further bug fixes. You can look at if the new alternative FlatList has a way to do the same thing, possible through onViewableItemsChanged. I never used FlatList so I wouldn't be able to help you there. Good luck!
Also, unless you have infinite scrolling and/or very long lists with lots of images (basically heavy-weight rendering needs) I wouldn't worry too much about clipping views.
Just FYI, @hey99xx : the onViewableItemsChanged-Event of VirtualizedList/FlatList works fine unless one use react-native-infinite-scrollview, which is base component of gifted-chat.
@hey99xx hi, thanks for your answer.
I encouter the same problem on android, besides removeClippedSubviews = {false}, we can't stand the performance problem。
do you have other solutions?
sorcery!!!
style={{opacity:1 }} works like charms!!! thanks.
Most helpful comment
So
style={{opacity: 1}}is what I used until I understood the issue.Collapsable property is explained in https://facebook.github.io/react-native/docs/view.html#collapsable
However, some of UIManager functions such as
measureexpect to find a native view; and when it can't it returnsundefinedvalues instead of throwing an error. Really it would be better to throw an error. React unfortunately is not intelligent to know you would be measuring the view in the first place.Putting an explicit style is one way to disable the optimization; because now the view has to be created with special drawing properties. But the real fix is putting
collapsable={false}on the view you will be measuring to disable the optimization by the documentation.