简体   繁体   中英

React Native - measure component when props recieved

I have a ScrollView as a root of my view. Inside of it I'm showing a bunch of Text components. Each component have it's own 'ref' so they're accesible. Now, I'm passing a prop with a number and that number tells me to which Text I should scroll to. So I need to measure it first. I tried these four approaches but each of them is giving me undefined values only. Any ideas anyone?

 componentWillReceiveProps(nextProps) { //this is a reference to my 'Text' component const chapterNo = nextProps.navigation.state.params.chapter; const chapterRef = this.refs["chapter" + chapterNo]; //method 1: var RCTUIManager = require('NativeModules').UIManager; var handle = ReactNative.findNodeHandle(chapterRef); RCTUIManager.measure(handle, (x, y, width, height, pageX, pageY) => { console.log(x, y, width, height); }); //method 2: NativeMethodsMixin.measure.call(chapterRef, (x, y, width, height) => { console.log(x, y, width, height); }); //method 3: chapterRef.measure((ox, oy, width, height, px, py) => { console.log(ox, oy, width, height); }); //method 4 (same as 3 but with setTimout): setTimeout(() => { chapterRef.measure((ox, oy, width, height, px, py) => { console.log(ox, oy, width, height); }); }, 0); } 

See an example bellow

Assuming each item of your scrollView has a different size (otherwise it's even easier) :

  • Create an array that will receive each item's height. For example in your component's constructor. It's empty by default.
  • Use onLayout property to get the height (you can also get the width and the exact x,y position on the screen) on each item of your scrollView. onLayout is invoked on mount and layout changes : https://facebook.github.io/react-native/docs/view.html#onlayout
  • In your callback function (the one you call onLayout) store this height with the item's index. You'll get for instance something like : this.widthsTab[0] = 312
  • Then, you'll just have to go through your widthsTab to get exactly where your element is and scroll to that exact position.
  • You can also remove half of the screen height to be sure your element is in the middle of your screen.

I'm sorry if it's not perfectly clear, but I'm sure you'll get the idea. I'll add an example ASAP.

Edit:

class HorizontalNavCustomerFlow extends Component {

  state = {
    heights: [],
    totalHeight: 0,
    heightsChecked: 0,
  };

  componentDidUpdate() {
    const { currentParagraph } = this.props; // Id of the paragraph you want to scroll to
    // Compute current item position and scroll when all item heights are computed
    if (this.state.widthsChecked === HOW_MANY_ITEMS_YOU_HAVE) { // use for example .lenght if you have an array
      let yposition = 0;
      const screenHeight = Dimensions.get('window').height;
      for (let i = 0; i <= currentParagraph; i++) {
        yposition += this.state.heights[i];
      }
      // Removing half of current element
      yposition -= this.state.heights[currentParagraph] / 2;
      // And half of screen's height
      yposition -= screenHeight / 2;
      // Last elements
      if (yposition > (this.state.totalWidth - screenWidth)) {
        yposition = this.state.totalHeight - screenHeight;
      }
      // Scroll
      if (yposition > 0) this.refs.MainScrollView.scrollTo({ y: yposition, animated: false });
    }
  }

  // Render
  render() {
    return (
      <View>
        <ScrollView
          ref='MainScrollView'
          showsVerticalScrollIndicator={false}
        >

          // ... Your items
          <View
            onLayout={(object) => {
              const { height } = object.nativeEvent.layout;
              const newState = this.state;
              newState.heights[index] = width;
              newState.heightsChecked = this.state.heightsChecked + 1;
              newState.totalHeight = this.state.totalHeight + height;
              this.setState(newState);
            }}
          >
            <Text>...</Text>
          </View>

        </ScrollView>
      </View>
    );
  }
}

Array's index might me off by one, depending if you count from 0 or 1. Feel free to adjust with +/-1. Also, I remove half of current item's width because I wanted to scroll right on the middle of it, but again, feel free to change if you want to scroll to the beginning or this item or something else.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM