【问题标题】:React Native - measure component when props recievedReact Native - 在收到道具时测量组件
【发布时间】:2018-01-10 08:04:20
【问题描述】:

我有一个 ScrollView 作为我的视图的根。在其中,我展示了一堆 Text 组件。每个组件都有自己的“参考”,因此它们是可访问的。 现在,我传递了一个带有数字的道具,该数字告诉我应该滚动到哪个文本。所以我需要先测量它。我尝试了这四种方法,但它们中的每一种都只给了我未定义的值。 有什么想法吗?

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);
 }

【问题讨论】:

  • 您确定chapterRef 指向有效组件吗?您应该避免将字符串文字作为参考。它们已被弃用。
  • 是的,这是我检查过的东西,我确信这个参考是好的,并且组件参考是有效的。我知道字符串不是最好的,但是一旦我解决了这个问题,我会在稍后更新它。事实证明,测量滚动视图中的任何内容在 RN 中都是一件令人头疼的事情......

标签: javascript react-native react-navigation


【解决方案1】:

请看下面的示例

假设你的 scrollView 的每个项目都有不同的大小(否则会更容易):

  • 创建一个接收每个项目高度的数组。例如在组件的构造函数中。默认为空。
  • 使用 onLayout 属性获取滚动视图每个项目的高度(您也可以获取宽度和屏幕上的确切 x、y 位置)。 onLayout 在安装和布局更改时调用:https://facebook.github.io/react-native/docs/view.html#onlayout
  • 在您的回调函数(您调用 onLayout 的那个)中,将此高度与项目的索引一起存储。例如,你会得到类似的东西:this.widthsTab[0] = 312
  • 然后,您只需通过 widthsTab 即可准确了解元素所在的位置并滚动到该确切位置。
  • 您还可以移除屏幕高度的一半,以确保您的元素位于屏幕中间。

如果不是很清楚,我很抱歉,但我相信你会明白的。我会尽快添加一个示例。

编辑:

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>
    );
  }
}

数组的索引可能会减一,具体取决于您是从 0 计数还是从 1 计数。请随意使用 +/-1 进行调整。 另外,我删除了当前项目宽度的一半,因为我想在它的中间滚动,但同样,如果你想滚动到开头或这个项目或其他东西,请随意更改。

【讨论】:

  • 是的,我已经研究这个主题几个小时了,看起来你描述的方式是唯一可能的方式。使用等高的行确实很容易,因为我可以使用 FlatList 和它的 goToIndex 方法。感谢您的出色回答。我现在应该可以更进一步了。
猜你喜欢
  • 2018-05-23
  • 2018-06-03
  • 2015-04-25
  • 1970-01-01
  • 2021-03-09
  • 2020-09-15
  • 2017-05-10
  • 2020-05-01
  • 2018-05-08
相关资源
最近更新 更多