amit amit - 3 months ago 47
React JSX Question

ScrollView child element get offset

I am creating a horizontal

ScrollView
navigation bar which needs to have the selected element at the center. Is there a way I can get the position offset of the selected item onPress. This is the code I am working with. onPress of TouchableOpacity should get the position offset of the element.
onLayout
wouldn't work here because it only fires the event on layout changes. Any help would be appreciated.

render() {
return (<View style={styles.footerCtr}>
<ScrollView ref="categoryScrollView" horizontal showsHorizontalScrollIndicator={false}>
{this.props.categories.map((cat, index) => {
const catIndex = index;
const catName = cat.nativename;

return (
<View style={catIndex === this.state.selCatIndex ? [styles.catCtr, styles.catSelected] : styles.catCtr} key={catIndex}>
<TouchableOpacity onPress={this.changeCategory.bind(this, catIndex)}>
<Text style={catIndex === this.state.selCatIndex ? [styles.category, styles.catSelText] : styles.category}
>{capitalize(catName)}</Text>
</TouchableOpacity>
</View>
);
})}
</ScrollView>
</View>);
}

Answer

There are two ways you can do this.

  1. Use onLayout on every element. And store the x and y co-ordinates that onLayout gives in the state. Also use an onScroll listener to store current scroll position. And now in the onPress handler onPress, calculate an adjusted x co-ordinate to bring it to the centre based on device dimensions and current scroll position. Then use scrollTo method of ScrollView to scroll to that position.
    https://facebook.github.io/react-native/docs/scrollview.html#methods
  2. The NativeEvent field of OnPress event also gives x and y co-ordinates of the touch event. Your onPress event will have to accept the event as argument. You can again calculate an adjusted x co-ordinate to bring it to the centre based on device dimensions and current scroll position. Then use scrollTo method of ScrollView to scroll to that position.

But the NativeEvent will only give the co-ordinate of the touch event. And not the starting of the element. You will most probably have to use method number one.

Comments