-
Notifications
You must be signed in to change notification settings - Fork 24.3k
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
How to get ref's style or width? #953
Comments
I'm interested in this as well. This is tightly related to #494 |
@gabro @leecade - this is possible with the for example: 'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity,
} = React;
var TestIt = React.createClass({
measureWelcome() {
this.refs.welcome.measure(this.logWelcomeLayout);
},
logWelcomeLayout(ox, oy, width, height, px, py) {
console.log("ox: " + ox);
console.log("oy: " + oy);
console.log("width: " + width);
console.log("height: " + height);
console.log("px: " + px);
console.log("py: " + py);
},
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome} ref="welcome">
Welcome to React Native!
</Text>
<TouchableOpacity onPress={this.measureWelcome}>
<Text>Measure it</Text>
</TouchableOpacity>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('TestIt', () => TestIt); The result of clicking the button:
You may also be interested in
|
See also #977 where I get an element's |
Thank you @brentvatne, that really helps! I tried in |
cc @vjeux |
Ok, I managed to achieve my goal by measuring the view asynchronously (with a
then I use Still feels like a hack though... |
What you've done is currently the best way to do it. It's far from being ideal but works well enough that we were able to solve all the problems we've thrown at it so far. There's definitely a better abstraction that exists somewhere. |
Fair enough, thank you for the clarification @vjeux ;) |
Thanks for the update @gabro, glad it worked out for you |
We've had a couple ideas here but no time to implement them. One idea was to predeclare what you want to measure, then native would populate the value after computing layout so you can access it synchronously in React. The other idea (which also has other benefits), is to have JS make an explicit call to run the layout rather than native choosing when to do it (currently "at the end"). This would let us sequence the measure calls after the layout calls so you don't have to do the setTimeout in componentDidMount to get the right data. |
If anyone wants to make either of these changes, let me know :) |
@sahrens - what kind of api did you have in mind for predeclaring what you want to measure? |
Haven't really thought through the details yet, but on the fly: I think it would be ideal to bake it into the react core and build it in such a way that it would also work in web with DOM measure APIs, utilized via a prop on the component you want to measure (maybe pass it a function that is invoked with the new measure values, a la the new functional refs? Maybe like <View onLayoutChange={dims => this._dims = dims} /> Or <View onLayoutChange={dims => this.setState({dims})} /> The advantage here is that you don't have to wait for a ref Another option is as an explicit subscription: <View ref={ref => ref.subscribeToLayout(dims => this.setState({dims}))}} /> Then implement subscribeToLayout in NativeMethodsMixin to register the reactTag with native, which would then either emit one layout event for all registered views which JS infra would then de-multiplex to the right callbacks per reactTag/nodeHandle. It might make sense to build the first API (does anyone prefer the second?), but in a way more like the second behind the scenes rather than emitting separate events for every view, like we do for normal onChange events - not sure if that would be a pre-mature optimization, but seems like batching all the updates from one layout run into one event would be good.
|
@gabro I've tried to measure the root view with the code you posted above but no avail: class MainComponent extends Component {
componentDidMount() {
// https://github.com/facebook/react-native/issues/953
setTimeout(this.measureMainComponent);
}
measureMainComponent() {
this.refs.rootView.measure((ox, oy, width, height) => {
this.setState({rootViewHeight: height});
});
}
render() {
return (
<View ref='rootView'/>
);
}
} What am I doing wrong? |
@fatuhoku - you need to bind the fn you pass in to setTimeout to the component:
or
|
@brentvatne Thanks binding seemed to work. |
Also note we now have onLayout implemented, so you can use that in some cases. |
mark |
How can we get the x, y coordinate of a view according to the screen without using ref. If anyone knows please suggest me it is highly needed to me. |
@brentvatne I'm trying to use measure in ES6 (I'm still a bit new to it) syntax but mixins ( like the NativeMethodsMixin required for your example ) don't seem to be an option on es6. Do you happen to know an alternative? |
@PaulAndreRada It's bit uglier, but:
is working for me. |
The suggestion to use |
I want to get the
offsetWidth
ofrefs.view
, thanksThe text was updated successfully, but these errors were encountered: